]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.6-pom-ng-20040518.patch
- obsolete
[packages/kernel.git] / 2.6.6-pom-ng-20040518.patch
1   Netfilter SNAP 20040518
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
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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter.h linux-2.6.6/include/linux/netfilter.h
56 --- linux-2.6.6.org/include/linux/netfilter.h   2004-05-10 04:32:37.000000000 +0200
57 +++ linux-2.6.6/include/linux/netfilter.h       2004-05-18 12:39:23.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_helpers.h linux-2.6.6/include/linux/netfilter_helpers.h
120 --- linux-2.6.6.org/include/linux/netfilter_helpers.h   1970-01-01 01:00:00.000000000 +0100
121 +++ linux-2.6.6/include/linux/netfilter_helpers.h       2004-05-18 12:40:21.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack.h
257 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-05-10 04:33:20.000000000 +0200
258 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack.h     2004-05-18 12:40:50.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_h323.h
320 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h    1970-01-01 01:00:00.000000000 +0100
321 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_h323.h        2004-05-18 12:39:18.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_mms.h
355 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h     1970-01-01 01:00:00.000000000 +0100
356 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-05-18 12:39:36.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
390 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h  1970-01-01 01:00:00.000000000 +0100
391 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_quake3.h      2004-05-18 12:40:06.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
415 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h     1970-01-01 01:00:00.000000000 +0100
416 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-05-18 12:40:16.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
454 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h    1970-01-01 01:00:00.000000000 +0100
455 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h        2004-05-18 12:40:21.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
526 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h    1970-01-01 01:00:00.000000000 +0100
527 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_sctp.h        2004-05-18 12:40:23.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_talk.h
555 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h    1970-01-01 01:00:00.000000000 +0100
556 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_talk.h        2004-05-18 12:40:50.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
711 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h   2004-05-10 04:32:54.000000000 +0200
712 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_conntrack_tuple.h       2004-05-18 12:40:23.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.6/include/linux/netfilter_ipv4/ip_pool.h
734 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_pool.h      1970-01-01 01:00:00.000000000 +0100
735 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_pool.h  2004-05-18 12:36:48.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 --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.6/include/linux/netfilter_ipv4/ip_tables.h
802 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ip_tables.h    2004-05-10 04:32:37.000000000 +0200
803 +++ linux-2.6.6/include/linux/netfilter_ipv4/ip_tables.h        2004-05-18 12:39:16.000000000 +0200
804 @@ -104,7 +104,8 @@
805  
806  /* Values for "flag" field in struct ipt_ip (general ip structure). */
807  #define IPT_F_FRAG             0x01    /* Set if rule is a fragment rule */
808 -#define IPT_F_MASK             0x01    /* All possible flag bits mask. */
809 +#define IPT_F_GOTO             0x02    /* Set if jump is a goto */
810 +#define IPT_F_MASK             0x03    /* All possible flag bits mask. */
811  
812  /* Values for "inv" field in struct ipt_ip. */
813  #define IPT_INV_VIA_IN         0x01    /* Invert the sense of IN IFACE. */
814 @@ -134,6 +135,12 @@
815         /* Back pointer */
816         unsigned int comefrom;
817  
818 +       /* Name of the chain */
819 +       char *chainname;
820 +       
821 +       /* Rule number in the chain. */
822 +       u_int32_t rulenum;
823 +
824         /* Packet and byte counters. */
825         struct ipt_counters counters;
826  
827 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_CONNMARK.h
828 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
829 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_CONNMARK.h     2004-05-18 12:38:02.000000000 +0200
830 @@ -0,0 +1,25 @@
831 +#ifndef _IPT_CONNMARK_H_target
832 +#define _IPT_CONNMARK_H_target
833 +
834 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
835 + * by Henrik Nordstrom <hno@marasystems.com>
836 + *
837 + * This program is free software; you can redistribute it and/or modify
838 + * it under the terms of the GNU General Public License as published by
839 + * the Free Software Foundation; either version 2 of the License, or
840 + * (at your option) any later version.
841 + */
842 +
843 +enum {
844 +       IPT_CONNMARK_SET = 0,
845 +       IPT_CONNMARK_SAVE,
846 +       IPT_CONNMARK_RESTORE
847 +};
848 +
849 +struct ipt_connmark_target_info {
850 +       unsigned long mark;
851 +       unsigned long mask;
852 +       u_int8_t mode;
853 +};
854 +
855 +#endif /*_IPT_CONNMARK_H_target*/
856 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_IPMARK.h
857 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_IPMARK.h   1970-01-01 01:00:00.000000000 +0100
858 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_IPMARK.h       2004-05-18 12:38:15.000000000 +0200
859 @@ -0,0 +1,13 @@
860 +#ifndef _IPT_IPMARK_H_target
861 +#define _IPT_IPMARK_H_target
862 +
863 +struct ipt_ipmark_target_info {
864 +       unsigned long andmask;
865 +       unsigned long ormask;
866 +       unsigned int addr;
867 +};
868 +
869 +#define IPT_IPMARK_SRC    0
870 +#define IPT_IPMARK_DST    1
871 +
872 +#endif /*_IPT_IPMARK_H_target*/
873 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_MARK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_MARK.h
874 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_MARK.h     2004-05-10 04:32:26.000000000 +0200
875 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_MARK.h 2004-05-18 12:38:18.000000000 +0200
876 @@ -1,8 +1,15 @@
877  #ifndef _IPT_MARK_H_target
878  #define _IPT_MARK_H_target
879  
880 +enum {
881 +        IPT_MARK_SET,
882 +        IPT_MARK_AND,
883 +        IPT_MARK_OR
884 +};
885 +
886  struct ipt_mark_target_info {
887         unsigned long mark;
888 +       u_int8_t mode;
889  };
890  
891  #endif /*_IPT_MARK_H_target*/
892 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_NETLINK.h
893 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_NETLINK.h  1970-01-01 01:00:00.000000000 +0100
894 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_NETLINK.h      2004-05-18 12:36:02.000000000 +0200
895 @@ -0,0 +1,27 @@
896 +#ifndef _IPT_FWMON_H
897 +#define _IPT_FWMON_H
898 +
899 +/* Bitmask macros */
900 +#define MASK(x,y) (x & y)
901 +#define MASK_SET(x,y) x |= y
902 +#define MASK_UNSET(x,y) x &= ~y
903 +
904 +#define USE_MARK       0x00000001
905 +#define USE_DROP       0x00000002
906 +#define USE_SIZE       0x00000004
907 +
908 +struct ipt_nldata
909 +{      
910 +       unsigned int flags;
911 +       unsigned int mark;
912 +       unsigned int size;
913 +};
914 +
915 +/* Old header */
916 +struct netlink_t {
917 +       unsigned int len;
918 +       unsigned int mark;
919 +       char iface[IFNAMSIZ];
920 +};
921 +
922 +#endif /*_IPT_FWMON_H*/
923 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_ROUTE.h
924 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ROUTE.h    1970-01-01 01:00:00.000000000 +0100
925 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_ROUTE.h        2004-05-18 12:38:20.000000000 +0200
926 @@ -0,0 +1,22 @@
927 +/* Header file for iptables ipt_ROUTE target
928 + *
929 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
930 + *
931 + * This software is distributed under GNU GPL v2, 1991
932 + */
933 +#ifndef _IPT_ROUTE_H_target
934 +#define _IPT_ROUTE_H_target
935 +
936 +#define IPT_ROUTE_IFNAMSIZ 16
937 +
938 +struct ipt_route_target_info {
939 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
940 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
941 +       u_int32_t gw;                           /* IP address of gateway */
942 +       u_int8_t  flags;
943 +};
944 +
945 +/* Values for "flags" field */
946 +#define IPT_ROUTE_CONTINUE        0x01
947 +
948 +#endif /*_IPT_ROUTE_H_target*/
949 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_TCPLAG.h
950 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h   1970-01-01 01:00:00.000000000 +0100
951 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_TCPLAG.h       2004-05-18 12:38:29.000000000 +0200
952 @@ -0,0 +1,10 @@
953 +#ifndef _IPT_TCPLAG_H
954 +#define _IPT_TCPLAG_H
955 +
956 +struct ipt_tcplag
957 +{
958 +       unsigned char level;
959 +       unsigned char prefix[ 15 ];
960 +};
961 +
962 +#endif
963 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_TTL.h
964 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_TTL.h      1970-01-01 01:00:00.000000000 +0100
965 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_TTL.h  2004-05-18 12:36:09.000000000 +0200
966 @@ -0,0 +1,21 @@
967 +/* TTL modification module for IP tables
968 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
969 +
970 +#ifndef _IPT_TTL_H
971 +#define _IPT_TTL_H
972 +
973 +enum {
974 +       IPT_TTL_SET = 0,
975 +       IPT_TTL_INC,
976 +       IPT_TTL_DEC
977 +};
978 +
979 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
980 +
981 +struct ipt_TTL_info {
982 +       u_int8_t        mode;
983 +       u_int8_t        ttl;
984 +};
985 +
986 +
987 +#endif
988 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_XOR.h
989 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_XOR.h      1970-01-01 01:00:00.000000000 +0100
990 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_XOR.h  2004-05-18 12:38:34.000000000 +0200
991 @@ -0,0 +1,9 @@
992 +#ifndef _IPT_XOR_H
993 +#define _IPT_XOR_H
994 +
995 +struct ipt_XOR_info {
996 +       char            key[30];
997 +       u_int8_t        block_size;
998 +};
999 +
1000 +#endif /* _IPT_XOR_H */
1001 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_addrtype.h
1002 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
1003 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_addrtype.h     2004-05-18 12:38:44.000000000 +0200
1004 @@ -0,0 +1,11 @@
1005 +#ifndef _IPT_ADDRTYPE_H
1006 +#define _IPT_ADDRTYPE_H
1007 +
1008 +struct ipt_addrtype_info {
1009 +       u_int16_t       source;         /* source-type mask */
1010 +       u_int16_t       dest;           /* dest-type mask */
1011 +       int             invert_source;
1012 +       int             invert_dest;
1013 +};
1014 +
1015 +#endif
1016 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_connlimit.h
1017 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connlimit.h        1970-01-01 01:00:00.000000000 +0100
1018 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_connlimit.h    2004-05-18 12:36:13.000000000 +0200
1019 @@ -0,0 +1,12 @@
1020 +#ifndef _IPT_CONNLIMIT_H
1021 +#define _IPT_CONNLIMIT_H
1022 +
1023 +struct ipt_connlimit_data;
1024 +
1025 +struct ipt_connlimit_info {
1026 +       int limit;
1027 +       int inverse;
1028 +       u_int32_t mask;
1029 +       struct ipt_connlimit_data *data;
1030 +};
1031 +#endif /* _IPT_CONNLIMIT_H */
1032 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_connmark.h
1033 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
1034 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_connmark.h     2004-05-18 12:38:02.000000000 +0200
1035 @@ -0,0 +1,18 @@
1036 +#ifndef _IPT_CONNMARK_H
1037 +#define _IPT_CONNMARK_H
1038 +
1039 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
1040 + * by Henrik Nordstrom <hno@marasystems.com>
1041 + *
1042 + * This program is free software; you can redistribute it and/or modify
1043 + * it under the terms of the GNU General Public License as published by
1044 + * the Free Software Foundation; either version 2 of the License, or
1045 + * (at your option) any later version.
1046 + */
1047 +
1048 +struct ipt_connmark_info {
1049 +       unsigned long mark, mask;
1050 +       u_int8_t invert;
1051 +};
1052 +
1053 +#endif /*_IPT_CONNMARK_H*/
1054 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_dstlimit.h
1055 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
1056 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_dstlimit.h     2004-05-18 12:36:19.000000000 +0200
1057 @@ -0,0 +1,39 @@
1058 +#ifndef _IPT_DSTLIMIT_H
1059 +#define _IPT_DSTLIMIT_H
1060 +
1061 +/* timings are in milliseconds. */
1062 +#define IPT_DSTLIMIT_SCALE 10000
1063 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
1064 +   seconds, or one every 59 hours. */
1065 +
1066 +/* details of this structure hidden by the implementation */
1067 +struct ipt_dstlimit_htable;
1068 +
1069 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
1070 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
1071 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
1072 +
1073 +struct dstlimit_cfg {
1074 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
1075 +       u_int32_t avg;    /* Average secs between packets * scale */
1076 +       u_int32_t burst;  /* Period multiplier for upper limit. */
1077 +
1078 +       /* user specified */
1079 +       u_int32_t size;         /* how many buckets */
1080 +       u_int32_t max;          /* max number of entries */
1081 +       u_int32_t gc_interval;  /* gc interval */
1082 +       u_int32_t expire;       /* when do entries expire? */
1083 +};
1084 +
1085 +struct ipt_dstlimit_info {
1086 +       char name [IFNAMSIZ];           /* name */
1087 +       struct dstlimit_cfg cfg;
1088 +       struct ipt_dstlimit_htable *hinfo;
1089 +
1090 +       /* Used internally by the kernel */
1091 +       union {
1092 +               void *ptr;
1093 +               struct ipt_dstlimit_info *master;
1094 +       } u;
1095 +};
1096 +#endif /*_IPT_DSTLIMIT_H*/
1097 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_fuzzy.h
1098 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_fuzzy.h    1970-01-01 01:00:00.000000000 +0100
1099 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_fuzzy.h        2004-05-18 12:36:22.000000000 +0200
1100 @@ -0,0 +1,21 @@
1101 +#ifndef _IPT_FUZZY_H
1102 +#define _IPT_FUZZY_H
1103 +
1104 +#include <linux/param.h>
1105 +#include <linux/types.h>
1106 +
1107 +#define MAXFUZZYRATE 10000000
1108 +#define MINFUZZYRATE 3
1109 +
1110 +struct ipt_fuzzy_info {
1111 +       u_int32_t minimum_rate;
1112 +       u_int32_t maximum_rate;
1113 +       u_int32_t packets_total;
1114 +       u_int32_t bytes_total;
1115 +       u_int32_t previous_time;
1116 +       u_int32_t present_time;
1117 +       u_int32_t mean_rate;
1118 +       u_int8_t acceptance_rate;
1119 +};
1120 +
1121 +#endif /*_IPT_FUZZY_H*/
1122 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_ipv4options.h
1123 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_ipv4options.h      1970-01-01 01:00:00.000000000 +0100
1124 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_ipv4options.h  2004-05-18 12:36:29.000000000 +0200
1125 @@ -0,0 +1,21 @@
1126 +#ifndef __ipt_ipv4options_h_included__
1127 +#define __ipt_ipv4options_h_included__
1128 +
1129 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
1130 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
1131 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
1132 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
1133 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
1134 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
1135 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
1136 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
1137 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1138 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
1139 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
1140 +
1141 +struct ipt_ipv4options_info {
1142 +       u_int16_t options;
1143 +};
1144 +
1145 +
1146 +#endif /* __ipt_ipv4options_h_included__ */
1147 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_mport.h
1148 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_mport.h    1970-01-01 01:00:00.000000000 +0100
1149 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_mport.h        2004-05-18 12:36:36.000000000 +0200
1150 @@ -0,0 +1,24 @@
1151 +#ifndef _IPT_MPORT_H
1152 +#define _IPT_MPORT_H
1153 +#include <linux/netfilter_ipv4/ip_tables.h>
1154 +
1155 +#define IPT_MPORT_SOURCE (1<<0)
1156 +#define IPT_MPORT_DESTINATION (1<<1)
1157 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1158 +
1159 +#define IPT_MULTI_PORTS        15
1160 +
1161 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1162 +/* every entry in ports[] except for the last one has one bit in pflags
1163 + * associated with it. If this bit is set, the port is the first port of
1164 + * a portrange, with the next entry being the last.
1165 + * End of list is marked with pflags bit set and port=65535.
1166 + * If 14 ports are used (last one does not have a pflag), the last port
1167 + * is repeated to fill the last entry in ports[] */
1168 +struct ipt_mport
1169 +{
1170 +       u_int8_t flags:2;                       /* Type of comparison */
1171 +       u_int16_t pflags:14;                    /* Port flags */
1172 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
1173 +};
1174 +#endif /*_IPT_MPORT_H*/
1175 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_nth.h
1176 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_nth.h      1970-01-01 01:00:00.000000000 +0100
1177 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_nth.h  2004-05-18 12:36:40.000000000 +0200
1178 @@ -0,0 +1,19 @@
1179 +#ifndef _IPT_NTH_H
1180 +#define _IPT_NTH_H
1181 +
1182 +#include <linux/param.h>
1183 +#include <linux/types.h>
1184 +
1185 +#ifndef IPT_NTH_NUM_COUNTERS
1186 +#define IPT_NTH_NUM_COUNTERS 16
1187 +#endif
1188 +
1189 +struct ipt_nth_info {
1190 +       u_int8_t every;
1191 +       u_int8_t not;
1192 +       u_int8_t startat;
1193 +       u_int8_t counter;
1194 +       u_int8_t packet;
1195 +};
1196 +
1197 +#endif /*_IPT_NTH_H*/
1198 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_osf.h
1199 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_osf.h      1970-01-01 01:00:00.000000000 +0100
1200 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_osf.h  2004-05-18 12:36:46.000000000 +0200
1201 @@ -0,0 +1,148 @@
1202 +/*
1203 + * ipt_osf.h
1204 + *
1205 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1206 + *
1207 + *
1208 + * This program is free software; you can redistribute it and/or modify
1209 + * it under the terms of the GNU General Public License as published by
1210 + * the Free Software Foundation; either version 2 of the License, or
1211 + * (at your option) any later version.
1212 + *
1213 + * This program is distributed in the hope that it will be useful,
1214 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1215 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1216 + * GNU General Public License for more details.
1217 + *
1218 + * You should have received a copy of the GNU General Public License
1219 + * along with this program; if not, write to the Free Software
1220 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1221 + */
1222 +
1223 +#ifndef _IPT_OSF_H
1224 +#define _IPT_OSF_H
1225 +
1226 +#define MAXGENRELEN            32
1227 +#define MAXDETLEN              64
1228 +
1229 +#define IPT_OSF_GENRE          1
1230 +#define        IPT_OSF_SMART           2
1231 +#define IPT_OSF_LOG            4
1232 +#define IPT_OSF_NETLINK                8
1233 +
1234 +#define IPT_OSF_LOGLEVEL_ALL   0
1235 +#define IPT_OSF_LOGLEVEL_FIRST 1
1236 +
1237 +#include <linux/list.h>
1238 +
1239 +#ifndef __KERNEL__
1240 +#include <netinet/ip.h>
1241 +#include <netinet/tcp.h>
1242 +
1243 +struct list_head
1244 +{
1245 +       struct list_head *prev, *next;
1246 +};
1247 +#endif
1248 +
1249 +struct ipt_osf_info
1250 +{
1251 +       char                    genre[MAXGENRELEN];
1252 +       int                     len;
1253 +       unsigned long           flags;
1254 +       int                     loglevel;
1255 +       int                     invert; /* UNSUPPORTED */
1256 +};
1257 +
1258 +struct osf_wc
1259 +{
1260 +       char                    wc;
1261 +       unsigned long           val;
1262 +};
1263 +
1264 +/* This struct represents IANA options
1265 + * http://www.iana.org/assignments/tcp-parameters
1266 + */
1267 +struct osf_opt
1268 +{
1269 +       unsigned char           kind;
1270 +       unsigned char           length;
1271 +       struct osf_wc           wc;
1272 +};
1273 +
1274 +struct osf_finger
1275 +{
1276 +       struct list_head        flist;
1277 +       struct osf_wc           wss;
1278 +       unsigned char           ttl;
1279 +       unsigned char           df;
1280 +       unsigned long           ss;
1281 +       unsigned char           genre[MAXGENRELEN];
1282 +       unsigned char           version[MAXGENRELEN], subtype[MAXGENRELEN];
1283 +       
1284 +       /* Not needed, but for consistency with original table from Michal Zalewski */
1285 +       unsigned char           details[MAXDETLEN]; 
1286 +
1287 +       int                     opt_num;
1288 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1289 +
1290 +};
1291 +
1292 +struct ipt_osf_nlmsg
1293 +{
1294 +       struct osf_finger       f;
1295 +       struct iphdr            ip;
1296 +       struct tcphdr           tcp;
1297 +};
1298 +
1299 +#ifdef __KERNEL__
1300 +
1301 +/* Defines for IANA option kinds */
1302 +
1303 +#define OSFOPT_EOL             0       /* End of options */
1304 +#define OSFOPT_NOP             1       /* NOP */
1305 +#define OSFOPT_MSS             2       /* Maximum segment size */
1306 +#define OSFOPT_WSO             3       /* Window scale option */
1307 +#define OSFOPT_SACKP           4       /* SACK permitted */
1308 +#define OSFOPT_SACK            5       /* SACK */
1309 +#define OSFOPT_ECHO            6       
1310 +#define OSFOPT_ECHOREPLY       7
1311 +#define OSFOPT_TS              8       /* Timestamp option */
1312 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
1313 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
1314 +/* Others are not used in current OSF */
1315 +
1316 +static struct osf_opt IANA_opts[] = 
1317 +{
1318 +       {0, 1,},
1319 +       {1, 1,},
1320 +       {2, 4,},
1321 +       {3, 3,},
1322 +       {4, 2,},
1323 +       {5, 1 ,}, /* SACK length is not defined */
1324 +       {6, 6,},
1325 +       {7, 6,},
1326 +       {8, 10,},
1327 +       {9, 2,},
1328 +       {10, 3,},
1329 +       {11, 1,}, /* CC: Suppose 1 */
1330 +       {12, 1,}, /* the same */
1331 +       {13, 1,}, /* and here too */
1332 +       {14, 3,},
1333 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1334 +       {16, 1,},
1335 +       {17, 1,},
1336 +       {18, 3,},
1337 +       {19, 18,},
1338 +       {20, 1,},
1339 +       {21, 1,},
1340 +       {22, 1,},
1341 +       {23, 1,},
1342 +       {24, 1,},
1343 +       {25, 1,},
1344 +       {26, 1,},
1345 +};
1346 +
1347 +#endif /* __KERNEL__ */
1348 +
1349 +#endif /* _IPT_OSF_H */
1350 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_policy.h
1351 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_policy.h   1970-01-01 01:00:00.000000000 +0100
1352 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_policy.h       2004-05-18 12:39:55.000000000 +0200
1353 @@ -0,0 +1,52 @@
1354 +#ifndef _IPT_POLICY_H
1355 +#define _IPT_POLICY_H
1356 +
1357 +#define POLICY_MAX_ELEM        4
1358 +
1359 +enum ipt_policy_flags
1360 +{
1361 +       POLICY_MATCH_IN         = 0x1,
1362 +       POLICY_MATCH_OUT        = 0x2,
1363 +       POLICY_MATCH_NONE       = 0x4,
1364 +       POLICY_MATCH_STRICT     = 0x8,
1365 +};
1366 +
1367 +enum ipt_policy_modes
1368 +{
1369 +       POLICY_MODE_TRANSPORT,
1370 +       POLICY_MODE_TUNNEL
1371 +};
1372 +
1373 +struct ipt_policy_spec
1374 +{
1375 +       u_int8_t        saddr:1,
1376 +                       daddr:1,
1377 +                       proto:1,
1378 +                       mode:1,
1379 +                       spi:1,
1380 +                       reqid:1;
1381 +};
1382 +
1383 +struct ipt_policy_elem
1384 +{
1385 +       u_int32_t       saddr;
1386 +       u_int32_t       smask;
1387 +       u_int32_t       daddr;
1388 +       u_int32_t       dmask;
1389 +       u_int32_t       spi;
1390 +       u_int32_t       reqid;
1391 +       u_int8_t        proto;
1392 +       u_int8_t        mode;
1393 +
1394 +       struct ipt_policy_spec  match;
1395 +       struct ipt_policy_spec  invert;
1396 +};
1397 +
1398 +struct ipt_policy_info
1399 +{
1400 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1401 +       u_int16_t flags;
1402 +       u_int16_t len;
1403 +};
1404 +
1405 +#endif /* _IPT_POLICY_H */
1406 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_pool.h
1407 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_pool.h     1970-01-01 01:00:00.000000000 +0100
1408 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_pool.h 2004-05-18 12:36:48.000000000 +0200
1409 @@ -0,0 +1,25 @@
1410 +#ifndef _IPT_POOL_H
1411 +#define _IPT_POOL_H
1412 +
1413 +#include <linux/netfilter_ipv4/ip_pool.h>
1414 +
1415 +#define IPT_POOL_INV_SRC       0x00000001
1416 +#define IPT_POOL_INV_DST       0x00000002
1417 +#define IPT_POOL_DEL_SRC       0x00000004
1418 +#define IPT_POOL_DEL_DST       0x00000008
1419 +#define IPT_POOL_INV_MOD_SRC   0x00000010
1420 +#define IPT_POOL_INV_MOD_DST   0x00000020
1421 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
1422 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
1423 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
1424 +#define IPT_POOL_MOD_DST_DROP  0x00000200
1425 +
1426 +/* match info */
1427 +struct ipt_pool_info
1428 +{
1429 +       ip_pool_t src;
1430 +       ip_pool_t dst;
1431 +       unsigned flags;
1432 +};
1433 +
1434 +#endif /*_IPT_POOL_H*/
1435 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_psd.h
1436 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_psd.h      1970-01-01 01:00:00.000000000 +0100
1437 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_psd.h  2004-05-18 12:36:55.000000000 +0200
1438 @@ -0,0 +1,40 @@
1439 +#ifndef _IPT_PSD_H
1440 +#define _IPT_PSD_H
1441 +
1442 +#include <linux/param.h>
1443 +#include <linux/types.h>
1444 +
1445 +/*
1446 + * High port numbers have a lower weight to reduce the frequency of false
1447 + * positives, such as from passive mode FTP transfers.
1448 + */
1449 +#define PORT_WEIGHT_PRIV               3
1450 +#define PORT_WEIGHT_HIGH               1
1451 +
1452 +/*
1453 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1454 + * from the same source, with no longer than DELAY ticks between ports.
1455 + */
1456 +#define SCAN_MIN_COUNT                 7
1457 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1458 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
1459 +#define SCAN_DELAY_THRESHOLD           (300) /* old usage of HZ here was erroneously and broke under uml */
1460 +
1461 +/*
1462 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1463 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1464 + * HASH_MAX source addresses per the same hash value.
1465 + */
1466 +#define LIST_SIZE                      0x100
1467 +#define HASH_LOG                       9
1468 +#define HASH_SIZE                      (1 << HASH_LOG)
1469 +#define HASH_MAX                       0x10
1470 +
1471 +struct ipt_psd_info {
1472 +       unsigned int weight_threshold;
1473 +       unsigned int delay_threshold;
1474 +       unsigned short lo_ports_weight;
1475 +       unsigned short hi_ports_weight;
1476 +};
1477 +
1478 +#endif /*_IPT_PSD_H*/
1479 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_quota.h
1480 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_quota.h    1970-01-01 01:00:00.000000000 +0100
1481 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_quota.h        2004-05-18 12:36:56.000000000 +0200
1482 @@ -0,0 +1,11 @@
1483 +#ifndef _IPT_QUOTA_H
1484 +#define _IPT_QUOTA_H
1485 +
1486 +/* print debug info in both kernel/netfilter module & iptable library */
1487 +//#define DEBUG_IPT_QUOTA
1488 +
1489 +struct ipt_quota_info {
1490 +        u_int64_t quota;
1491 +};
1492 +
1493 +#endif /*_IPT_QUOTA_H*/
1494 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_random.h
1495 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_random.h   1970-01-01 01:00:00.000000000 +0100
1496 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_random.h       2004-05-18 12:36:59.000000000 +0200
1497 @@ -0,0 +1,11 @@
1498 +#ifndef _IPT_RAND_H
1499 +#define _IPT_RAND_H
1500 +
1501 +#include <linux/param.h>
1502 +#include <linux/types.h>
1503 +
1504 +struct ipt_rand_info {
1505 +       u_int8_t average;
1506 +};
1507 +
1508 +#endif /*_IPT_RAND_H*/
1509 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_realm.h
1510 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_realm.h    1970-01-01 01:00:00.000000000 +0100
1511 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_realm.h        2004-05-18 12:37:05.000000000 +0200
1512 @@ -0,0 +1,9 @@
1513 +#ifndef _IPT_REALM_H
1514 +#define _IPT_REALM_H
1515 +
1516 +struct ipt_realm_info {
1517 +       u_int32_t id;
1518 +       u_int32_t mask;
1519 +       u_int8_t invert;
1520 +};
1521 +#endif /*_IPT_REALM_H*/
1522 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_sctp.h
1523 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_sctp.h     1970-01-01 01:00:00.000000000 +0100
1524 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_sctp.h 2004-05-18 12:37:09.000000000 +0200
1525 @@ -0,0 +1,107 @@
1526 +#ifndef _IPT_SCTP_H_
1527 +#define _IPT_SCTP_H_
1528 +
1529 +#define IPT_SCTP_SRC_PORTS             0x01
1530 +#define IPT_SCTP_DEST_PORTS            0x02
1531 +#define IPT_SCTP_CHUNK_TYPES           0x04
1532 +
1533 +#define IPT_SCTP_VALID_FLAGS           0x07
1534 +
1535 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1536 +
1537 +
1538 +struct ipt_sctp_flag_info {
1539 +       u_int8_t chunktype;
1540 +       u_int8_t flag;
1541 +       u_int8_t flag_mask;
1542 +};
1543 +
1544 +#define IPT_NUM_SCTP_FLAGS     4
1545 +
1546 +struct ipt_sctp_info {
1547 +       u_int16_t dpts[2];  /* Min, Max */
1548 +       u_int16_t spts[2];  /* Min, Max */
1549 +
1550 +       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
1551 +
1552 +#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
1553 +#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
1554 +#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
1555 +
1556 +       u_int32_t chunk_match_type;
1557 +       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1558 +       int flag_count;
1559 +
1560 +       u_int32_t flags;
1561 +       u_int32_t invflags;
1562 +};
1563 +
1564 +#define bytes(type) (sizeof(type) * 8)
1565 +
1566 +#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
1567 +       do {                                            \
1568 +               chunkmap[type / bytes(u_int32_t)] |=    \
1569 +                       1 << (type % bytes(u_int32_t)); \
1570 +       } while (0)
1571 +
1572 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
1573 +       do {                                                    \
1574 +               chunkmap[type / bytes(u_int32_t)] &=            \
1575 +                       ~(1 << (type % bytes(u_int32_t)));      \
1576 +       } while (0)
1577 +
1578 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
1579 +({                                                             \
1580 +       (chunkmap[type / bytes (u_int32_t)] &                   \
1581 +               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
1582 +})
1583 +
1584 +#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
1585 +       do {                                                    \
1586 +               int i;                                          \
1587 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1588 +                       chunkmap[i] = 0;                        \
1589 +       } while (0)
1590 +
1591 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
1592 +       do {                                                    \
1593 +               int i;                                          \
1594 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1595 +                       chunkmap[i] = ~0;                       \
1596 +       } while (0)
1597 +
1598 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
1599 +       do {                                                    \
1600 +               int i;                                          \
1601 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1602 +                       destmap[i] = srcmap[i];                 \
1603 +       } while (0)
1604 +
1605 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
1606 +({                                                     \
1607 +       int i;                                          \
1608 +       int flag = 1;                                   \
1609 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1610 +               if (chunkmap[i]) {                      \
1611 +                       flag = 0;                       \
1612 +                       break;                          \
1613 +               }                                       \
1614 +       }                                               \
1615 +        flag;                                          \
1616 +})
1617 +
1618 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
1619 +({                                                     \
1620 +       int i;                                          \
1621 +       int flag = 1;                                   \
1622 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1623 +               if (chunkmap[i] != ~0) {                \
1624 +                       flag = 0;                       \
1625 +                               break;                  \
1626 +               }                                       \
1627 +       }                                               \
1628 +        flag;                                          \
1629 +})
1630 +
1631 +#endif /* _IPT_SCTP_H_ */
1632 +
1633 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_string.h
1634 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_string.h   1970-01-01 01:00:00.000000000 +0100
1635 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_string.h       2004-05-18 12:40:41.000000000 +0200
1636 @@ -0,0 +1,21 @@
1637 +#ifndef _IPT_STRING_H
1638 +#define _IPT_STRING_H
1639 +
1640 +/* *** PERFORMANCE TWEAK ***
1641 + * Packet size and search string threshold,
1642 + * above which sublinear searches is used. */
1643 +#define IPT_STRING_HAYSTACK_THRESH     100
1644 +#define IPT_STRING_NEEDLE_THRESH       20
1645 +
1646 +#define BM_MAX_NLEN 256
1647 +#define BM_MAX_HLEN 1024
1648 +
1649 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1650 +
1651 +struct ipt_string_info {
1652 +    char string[BM_MAX_NLEN];
1653 +    u_int16_t invert;
1654 +    u_int16_t len;
1655 +};
1656 +
1657 +#endif /* _IPT_STRING_H */
1658 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_time.h
1659 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_time.h     1970-01-01 01:00:00.000000000 +0100
1660 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_time.h 2004-05-18 12:37:29.000000000 +0200
1661 @@ -0,0 +1,15 @@
1662 +#ifndef __ipt_time_h_included__
1663 +#define __ipt_time_h_included__
1664 +
1665 +
1666 +struct ipt_time_info {
1667 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
1668 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
1669 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
1670 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
1671 +       time_t    date_start;
1672 +       time_t    date_stop;
1673 +};
1674 +
1675 +
1676 +#endif /* __ipt_time_h_included__ */
1677 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.6/include/linux/netfilter_ipv4/ipt_u32.h
1678 --- linux-2.6.6.org/include/linux/netfilter_ipv4/ipt_u32.h      1970-01-01 01:00:00.000000000 +0100
1679 +++ linux-2.6.6/include/linux/netfilter_ipv4/ipt_u32.h  2004-05-18 12:37:31.000000000 +0200
1680 @@ -0,0 +1,40 @@
1681 +#ifndef _IPT_U32_H
1682 +#define _IPT_U32_H
1683 +#include <linux/netfilter_ipv4/ip_tables.h>
1684 +
1685 +enum ipt_u32_ops
1686 +{
1687 +       IPT_U32_AND,
1688 +       IPT_U32_LEFTSH,
1689 +       IPT_U32_RIGHTSH,
1690 +       IPT_U32_AT
1691 +};
1692 +
1693 +struct ipt_u32_location_element
1694 +{
1695 +       u_int32_t number;
1696 +       u_int8_t nextop;
1697 +};
1698 +struct ipt_u32_value_element
1699 +{
1700 +       u_int32_t min;
1701 +       u_int32_t max;
1702 +};
1703 +/* *** any way to allow for an arbitrary number of elements?
1704 +   for now I settle for a limit of 10 of each */
1705 +#define U32MAXSIZE 10
1706 +struct ipt_u32_test
1707 +{
1708 +       u_int8_t nnums;
1709 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
1710 +       u_int8_t nvalues;
1711 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
1712 +};
1713 +
1714 +struct ipt_u32
1715 +{
1716 +       u_int8_t ntests;
1717 +       struct ipt_u32_test tests[U32MAXSIZE+1];
1718 +};
1719 +
1720 +#endif /*_IPT_U32_H*/
1721 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv4.h linux-2.6.6/include/linux/netfilter_ipv4.h
1722 --- linux-2.6.6.org/include/linux/netfilter_ipv4.h      2004-05-10 04:33:13.000000000 +0200
1723 +++ linux-2.6.6/include/linux/netfilter_ipv4.h  2004-05-18 12:39:22.000000000 +0200
1724 @@ -7,6 +7,8 @@
1725  
1726  #include <linux/config.h>
1727  #include <linux/netfilter.h>
1728 +#include <linux/netdevice.h>
1729 +#include <net/protocol.h>
1730  
1731  /* IP Cache bits. */
1732  /* Src IP address. */
1733 @@ -85,6 +87,58 @@
1734     Returns true or false. */
1735  extern int skb_ip_make_writable(struct sk_buff **pskb,
1736                                 unsigned int writable_len);
1737 +
1738 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1739 +#include <net/route.h>
1740 +#include <net/xfrm.h>
1741 +
1742 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1743 +{
1744 +       return !skb->sp || skb->sp->decap_done;
1745 +}
1746 +
1747 +static inline int
1748 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1749 +{
1750 +       return skb->sp && !skb->sp->decap_done
1751 +              && (!ipprot || !ipprot->xfrm_prot);
1752 +}
1753 +
1754 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1755 +{
1756 +       return skb->sp && !skb->sp->decap_done
1757 +              && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1758 +}
1759 +
1760 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1761 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1762 +#else /* CONFIG_XFRM */
1763 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1764 +{
1765 +       return 1;
1766 +}
1767 +
1768 +static inline int
1769 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1770 +{
1771 +       return 0;
1772 +}
1773 +
1774 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1775 +{
1776 +       return 0;
1777 +}
1778 +
1779 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1780 +{
1781 +       return 0;
1782 +}
1783 +
1784 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1785 +{
1786 +       return 0; 
1787 +}
1788 +#endif /* CONFIG_XFRM */
1789  #endif /*__KERNEL__*/
1790  
1791  #endif /*__LINUX_IP_NETFILTER_H*/
1792 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.6/include/linux/netfilter_ipv6/ip6_tables.h
1793 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6_tables.h   2004-05-10 04:33:20.000000000 +0200
1794 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6_tables.h       2004-05-18 12:38:32.000000000 +0200
1795 @@ -140,6 +140,12 @@
1796         /* Back pointer */
1797         unsigned int comefrom;
1798  
1799 +       /* Name of the chain */
1800 +       char *chainname;
1801 +       
1802 +       /* Rule number in the chain. */
1803 +       u_int32_t rulenum;
1804 +
1805         /* Packet and byte counters. */
1806         struct ip6t_counters counters;
1807  
1808 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_HL.h
1809 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_HL.h      1970-01-01 01:00:00.000000000 +0100
1810 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_HL.h  2004-05-18 12:35:59.000000000 +0200
1811 @@ -0,0 +1,22 @@
1812 +/* Hop Limit modification module for ip6tables
1813 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1814 + * Based on HW's TTL module */
1815 +
1816 +#ifndef _IP6T_HL_H
1817 +#define _IP6T_HL_H
1818 +
1819 +enum {
1820 +       IP6T_HL_SET = 0,
1821 +       IP6T_HL_INC,
1822 +       IP6T_HL_DEC
1823 +};
1824 +
1825 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
1826 +
1827 +struct ip6t_HL_info {
1828 +       u_int8_t        mode;
1829 +       u_int8_t        hop_limit;
1830 +};
1831 +
1832 +
1833 +#endif
1834 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_REJECT.h
1835 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-05-10 04:31:58.000000000 +0200
1836 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-05-18 12:36:05.000000000 +0200
1837 @@ -2,15 +2,17 @@
1838  #define _IP6T_REJECT_H
1839  
1840  enum ip6t_reject_with {
1841 -       IP6T_ICMP_NET_UNREACHABLE,
1842 -       IP6T_ICMP_HOST_UNREACHABLE,
1843 -       IP6T_ICMP_PROT_UNREACHABLE,
1844 -       IP6T_ICMP_PORT_UNREACHABLE,
1845 -       IP6T_ICMP_ECHOREPLY
1846 +       IP6T_ICMP6_NO_ROUTE,
1847 +       IP6T_ICMP6_ADM_PROHIBITED,
1848 +       IP6T_ICMP6_NOT_NEIGHBOUR,
1849 +       IP6T_ICMP6_ADDR_UNREACH,
1850 +       IP6T_ICMP6_PORT_UNREACH,
1851 +       IP6T_ICMP6_ECHOREPLY,
1852 +       IP6T_TCP_RESET
1853  };
1854  
1855  struct ip6t_reject_info {
1856         enum ip6t_reject_with with;      /* reject type */
1857  };
1858  
1859 -#endif /*_IPT_REJECT_H*/
1860 +#endif /*_IP6T_REJECT_H*/
1861 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h
1862 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h   1970-01-01 01:00:00.000000000 +0100
1863 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h       2004-05-18 12:38:20.000000000 +0200
1864 @@ -0,0 +1,22 @@
1865 +/* Header file for iptables ip6t_ROUTE target
1866 + *
1867 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
1868 + *
1869 + * This software is distributed under GNU GPL v2, 1991
1870 + */
1871 +#ifndef _IPT_ROUTE_H_target
1872 +#define _IPT_ROUTE_H_target
1873 +
1874 +#define IP6T_ROUTE_IFNAMSIZ 16
1875 +
1876 +struct ip6t_route_target_info {
1877 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
1878 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
1879 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
1880 +       u_int8_t  flags;
1881 +};
1882 +
1883 +/* Values for "flags" field */
1884 +#define IP6T_ROUTE_CONTINUE        0x01
1885 +
1886 +#endif /*_IP6T_ROUTE_H_target*/
1887 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1888 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h   1970-01-01 01:00:00.000000000 +0100
1889 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_fuzzy.h       2004-05-18 12:36:22.000000000 +0200
1890 @@ -0,0 +1,21 @@
1891 +#ifndef _IP6T_FUZZY_H
1892 +#define _IP6T_FUZZY_H
1893 +
1894 +#include <linux/param.h>
1895 +#include <linux/types.h>
1896 +
1897 +#define MAXFUZZYRATE 10000000
1898 +#define MINFUZZYRATE 3
1899 +
1900 +struct ip6t_fuzzy_info {
1901 +       u_int32_t minimum_rate;
1902 +       u_int32_t maximum_rate;
1903 +       u_int32_t packets_total;
1904 +       u_int32_t bytes_total;
1905 +       u_int32_t previous_time;
1906 +       u_int32_t present_time;
1907 +       u_int32_t mean_rate;
1908 +       u_int8_t acceptance_rate;
1909 +};
1910 +
1911 +#endif /*_IP6T_FUZZY_H*/
1912 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_nth.h
1913 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_nth.h     1970-01-01 01:00:00.000000000 +0100
1914 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_nth.h 2004-05-18 12:36:40.000000000 +0200
1915 @@ -0,0 +1,19 @@
1916 +#ifndef _IP6T_NTH_H
1917 +#define _IP6T_NTH_H
1918 +
1919 +#include <linux/param.h>
1920 +#include <linux/types.h>
1921 +
1922 +#ifndef IP6T_NTH_NUM_COUNTERS
1923 +#define IP6T_NTH_NUM_COUNTERS 16
1924 +#endif
1925 +
1926 +struct ip6t_nth_info {
1927 +       u_int8_t every;
1928 +       u_int8_t not;
1929 +       u_int8_t startat;
1930 +       u_int8_t counter;
1931 +       u_int8_t packet;
1932 +};
1933 +
1934 +#endif /*_IP6T_NTH_H*/
1935 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_owner.h
1936 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_owner.h   2004-05-10 04:32:52.000000000 +0200
1937 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_owner.h       2004-05-18 12:39:53.000000000 +0200
1938 @@ -6,12 +6,14 @@
1939  #define IP6T_OWNER_GID 0x02
1940  #define IP6T_OWNER_PID 0x04
1941  #define IP6T_OWNER_SID 0x08
1942 +#define IP6T_OWNER_COMM 0x10
1943  
1944  struct ip6t_owner_info {
1945      uid_t uid;
1946      gid_t gid;
1947      pid_t pid;
1948      pid_t sid;
1949 +    char comm[16];
1950      u_int8_t match, invert;    /* flags */
1951  };
1952  
1953 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_policy.h
1954 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_policy.h  1970-01-01 01:00:00.000000000 +0100
1955 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_policy.h      2004-05-18 12:39:55.000000000 +0200
1956 @@ -0,0 +1,52 @@
1957 +#ifndef _IP6T_POLICY_H
1958 +#define _IP6T_POLICY_H
1959 +
1960 +#define POLICY_MAX_ELEM        4
1961 +
1962 +enum ip6t_policy_flags
1963 +{
1964 +       POLICY_MATCH_IN         = 0x1,
1965 +       POLICY_MATCH_OUT        = 0x2,
1966 +       POLICY_MATCH_NONE       = 0x4,
1967 +       POLICY_MATCH_STRICT     = 0x8,
1968 +};
1969 +
1970 +enum ip6t_policy_modes
1971 +{
1972 +       POLICY_MODE_TRANSPORT,
1973 +       POLICY_MODE_TUNNEL
1974 +};
1975 +
1976 +struct ip6t_policy_spec
1977 +{
1978 +       u_int8_t        saddr:1,
1979 +                       daddr:1,
1980 +                       proto:1,
1981 +                       mode:1,
1982 +                       spi:1,
1983 +                       reqid:1;
1984 +};
1985 +
1986 +struct ip6t_policy_elem
1987 +{
1988 +       struct in6_addr saddr;
1989 +       struct in6_addr smask;
1990 +       struct in6_addr daddr;
1991 +       struct in6_addr dmask;
1992 +       u_int32_t       spi;
1993 +       u_int32_t       reqid;
1994 +       u_int8_t        proto;
1995 +       u_int8_t        mode;
1996 +
1997 +       struct ip6t_policy_spec match;
1998 +       struct ip6t_policy_spec invert;
1999 +};
2000 +
2001 +struct ip6t_policy_info
2002 +{
2003 +       struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
2004 +       u_int16_t flags;
2005 +       u_int16_t len;
2006 +};
2007 +
2008 +#endif /* _IP6T_POLICY_H */
2009 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.6/include/linux/netfilter_ipv6/ip6t_random.h
2010 --- linux-2.6.6.org/include/linux/netfilter_ipv6/ip6t_random.h  1970-01-01 01:00:00.000000000 +0100
2011 +++ linux-2.6.6/include/linux/netfilter_ipv6/ip6t_random.h      2004-05-18 12:36:59.000000000 +0200
2012 @@ -0,0 +1,11 @@
2013 +#ifndef _IP6T_RAND_H
2014 +#define _IP6T_RAND_H
2015 +
2016 +#include <linux/param.h>
2017 +#include <linux/types.h>
2018 +
2019 +struct ip6t_rand_info {
2020 +       u_int8_t average;
2021 +};
2022 +
2023 +#endif /*_IP6T_RAND_H*/
2024 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/netfilter_mime.h linux-2.6.6/include/linux/netfilter_mime.h
2025 --- linux-2.6.6.org/include/linux/netfilter_mime.h      1970-01-01 01:00:00.000000000 +0100
2026 +++ linux-2.6.6/include/linux/netfilter_mime.h  2004-05-18 12:40:21.000000000 +0200
2027 @@ -0,0 +1,89 @@
2028 +/*
2029 + * MIME functions for netfilter modules.  This file provides implementations
2030 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
2031 + * HTTP, RTSP, SIP, etc.
2032 + *
2033 + * gcc will warn for defined but unused functions, so we only include the
2034 + * functions requested.  The following macros are used:
2035 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
2036 + */
2037 +#ifndef _NETFILTER_MIME_H
2038 +#define _NETFILTER_MIME_H
2039 +
2040 +/* Only include these functions for kernel code. */
2041 +#ifdef __KERNEL__
2042 +
2043 +#include <linux/ctype.h>
2044 +
2045 +/*
2046 + * Given a buffer and length, advance to the next line and mark the current
2047 + * line.  If the current line is empty, *plinelen will be set to zero.  If
2048 + * not, it will be set to the actual line length (including CRLF).
2049 + *
2050 + * 'line' in this context means logical line (includes LWS continuations).
2051 + * Returns 1 on success, 0 on failure.
2052 + */
2053 +#ifdef NF_NEED_MIME_NEXTLINE
2054 +static int
2055 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2056 +{
2057 +    uint    off = *poff;
2058 +    uint    physlen = 0;
2059 +    int     is_first_line = 1;
2060 +
2061 +    if (off >= len)
2062 +    {
2063 +        return 0;
2064 +    }
2065 +
2066 +    do
2067 +    {
2068 +        while (p[off] != '\n')
2069 +        {
2070 +            if (len-off <= 1)
2071 +            {
2072 +                return 0;
2073 +            }
2074 +
2075 +            physlen++;
2076 +            off++;
2077 +        }
2078 +
2079 +        /* if we saw a crlf, physlen needs adjusted */
2080 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2081 +        {
2082 +            physlen--;
2083 +        }
2084 +
2085 +        /* advance past the newline */
2086 +        off++;
2087 +
2088 +        /* check for an empty line */
2089 +        if (physlen == 0)
2090 +        {
2091 +            break;
2092 +        }
2093 +
2094 +        /* check for colon on the first physical line */
2095 +        if (is_first_line)
2096 +        {
2097 +            is_first_line = 0;
2098 +            if (memchr(p+(*poff), ':', physlen) == NULL)
2099 +            {
2100 +                return 0;
2101 +            }
2102 +        }
2103 +    }
2104 +    while (p[off] == ' ' || p[off] == '\t');
2105 +
2106 +    *plineoff = *poff;
2107 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
2108 +    *poff = off;
2109 +
2110 +    return 1;
2111 +}
2112 +#endif /* NF_NEED_MIME_NEXTLINE */
2113 +
2114 +#endif /* __KERNEL__ */
2115 +
2116 +#endif /* _NETFILTER_MIME_H */
2117 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/linux/skbuff.h linux-2.6.6/include/linux/skbuff.h
2118 --- linux-2.6.6.org/include/linux/skbuff.h      2004-05-10 04:32:39.000000000 +0200
2119 +++ linux-2.6.6/include/linux/skbuff.h  2004-05-18 12:35:50.000000000 +0200
2120 @@ -1049,6 +1049,14 @@
2121         if (nfct)
2122                 atomic_inc(&nfct->master->use);
2123  }
2124 +static inline void nf_reset(struct sk_buff *skb)
2125 +{
2126 +       nf_conntrack_put(skb->nfct);
2127 +       skb->nfct = NULL;
2128 +#ifdef CONFIG_NETFILTER_DEBUG
2129 +       skb->nf_debug = 0;
2130 +#endif
2131 +}
2132  
2133  #ifdef CONFIG_BRIDGE_NETFILTER
2134  static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2135 @@ -1061,9 +1069,10 @@
2136         if (nf_bridge)
2137                 atomic_inc(&nf_bridge->use);
2138  }
2139 -#endif
2140 -
2141 -#endif
2142 +#endif /* CONFIG_BRIDGE_NETFILTER */
2143 +#else /* CONFIG_NETFILTER */
2144 +static inline void nf_reset(struct sk_buff *skb) {}
2145 +#endif /* CONFIG_NETFILTER */
2146  
2147  #endif /* __KERNEL__ */
2148  #endif /* _LINUX_SKBUFF_H */
2149 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/ip.h linux-2.6.6/include/net/ip.h
2150 --- linux-2.6.6.org/include/net/ip.h    2004-05-10 04:32:53.000000000 +0200
2151 +++ linux-2.6.6/include/net/ip.h        2004-05-18 12:39:21.000000000 +0200
2152 @@ -30,6 +30,8 @@
2153  #include <linux/netdevice.h>
2154  #include <linux/inetdevice.h>
2155  #include <linux/in_route.h>
2156 +#include <linux/netfilter.h>
2157 +#include <linux/netfilter_ipv4.h>
2158  #include <net/route.h>
2159  #include <net/arp.h>
2160  
2161 @@ -48,6 +50,7 @@
2162  #define IPSKB_TRANSLATED       2
2163  #define IPSKB_FORWARDED                4
2164  #define IPSKB_XFRM_TUNNEL_SIZE 8
2165 +#define IPSKB_XFRM_TRANSFORMED 16
2166  };
2167  
2168  struct ipcm_cookie
2169 @@ -212,6 +215,12 @@
2170                 __ip_select_ident(iph, dst, more);
2171  }
2172  
2173 +extern inline int ip_dst_output(struct sk_buff *skb)
2174 +{
2175 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2176 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2177 +}
2178 +
2179  /*
2180   *     Map a multicast IP onto multicast MAC for type ethernet.
2181   */
2182 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/protocol.h linux-2.6.6/include/net/protocol.h
2183 --- linux-2.6.6.org/include/net/protocol.h      2004-05-10 04:32:28.000000000 +0200
2184 +++ linux-2.6.6/include/net/protocol.h  2004-05-18 12:39:22.000000000 +0200
2185 @@ -39,6 +39,7 @@
2186         int                     (*handler)(struct sk_buff *skb);
2187         void                    (*err_handler)(struct sk_buff *skb, u32 info);
2188         int                     no_policy;
2189 +       int                     xfrm_prot;
2190  };
2191  
2192  #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2193 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/tcp.h linux-2.6.6/include/net/tcp.h
2194 --- linux-2.6.6.org/include/net/tcp.h   2004-05-10 04:32:01.000000000 +0200
2195 +++ linux-2.6.6/include/net/tcp.h       2004-05-18 12:39:47.000000000 +0200
2196 @@ -162,6 +162,7 @@
2197  extern void tcp_bucket_unlock(struct sock *sk);
2198  extern int tcp_port_rover;
2199  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2200 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2201  
2202  /* These are AF independent. */
2203  static __inline__ int tcp_bhashfn(__u16 lport)
2204 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/udp.h linux-2.6.6/include/net/udp.h
2205 --- linux-2.6.6.org/include/net/udp.h   2004-05-10 04:33:13.000000000 +0200
2206 +++ linux-2.6.6/include/net/udp.h       2004-05-18 12:39:47.000000000 +0200
2207 @@ -74,6 +74,8 @@
2208  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2209  extern int     udp_disconnect(struct sock *sk, int flags);
2210  
2211 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2212 +
2213  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2214  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
2215  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
2216 diff -Nur --exclude '*.orig' linux-2.6.6.org/include/net/xfrm.h linux-2.6.6/include/net/xfrm.h
2217 --- linux-2.6.6.org/include/net/xfrm.h  2004-05-10 04:33:13.000000000 +0200
2218 +++ linux-2.6.6/include/net/xfrm.h      2004-05-18 12:39:22.000000000 +0200
2219 @@ -540,6 +540,9 @@
2220  {
2221         atomic_t                refcnt;
2222         int                     len;
2223 +#ifdef CONFIG_NETFILTER
2224 +       int                     decap_done;
2225 +#endif
2226         struct sec_decap_state  x[XFRM_MAX_DEPTH];
2227  };
2228  
2229 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/core/netfilter.c linux-2.6.6/net/core/netfilter.c
2230 --- linux-2.6.6.org/net/core/netfilter.c        2004-05-10 04:32:29.000000000 +0200
2231 +++ linux-2.6.6/net/core/netfilter.c    2004-05-18 12:39:23.000000000 +0200
2232 @@ -27,6 +27,8 @@
2233  #include <linux/icmp.h>
2234  #include <net/sock.h>
2235  #include <net/route.h>
2236 +#include <net/xfrm.h>
2237 +#include <net/ip.h>
2238  #include <linux/ip.h>
2239  
2240  /* In this code, we can be waiting indefinitely for userspace to
2241 @@ -638,7 +640,6 @@
2242  #ifdef CONFIG_IP_ROUTE_FWMARK
2243                 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2244  #endif
2245 -               fl.proto = iph->protocol;
2246                 if (ip_route_output_key(&rt, &fl) != 0)
2247                         return -1;
2248  
2249 @@ -665,6 +666,20 @@
2250         if ((*pskb)->dst->error)
2251                 return -1;
2252  
2253 +#ifdef CONFIG_XFRM
2254 +       if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2255 +               struct xfrm_policy_afinfo *afinfo;
2256 +
2257 +               afinfo = xfrm_policy_get_afinfo(AF_INET);
2258 +               if (afinfo != NULL) {
2259 +                       afinfo->decode_session(*pskb, &fl);
2260 +                       xfrm_policy_put_afinfo(afinfo);
2261 +                       if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2262 +                               return -1;
2263 +               }
2264 +       }
2265 +#endif
2266 +
2267         /* Change in oif may mean change in hh_len. */
2268         hh_len = (*pskb)->dst->dev->hard_header_len;
2269         if (skb_headroom(*pskb) < hh_len) {
2270 @@ -682,6 +697,71 @@
2271         return 0;
2272  }
2273  
2274 +#ifdef CONFIG_XFRM
2275 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2276 +{
2277 +       skb->sp->decap_done = 1;
2278 +       dst_release(skb->dst);
2279 +       skb->dst = NULL;
2280 +       nf_reset(skb);
2281 +       return netif_rx(skb);
2282 +}
2283 +
2284 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2285 +{
2286 +       __skb_push(skb, skb->data - skb->nh.raw);
2287 +       /* Fix header len and checksum if last xfrm was transport mode */
2288 +       if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2289 +               skb->nh.iph->tot_len = htons(skb->len);
2290 +               ip_send_check(skb->nh.iph);
2291 +       }
2292 +       return nf_rcv_postxfrm_nonlocal(skb);
2293 +}
2294 +
2295 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2296 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2297 +#include <linux/netfilter_ipv4/ip_nat.h>
2298 +
2299 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2300 +{
2301 +       struct ip_conntrack *ct;
2302 +       struct ip_conntrack_tuple *t;
2303 +       struct ip_nat_info_manip *m;
2304 +       unsigned int i;
2305 +
2306 +       if (skb->nfct == NULL)
2307 +               return;
2308 +       ct = (struct ip_conntrack *)skb->nfct->master;
2309 +
2310 +       for (i = 0; i < ct->nat.info.num_manips; i++) {
2311 +               m = &ct->nat.info.manips[i];
2312 +               t = &ct->tuplehash[m->direction].tuple;
2313 +
2314 +               switch (m->hooknum) {
2315 +               case NF_IP_PRE_ROUTING:
2316 +                       if (m->maniptype != IP_NAT_MANIP_DST)
2317 +                               break;
2318 +                       fl->fl4_dst = t->dst.ip;
2319 +                       if (t->dst.protonum == IPPROTO_TCP ||
2320 +                           t->dst.protonum == IPPROTO_UDP)
2321 +                               fl->fl_ip_dport = t->dst.u.tcp.port;
2322 +                       break;
2323 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2324 +               case NF_IP_LOCAL_IN:
2325 +                       if (m->maniptype != IP_NAT_MANIP_SRC)
2326 +                               break;
2327 +                       fl->fl4_src = t->src.ip;
2328 +                       if (t->dst.protonum == IPPROTO_TCP ||
2329 +                           t->dst.protonum == IPPROTO_UDP)
2330 +                               fl->fl_ip_sport = t->src.u.tcp.port;
2331 +                       break;
2332 +#endif
2333 +               }
2334 +       }
2335 +}
2336 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2337 +#endif
2338 +
2339  int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2340  {
2341         struct sk_buff *nskb;
2342 @@ -839,3 +919,4 @@
2343  EXPORT_SYMBOL(nf_unregister_hook);
2344  EXPORT_SYMBOL(nf_unregister_queue_handler);
2345  EXPORT_SYMBOL(nf_unregister_sockopt);
2346 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2347 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ah4.c linux-2.6.6/net/ipv4/ah4.c
2348 --- linux-2.6.6.org/net/ipv4/ah4.c      2004-05-10 04:33:19.000000000 +0200
2349 +++ linux-2.6.6/net/ipv4/ah4.c  2004-05-18 12:39:22.000000000 +0200
2350 @@ -145,6 +145,7 @@
2351                 err = -EHOSTUNREACH;
2352                 goto error_nolock;
2353         }
2354 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2355         return NET_XMIT_BYPASS;
2356  
2357  error:
2358 @@ -343,6 +344,7 @@
2359         .handler        =       xfrm4_rcv,
2360         .err_handler    =       ah4_err,
2361         .no_policy      =       1,
2362 +       .xfrm_prot      =       1,
2363  };
2364  
2365  static int __init ah4_init(void)
2366 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/esp4.c linux-2.6.6/net/ipv4/esp4.c
2367 --- linux-2.6.6.org/net/ipv4/esp4.c     2004-05-10 04:32:39.000000000 +0200
2368 +++ linux-2.6.6/net/ipv4/esp4.c 2004-05-18 12:39:22.000000000 +0200
2369 @@ -216,6 +216,7 @@
2370                 err = -EHOSTUNREACH;
2371                 goto error_nolock;
2372         }
2373 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2374         return NET_XMIT_BYPASS;
2375  
2376  error:
2377 @@ -598,6 +599,7 @@
2378         .handler        =       xfrm4_rcv,
2379         .err_handler    =       esp4_err,
2380         .no_policy      =       1,
2381 +       .xfrm_prot      =       1,
2382  };
2383  
2384  static int __init esp4_init(void)
2385 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/igmp.c linux-2.6.6/net/ipv4/igmp.c
2386 --- linux-2.6.6.org/net/ipv4/igmp.c     2004-05-10 04:33:21.000000000 +0200
2387 +++ linux-2.6.6/net/ipv4/igmp.c 2004-05-18 12:39:21.000000000 +0200
2388 @@ -342,7 +342,7 @@
2389         pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2390  
2391         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2392 -                      dst_output);
2393 +                      ip_dst_output);
2394  }
2395  
2396  static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2397 @@ -672,7 +672,7 @@
2398         ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2399  
2400         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2401 -                      dst_output);
2402 +                      ip_dst_output);
2403  }
2404  
2405  static void igmp_gq_timer_expire(unsigned long data)
2406 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_forward.c linux-2.6.6/net/ipv4/ip_forward.c
2407 --- linux-2.6.6.org/net/ipv4/ip_forward.c       2004-05-10 04:31:58.000000000 +0200
2408 +++ linux-2.6.6/net/ipv4/ip_forward.c   2004-05-18 12:39:21.000000000 +0200
2409 @@ -51,7 +51,7 @@
2410         if (unlikely(opt->optlen))
2411                 ip_forward_options(skb);
2412  
2413 -       return dst_output(skb);
2414 +       return ip_dst_output(skb);
2415  }
2416  
2417  int ip_forward(struct sk_buff *skb)
2418 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_gre.c linux-2.6.6/net/ipv4/ip_gre.c
2419 --- linux-2.6.6.org/net/ipv4/ip_gre.c   2004-05-10 04:32:54.000000000 +0200
2420 +++ linux-2.6.6/net/ipv4/ip_gre.c       2004-05-18 12:35:50.000000000 +0200
2421 @@ -643,13 +643,7 @@
2422                 skb->dev = tunnel->dev;
2423                 dst_release(skb->dst);
2424                 skb->dst = NULL;
2425 -#ifdef CONFIG_NETFILTER
2426 -               nf_conntrack_put(skb->nfct);
2427 -               skb->nfct = NULL;
2428 -#ifdef CONFIG_NETFILTER_DEBUG
2429 -               skb->nf_debug = 0;
2430 -#endif
2431 -#endif
2432 +               nf_reset(skb);
2433                 ipgre_ecn_decapsulate(iph, skb);
2434                 netif_rx(skb);
2435                 read_unlock(&ipgre_lock);
2436 @@ -877,13 +871,7 @@
2437                 }
2438         }
2439  
2440 -#ifdef CONFIG_NETFILTER
2441 -       nf_conntrack_put(skb->nfct);
2442 -       skb->nfct = NULL;
2443 -#ifdef CONFIG_NETFILTER_DEBUG
2444 -       skb->nf_debug = 0;
2445 -#endif
2446 -#endif
2447 +       nf_reset(skb);
2448  
2449         IPTUNNEL_XMIT();
2450         tunnel->recursion--;
2451 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_input.c linux-2.6.6/net/ipv4/ip_input.c
2452 --- linux-2.6.6.org/net/ipv4/ip_input.c 2004-05-10 04:31:59.000000000 +0200
2453 +++ linux-2.6.6/net/ipv4/ip_input.c     2004-05-18 12:39:23.000000000 +0200
2454 @@ -202,18 +202,10 @@
2455  
2456  #ifdef CONFIG_NETFILTER_DEBUG
2457         nf_debug_ip_local_deliver(skb);
2458 -       skb->nf_debug = 0;
2459  #endif /*CONFIG_NETFILTER_DEBUG*/
2460  
2461         __skb_pull(skb, ihl);
2462  
2463 -#ifdef CONFIG_NETFILTER
2464 -       /* Free reference early: we don't need it any more, and it may
2465 -           hold ip_conntrack module loaded indefinitely. */
2466 -       nf_conntrack_put(skb->nfct);
2467 -       skb->nfct = NULL;
2468 -#endif /*CONFIG_NETFILTER*/
2469 -
2470          /* Point into the IP datagram, just past the header. */
2471          skb->h.raw = skb->data;
2472  
2473 @@ -228,6 +220,13 @@
2474         resubmit:
2475                 hash = protocol & (MAX_INET_PROTOS - 1);
2476                 raw_sk = sk_head(&raw_v4_htable[hash]);
2477 +               ipprot = inet_protos[hash];
2478 +               smp_read_barrier_depends();
2479 +
2480 +               if (nf_xfrm_local_done(skb, ipprot)) {
2481 +                       nf_rcv_postxfrm_local(skb);
2482 +                       goto out;
2483 +               }
2484  
2485                 /* If there maybe a raw socket we must check - if not we
2486                  * don't care less
2487 @@ -235,14 +234,15 @@
2488                 if (raw_sk)
2489                         raw_v4_input(skb, skb->nh.iph, hash);
2490  
2491 -               if ((ipprot = inet_protos[hash]) != NULL) {
2492 +               if (ipprot != NULL) {
2493                         int ret;
2494  
2495 -                       smp_read_barrier_depends();
2496 -                       if (!ipprot->no_policy &&
2497 -                           !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2498 -                               kfree_skb(skb);
2499 -                               goto out;
2500 +                       if (!ipprot->no_policy) {
2501 +                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2502 +                                       kfree_skb(skb);
2503 +                                       goto out;
2504 +                               }
2505 +                               nf_reset(skb);
2506                         }
2507                         ret = ipprot->handler(skb);
2508                         if (ret < 0) {
2509 @@ -283,8 +283,8 @@
2510                         return 0;
2511         }
2512  
2513 -       return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2514 -                      ip_local_deliver_finish);
2515 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2516 +                           ip_local_deliver_finish, nf_hook_input_cond(skb));
2517  }
2518  
2519  static inline int ip_rcv_finish(struct sk_buff *skb)
2520 @@ -301,6 +301,9 @@
2521                         goto drop; 
2522         }
2523  
2524 +       if (nf_xfrm_nonlocal_done(skb))
2525 +               return nf_rcv_postxfrm_nonlocal(skb);
2526 +
2527  #ifdef CONFIG_NET_CLS_ROUTE
2528         if (skb->dst->tclassid) {
2529                 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2530 @@ -422,8 +425,8 @@
2531                 }
2532         }
2533  
2534 -       return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2535 -                      ip_rcv_finish);
2536 +       return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2537 +                           ip_rcv_finish, nf_hook_input_cond(skb));
2538  
2539  inhdr_error:
2540         IP_INC_STATS_BH(IpInHdrErrors);
2541 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ip_output.c linux-2.6.6/net/ipv4/ip_output.c
2542 --- linux-2.6.6.org/net/ipv4/ip_output.c        2004-05-10 04:33:21.000000000 +0200
2543 +++ linux-2.6.6/net/ipv4/ip_output.c    2004-05-18 12:39:21.000000000 +0200
2544 @@ -123,6 +123,15 @@
2545         return ttl;
2546  }
2547  
2548 +#ifdef CONFIG_NETFILTER
2549 +/* out-of-line copy is only required with netfilter */
2550 +int ip_dst_output(struct sk_buff *skb)
2551 +{
2552 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2553 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2554 +}
2555 +#endif
2556 +
2557  /* 
2558   *             Add an ip header to a skbuff and send it out.
2559   *
2560 @@ -165,7 +174,7 @@
2561  
2562         /* Send it out. */
2563         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2564 -                      dst_output);
2565 +                      ip_dst_output);
2566  }
2567  
2568  static inline int ip_finish_output2(struct sk_buff *skb)
2569 @@ -283,7 +292,7 @@
2570                 return ip_finish_output(skb);
2571  }
2572  
2573 -int ip_output(struct sk_buff *skb)
2574 +static inline int ip_output2(struct sk_buff *skb)
2575  {
2576         IP_INC_STATS(IpOutRequests);
2577  
2578 @@ -294,6 +303,16 @@
2579                 return ip_finish_output(skb);
2580  }
2581  
2582 +int ip_output(struct sk_buff *skb)
2583 +{
2584 +       int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2585 +
2586 +       if (transformed)
2587 +               nf_reset(skb);
2588 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2589 +                           skb->dst->dev, ip_output2, transformed);
2590 +}
2591 +
2592  int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2593  {
2594         struct sock *sk = skb->sk;
2595 @@ -387,7 +406,7 @@
2596         skb->priority = sk->sk_priority;
2597  
2598         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2599 -                      dst_output);
2600 +                      ip_dst_output);
2601  
2602  no_route:
2603         IP_INC_STATS(IpOutNoRoutes);
2604 @@ -1177,7 +1196,7 @@
2605  
2606         /* Netfilter gets whole the not fragmented skb. */
2607         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
2608 -                     skb->dst->dev, dst_output);
2609 +                     skb->dst->dev, ip_dst_output);
2610         if (err) {
2611                 if (err > 0)
2612                         err = inet->recverr ? net_xmit_errno(err) : 0;
2613 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ipcomp.c linux-2.6.6/net/ipv4/ipcomp.c
2614 --- linux-2.6.6.org/net/ipv4/ipcomp.c   2004-05-10 04:33:13.000000000 +0200
2615 +++ linux-2.6.6/net/ipv4/ipcomp.c       2004-05-18 12:39:22.000000000 +0200
2616 @@ -231,6 +231,7 @@
2617                 err = -EHOSTUNREACH;
2618                 goto error_nolock;
2619         }
2620 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2621         err = NET_XMIT_BYPASS;
2622  
2623  out_exit:
2624 @@ -407,6 +408,7 @@
2625         .handler        =       xfrm4_rcv,
2626         .err_handler    =       ipcomp4_err,
2627         .no_policy      =       1,
2628 +       .xfrm_prot      =       1,
2629  };
2630  
2631  static int __init ipcomp4_init(void)
2632 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ipip.c linux-2.6.6/net/ipv4/ipip.c
2633 --- linux-2.6.6.org/net/ipv4/ipip.c     2004-05-10 04:33:22.000000000 +0200
2634 +++ linux-2.6.6/net/ipv4/ipip.c 2004-05-18 12:39:22.000000000 +0200
2635 @@ -478,6 +478,11 @@
2636  
2637         read_lock(&ipip_lock);
2638         if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2639 +               /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2640 +               if (nf_xfrm_local_done(skb, NULL)) {
2641 +                       nf_rcv_postxfrm_local(skb);
2642 +                       return 0;
2643 +               }
2644                 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2645                         kfree_skb(skb);
2646                         return 0;
2647 @@ -496,13 +501,7 @@
2648                 skb->dev = tunnel->dev;
2649                 dst_release(skb->dst);
2650                 skb->dst = NULL;
2651 -#ifdef CONFIG_NETFILTER
2652 -               nf_conntrack_put(skb->nfct);
2653 -               skb->nfct = NULL;
2654 -#ifdef CONFIG_NETFILTER_DEBUG
2655 -               skb->nf_debug = 0;
2656 -#endif
2657 -#endif
2658 +               nf_reset(skb);
2659                 ipip_ecn_decapsulate(iph, skb);
2660                 netif_rx(skb);
2661                 read_unlock(&ipip_lock);
2662 @@ -647,13 +646,7 @@
2663         if ((iph->ttl = tiph->ttl) == 0)
2664                 iph->ttl        =       old_iph->ttl;
2665  
2666 -#ifdef CONFIG_NETFILTER
2667 -       nf_conntrack_put(skb->nfct);
2668 -       skb->nfct = NULL;
2669 -#ifdef CONFIG_NETFILTER_DEBUG
2670 -       skb->nf_debug = 0;
2671 -#endif
2672 -#endif
2673 +       nf_reset(skb);
2674  
2675         IPTUNNEL_XMIT();
2676         tunnel->recursion--;
2677 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/ipmr.c linux-2.6.6/net/ipv4/ipmr.c
2678 --- linux-2.6.6.org/net/ipv4/ipmr.c     2004-05-10 04:32:30.000000000 +0200
2679 +++ linux-2.6.6/net/ipv4/ipmr.c 2004-05-18 12:39:21.000000000 +0200
2680 @@ -1120,7 +1120,7 @@
2681         if (unlikely(opt->optlen))
2682                 ip_forward_options(skb);
2683  
2684 -       return dst_output(skb);
2685 +       return ip_dst_output(skb);
2686  }
2687  
2688  /*
2689 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/Kconfig linux-2.6.6/net/ipv4/netfilter/Kconfig
2690 --- linux-2.6.6.org/net/ipv4/netfilter/Kconfig  2004-05-10 04:33:13.000000000 +0200
2691 +++ linux-2.6.6/net/ipv4/netfilter/Kconfig      2004-05-18 12:40:50.000000000 +0200
2692 @@ -206,6 +206,11 @@
2693  
2694           To compile it as a module, choose M here.  If unsure, say N.
2695  
2696 +config IP_NF_MATCH_UNCLEAN
2697 +       tristate  'unclean match support (EXPERIMENTAL)'
2698 +       depends on EXPERIMENTAL && IP_NF_IPTABLES
2699 +         help
2700 +
2701  config IP_NF_MATCH_TTL
2702         tristate "TTL match support"
2703         depends on IP_NF_IPTABLES
2704 @@ -603,5 +608,509 @@
2705           <file:Documentation/modules.txt>.  If unsure, say `N'.
2706           help
2707  
2708 +config IP_NF_TARGET_IPV4OPTSSTRIP
2709 +       tristate  'IPV4OPTSSTRIP target support'
2710 +       depends on IP_NF_MANGLE
2711 +       help
2712 +         This option adds an IPV4OPTSSTRIP target.
2713 +         This target allows you to strip all IP options in a packet.
2714 +        
2715 +         If you want to compile it as a module, say M here and read
2716 +         Documentation/modules.txt.  If unsure, say `N'.
2717 +
2718 +config IP_NF_TARGET_NETLINK
2719 +       tristate  'NETLINK target support'
2720 +       depends on IP_NF_FILTER
2721 +       help
2722 +         The NETLINK target allows you to recieve packets in userspace via
2723 +         the kernel firewall netlink socket. Apps such as fwmon
2724 +         (http://firestorm.geek-ware.co.uk) can then recieve and dislpay
2725 +         these packets. This option is basically a re-implementation of the
2726 +         ipchains -o option.
2727 +
2728 +config IP_NF_TARGET_TTL
2729 +       tristate  'TTL target support'
2730 +       depends on IP_NF_MANGLE
2731 +       help
2732 +         This option adds a `TTL' target, which enables the user to set
2733 +         the TTL value or increment / decrement the TTL value by a given
2734 +         amount.
2735 +       
2736 +         If you want to compile it as a module, say M here and read
2737 +         Documentation/modules.txt.  If unsure, say `N'.
2738 +
2739 +config IP_NF_MATCH_CONNLIMIT
2740 +       tristate  'Connections/IP limit match support'
2741 +       depends on IP_NF_IPTABLES
2742 +       help
2743 +         This match allows you to restrict the number of parallel TCP
2744 +         connections to a server per client IP address (or address block).
2745 +       
2746 +         If you want to compile it as a module, say M here and read
2747 +         Documentation/modules.txt.  If unsure, say `N'.
2748 +
2749 +config IP_NF_MATCH_DSTLIMIT
2750 +       tristate  'dstlimit match support'
2751 +       depends on IP_NF_IPTABLES
2752 +
2753 +config IP_NF_MATCH_FUZZY
2754 +       tristate  'fuzzy match support'
2755 +       depends on IP_NF_IPTABLES
2756 +       help
2757 +         This option adds a `fuzzy' match, which allows you to match
2758 +         packets according to a fuzzy logic based law.
2759 +       
2760 +         If you want to compile it as a module, say M here and read
2761 +         Documentation/modules.txt.  If unsure, say `N'.
2762 +
2763 +config IP_NF_MATCH_IPV4OPTIONS
2764 +       tristate  'IPV4OPTIONS match support'
2765 +       depends on IP_NF_IPTABLES
2766 +       help
2767 +         This option adds a IPV4OPTIONS match.
2768 +         It allows you to filter options like source routing,
2769 +         record route, timestamp and router-altert.
2770 +       
2771 +         If you say Y here, try iptables -m ipv4options --help for more information.
2772 +        
2773 +         If you want to compile it as a module, say M here and read
2774 +         Documentation/modules.txt.  If unsure, say `N'.
2775 +
2776 +config IP_NF_MATCH_MPORT
2777 +       tristate  'Multiple port with ranges match support'
2778 +       depends on IP_NF_IPTABLES
2779 +       help
2780 +         This is an enhanced multiport match which supports port
2781 +         ranges as well as single ports.
2782 +       
2783 +         If you want to compile it as a module, say M here and read
2784 +         Documentation/modules.txt.  If unsure, say `N'.
2785 +
2786 +config IP_NF_MATCH_NTH
2787 +       tristate  'Nth match support'
2788 +       depends on IP_NF_IPTABLES
2789 +       help
2790 +         This option adds a `Nth' match, which allow you to make
2791 +         rules that match every Nth packet.  By default there are 
2792 +         16 different counters.
2793 +       
2794 +         [options]
2795 +          --every     Nth              Match every Nth packet
2796 +         [--counter]  num              Use counter 0-15 (default:0)
2797 +         [--start]    num              Initialize the counter at the number 'num'
2798 +                                       instead of 0. Must be between 0 and Nth-1
2799 +         [--packet]   num              Match on 'num' packet. Must be between 0
2800 +                                       and Nth-1.
2801 +       
2802 +                                       If --packet is used for a counter than
2803 +                                       there must be Nth number of --packet
2804 +                                       rules, covering all values between 0 and
2805 +                                       Nth-1 inclusively.
2806 +        
2807 +         If you want to compile it as a module, say M here and read
2808 +         Documentation/modules.txt.  If unsure, say `N'.
2809 +
2810 +config IP_NF_MATCH_OSF
2811 +       tristate  'OSF match support'
2812 +       depends on IP_NF_IPTABLES
2813 +       help
2814 +       
2815 +         The idea of passive OS fingerprint matching exists for quite a long time,
2816 +         but was created as extension fo OpenBSD pf only some weeks ago.
2817 +         Original idea was lurked in some OpenBSD mailing list (thanks
2818 +         grange@open...) and than adopted for Linux netfilter in form of this code.
2819 +       
2820 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
2821 +         his excellent p0f and than changed a bit for more convenience.
2822 +       
2823 +         This module compares some data(WS, MSS, options and it's order, ttl,
2824 +         df and others) from first SYN packet (actually from packets with SYN
2825 +         bit set) with hardcoded in fingers[] table ones.
2826 +       
2827 +         If you say Y here, try iptables -m osf --help for more information.
2828 +        
2829 +         If you want to compile it as a module, say M here and read
2830 +         Documentation/modules.txt.  If unsure, say `N'.
2831 +
2832 +config IP_POOL_STATISTICS
2833 +       bool  'enable statistics on pool usage'
2834 +       depends on IP_NF_POOL!=n
2835 +       help
2836 +         This option controls whether usage gathering code is compiled into the
2837 +         ip_pool module.  Disabling statistics may be substantially faster.
2838 +
2839 +config IP_NF_POOL
2840 +       tristate  'IP address pool support'
2841 +       depends on IP_NF_IPTABLES
2842 +       help
2843 +         Pool matching lets you use bitmaps with one bit per address from some
2844 +         range of IP addresses; the match depends on whether a checked source
2845 +         or destination address has its bit set in the pool.
2846 +       
2847 +         There is also a POOL netfilter target, which can be used to set or remove
2848 +         the addresses of a packet from a pool.
2849 +       
2850 +         To define and use pools, you need userlevel utilities: a patched iptables,
2851 +         and the program ippool(8), which defines the pools and their bounds.
2852 +         The current release of pool matching is ippool-0.0.2, and can be found
2853 +         in the archives of the netfilter mailing list at
2854 +         http://lists.samba.org/netfilter/.
2855 +       
2856 +         If you want to compile it as a module, say M here and read
2857 +         Documentation/modules.txt.  If unsure, say `N'.
2858 +
2859 +config IP_NF_MATCH_PSD
2860 +       tristate  'psd match support'
2861 +       depends on IP_NF_IPTABLES
2862 +       help
2863 +         This option adds a `psd' match, which allows you to create rules in
2864 +         any iptables table wich will detect TCP and UDP port scans.
2865 +        
2866 +         If you want to compile it as a module, say M here and read
2867 +         Documentation/modules.txt.  If unsure, say `N'.
2868 +
2869 +config IP_NF_MATCH_QUOTA
2870 +       tristate  'quota match support'
2871 +       depends on IP_NF_IPTABLES
2872 +       help
2873 +         This match implements network quotas.
2874 +       
2875 +         If you want to compile it as a module, say M here and read
2876 +         Documentation/modules.txt.  If unsure, say `N'.
2877 +       
2878 +
2879 +config IP_NF_MATCH_RANDOM
2880 +       tristate  'random match support'
2881 +       depends on IP_NF_IPTABLES
2882 +       help
2883 +         This option adds a `random' match,
2884 +         which allow you to match packets randomly
2885 +         following a given probability.
2886 +        
2887 +         If you want to compile it as a module, say M here and read
2888 +         Documentation/modules.txt.  If unsure, say `N'.
2889 +
2890 +config IP_NF_MATCH_REALM
2891 +       tristate  'realm match support'
2892 +       depends on IP_NF_IPTABLES && NET_CLS_ROUTE
2893 +       help
2894 +         This option adds a `realm' match, which allows you to use the realm
2895 +         key from the routing subsytem inside iptables.
2896 +       
2897 +         This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
2898 +         in tc world.
2899 +       
2900 +         If you want to compile it as a module, say M here and read
2901 +         Documentation/modules.txt.  If unsure, say `N'.
2902 +
2903 +config IP_NF_MATCH_SCTP
2904 +       tristate  'SCTP protocol match support'
2905 +       depends on IP_NF_IPTABLES
2906 +
2907 +config IP_NF_MATCH_TIME
2908 +       tristate  'TIME match support'
2909 +       depends on IP_NF_IPTABLES
2910 +       help
2911 +         This option adds a `time' match, which allows you
2912 +         to match based on the packet arrival time/date
2913 +         (arrival time/date at the machine which netfilter is running on) or
2914 +         departure time/date (for locally generated packets).
2915 +       
2916 +         If you say Y here, try iptables -m time --help for more information.
2917 +        
2918 +         If you want to compile it as a module, say M here and read
2919 +         Documentation/modules.txt.  If unsure, say `N'.
2920 +
2921 +config IP_NF_MATCH_U32
2922 +       tristate  'U32 match support'
2923 +       depends on IP_NF_IPTABLES
2924 +       help
2925 +         U32 allows you to extract quantities of up to 4 bytes from a packet,
2926 +         AND them with specified masks, shift them by specified amounts and
2927 +         test whether the results are in any of a set of specified ranges.
2928 +         The specification of what to extract is general enough to skip over
2929 +         headers with lengths stored in the packet, as in IP or TCP header
2930 +         lengths.
2931 +       
2932 +         Details and examples are in the kernel module source.
2933 +
2934 +config IP_NF_CONNTRACK_MARK
2935 +       bool  'Connection mark tracking support'
2936 +       help
2937 +         This option enables support for connection marks, used by the
2938 +         `CONNMARK' target and `connmark' match. Similar to the mark value
2939 +         of packets, but this mark value is kept in the conntrack session
2940 +         instead of the individual packets.
2941 +       
2942 +config IP_NF_TARGET_CONNMARK
2943 +       tristate  'CONNMARK target support'
2944 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
2945 +       help
2946 +         This option adds a `CONNMARK' target, which allows one to manipulate
2947 +         the connection mark value.  Similar to the MARK target, but
2948 +         affects the connection mark value rather than the packet mark value.
2949 +       
2950 +         If you want to compile it as a module, say M here and read
2951 +         Documentation/modules.txt.  The module will be called
2952 +         ipt_CONNMARK.o.  If unsure, say `N'.
2953 +       
2954 +config IP_NF_MATCH_CONNMARK
2955 +       tristate  ' Connection mark match support'
2956 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES
2957 +       help
2958 +         This option adds a `connmark' match, which allows you to match the
2959 +         connection mark value previously set for the session by `CONNMARK'. 
2960 +       
2961 +         If you want to compile it as a module, say M here and read
2962 +         Documentation/modules.txt.  The module will be called
2963 +         ipt_connmark.o.  If unsure, say `N'.
2964 +
2965 +config IP_NF_TARGET_IPMARK
2966 +       tristate  'IPMARK target support'
2967 +       depends on IP_NF_MANGLE
2968 +       help
2969 +         This option adds a `IPMARK' target, which allows you to create rules
2970 +         in the `mangle' table which alter the netfilter mark (nfmark) field
2971 +         basing on the source or destination ip address of the packet.
2972 +         This is very useful for very fast massive mangling and marking.
2973 +       
2974 +         If you want to compile it as a module, say M here and read
2975 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
2976 +
2977 +config IP_NF_TARGET_ROUTE
2978 +       tristate  'ROUTE target support'
2979 +       depends on IP_NF_MANGLE
2980 +       help
2981 +         This option adds a `ROUTE' target, which enables you to setup unusual
2982 +         routes. For example, the ROUTE lets you route a received packet through 
2983 +         an interface or towards a host, even if the regular destination of the 
2984 +         packet is the router itself. The ROUTE target is also able to change the 
2985 +         incoming interface of a packet.
2986 +       
2987 +         The target can be or not a final target. It has to be used inside the 
2988 +         mangle table.
2989 +         
2990 +         If you want to compile it as a module, say M here and read
2991 +         Documentation/modules.txt.  The module will be called ipt_ROUTE.o.
2992 +         If unsure, say `N'.
2993 +
2994 +config IP_NF_TARGET_TARPIT
2995 +       tristate 'TARPIT target support'
2996 +       depends on IP_NF_FILTER
2997 +       help
2998 +         Adds a TARPIT target to iptables, which captures and holds
2999 +         incoming TCP connections using no local per-connection resources.
3000 +         Connections are accepted, but immediately switched to the persist
3001 +         state (0 byte window), in which the remote side stops sending data
3002 +         and asks to continue every 60-240 seconds.  Attempts to close the
3003 +         connection are ignored, forcing the remote side to time out the
3004 +         connection in 12-24 minutes.
3005 +       
3006 +         This offers similar functionality to LaBrea
3007 +         <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
3008 +         hardware or IPs.  Any TCP port that you would normally DROP or REJECT
3009 +         can instead become a tarpit.
3010 +
3011 +config IP_NF_TARGET_TCPLAG
3012 +       tristate  'TCPLAG target support'
3013 +       depends on IP_NF_IPTABLES
3014 +       help
3015 +         This option adds a `TCPLAG' target, intended for INPUT, OUTPUT and
3016 +         FORWARD chains.
3017 +       
3018 +         This target has no effect on packets but will passively monitor TCP/IP
3019 +         connections and send lag estimates to syslog. Lag estimates are
3020 +         generated by considering the time delay between SEQ and matching ACK,
3021 +         which does not map precisely to any particular network property.
3022 +         We can say that a fast network will typically give smaller lag values
3023 +         than a slow network.
3024 +       
3025 +         Safest option is to choose `M' here and compile as a module,
3026 +         the module will do nothing until activated using the `iptables' utility.
3027 +
3028 +config IP_NF_TARGET_TRACE
3029 +       tristate  'TRACE target support'
3030 +       depends on IP_NF_RAW
3031 +       help
3032 +         The TRACE target allows packets to be traced as those
3033 +         matches any subsequent rule in any table/rule. The matched
3034 +         rule and the packet is logged with the prefix
3035 +       
3036 +         TRACE: tablename/chainname/rulenum  
3037 +       
3038 +         If you want to compile it as a module, say M here and read
3039 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
3040 +
3041 +config IP_NF_TARGET_XOR
3042 +       tristate  'XOR target support'
3043 +       depends on IP_NF_MANGLE
3044 +       help
3045 +         This option adds a `XOR' target, which can encrypt TCP and 
3046 +         UDP traffic using a simple XOR encryption.
3047 +       
3048 +         If you want to compile it as a module, say M here and read
3049 +         Documentation/modules.txt.  If unsure, say `N'.
3050 +
3051 +config IP_NF_MATCH_ADDRTYPE
3052 +       tristate  'address type match support'
3053 +       depends on IP_NF_IPTABLES
3054 +       help
3055 +         This option allows you to match what routing thinks of an address,
3056 +         eg. UNICAST, LOCAL, BROADCAST, ...
3057 +       
3058 +         If you want to compile it as a module, say M here and read
3059 +         Documentation/modules.txt.  If unsure, say `N'.
3060 +
3061 +config IP_NF_EGG
3062 +       tristate  'Eggdrop bot support'
3063 +       depends on IP_NF_CONNTRACK
3064 +       help
3065 +         If you are running an eggdrop hub bot on this machine, then you
3066 +         may want to enable this feature. This enables eggdrop bots to share
3067 +         their user file to other eggdrop bots.
3068 +       
3069 +         If you want to compile it as a module, say M here and read
3070 +         Documentation/modules.txt.  If unsure, say `N'.
3071 +
3072 +config IP_NF_NAT_H323
3073 +       tristate
3074 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3075 +       default IP_NF_NAT if IP_NF_H323=y
3076 +       default m if IP_NF_H323=m
3077 +
3078 +config IP_NF_H323
3079 +       tristate  'H.323 (netmeeting) support'
3080 +       depends on IP_NF_CONNTRACK
3081 +       help
3082 +         H.323 is a standard signalling protocol used by teleconferencing
3083 +         softwares like netmeeting. With the ip_conntrack_h323 and
3084 +         the ip_nat_h323 modules you can support the protocol on a connection
3085 +         tracking/NATing firewall.
3086 +       
3087 +         If you want to compile it as a module, say 'M' here and read
3088 +         Documentation/modules.txt.  If unsure, say 'N'.
3089 +
3090 +config IP_NF_NAT_MMS
3091 +       tristate
3092 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3093 +       default IP_NF_NAT if IP_NF_MMS=y
3094 +       default m if IP_NF_MMS=m
3095 +
3096 +config IP_NF_MMS
3097 +       tristate  'MMS protocol support'
3098 +       depends on IP_NF_CONNTRACK
3099 +       help
3100 +         Tracking MMS (Microsoft Windows Media Services) connections
3101 +         could be problematic if random ports are used to send the
3102 +         streaming content. This option allows users to track streaming
3103 +         connections over random UDP or TCP ports.
3104 +       
3105 +         If you want to compile it as a module, say M here and read
3106 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
3107 +
3108 +config IP_NF_MATCH_POLICY
3109 +       tristate "IPsec policy match support"
3110 +       depends on IP_NF_IPTABLES && XFRM
3111 +       help
3112 +         Policy matching allows you to match packets based on the
3113 +         IPsec policy that was used during decapsulation/will
3114 +         be used during encapsulation.
3115 +
3116 +         To compile it as a module, choose M here.  If unsure, say N.
3117 +
3118 +config IP_NF_NAT_QUAKE3
3119 +       tristate
3120 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
3121 +       default IP_NF_NAT if IP_NF_QUAKE3=y
3122 +       default m if IP_NF_QUAKE3=m
3123 +
3124 +config IP_NF_QUAKE3
3125 +       tristate "Quake3 protocol support"
3126 +       depends on IP_NF_CONNTRACK
3127 +       help
3128 +         Quake III Arena  connection tracking helper. This module allows for a
3129 +         stricter firewall rulebase if one only allows traffic to a master
3130 +         server. Connections to Quake III server IP addresses and ports returned
3131 +         by the master server will be tracked automatically.
3132 +       
3133 +         If you want to compile it as a module, say M here and read
3134 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
3135 +
3136 +config IP_NF_RSH
3137 +       tristate  'RSH protocol support'
3138 +       depends on IP_NF_CONNTRACK
3139 +       help
3140 +         The RSH connection tracker is required if the dynamic
3141 +         stderr "Server to Client" connection is to occur during a
3142 +         normal RSH session.  This typically operates as follows;
3143 +       
3144 +           Client 0:1023 --> Server 514    (stream 1 - stdin/stdout)
3145 +           Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
3146 +       
3147 +         This connection tracker will identify new RSH sessions,
3148 +         extract the outbound session details, and notify netfilter
3149 +         of pending "related" sessions.
3150 +       
3151 +         Warning: This module could be dangerous. It is not "best
3152 +                  practice" to use RSH, use SSH in all instances.
3153 +                  (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
3154 +       
3155 +       
3156 +         If you want to compile it as a module, say M here and read
3157 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
3158 +
3159 +config IP_NF_NAT_RTSP
3160 +       tristate
3161 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3162 +       default IP_NF_NAT if IP_NF_RTSP=y
3163 +       default m if IP_NF_RTSP=m
3164 +
3165 +config IP_NF_RTSP
3166 +       tristate  ' RTSP protocol support'
3167 +       depends on IP_NF_CONNTRACK
3168 +       help
3169 +         Support the RTSP protocol.  This allows UDP transports to be setup
3170 +         properly, including RTP and RDT.
3171 +       
3172 +         If you want to compile it as a module, say 'M' here and read
3173 +         Documentation/modules.txt.  If unsure, say 'Y'.
3174 +
3175 +config IP_NF_CT_PROTO_SCTP
3176 +       tristate  'SCTP protocol connection tracking support'
3177 +       depends on IP_NF_CONNTRACK
3178 +
3179 +config IP_NF_MATCH_STRING
3180 +       tristate  'String match support'
3181 +       depends on IP_NF_IPTABLES
3182 +       help
3183 +         String matching alows you to match packets which contain a
3184 +         specified string of characters.
3185 +       
3186 +         If you want to compile it as a module, say M here and read
3187 +         Documentation/modules.txt.  If unsure, say `N'.
3188 +
3189 +config IP_NF_NAT_TALK
3190 +       tristate
3191 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3192 +       default IP_NF_NAT if IP_NF_TALK=y
3193 +       default m if IP_NF_TALK=m
3194 +
3195 +config IP_NF_TALK
3196 +       tristate  'talk protocol support'
3197 +       depends on IP_NF_CONNTRACK
3198 +       help
3199 +         The talk protocols (both otalk/talk - or talk/ntalk, to confuse
3200 +         you by the different namings about which is old or which is new :-)
3201 +         use an additional channel to setup the talk session and a separated
3202 +         data channel for the actual conversation (like in FTP). Both the 
3203 +         initiating and the setup channels are over UDP, while the data channel 
3204 +         is over TCP, on a random port. The conntrack part of this extension
3205 +         will enable you to let in/out talk sessions easily by matching these
3206 +         connections as RELATED by the state match, while the NAT part helps
3207 +         you to let talk sessions trough a NAT machine.
3208 +       
3209 +         If you want to compile it as a module, say 'M' here and read
3210 +         Documentation/modules.txt.  If unsure, say 'N'.
3211 +
3212  endmenu
3213  
3214 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/Makefile linux-2.6.6/net/ipv4/netfilter/Makefile
3215 --- linux-2.6.6.org/net/ipv4/netfilter/Makefile 2004-05-10 04:32:26.000000000 +0200
3216 +++ linux-2.6.6/net/ipv4/netfilter/Makefile     2004-05-18 12:40:50.000000000 +0200
3217 @@ -19,10 +19,49 @@
3218  # connection tracking
3219  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
3220  
3221 +# talk protocol support
3222 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
3223 +ifdef CONFIG_IP_NF_TALK
3224 +       export-objs += ip_conntrack_talk.o
3225 +endif
3226 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
3227 +
3228 +
3229 +# SCTP protocol connection tracking
3230 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
3231
3232 +# H.323 support
3233 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
3234 +ifdef CONFIG_IP_NF_H323
3235 +       export-objs += ip_conntrack_h323.o
3236 +endif
3237 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
3238 +
3239 +
3240  # connection tracking helpers
3241 +
3242 +# rtsp protocol support
3243 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
3244 +ifdef CONFIG_IP_NF_NAT_RTSP
3245 +       export-objs += ip_conntrack_rtsp.o
3246 +endif
3247 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
3248 +
3249 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
3250 +ifdef CONFIG_IP_NF_NAT_QUAKE3
3251 +       export-objs += ip_conntrack_quake3.o
3252 +endif
3253 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
3254 +ifdef CONFIG_IP_NF_MMS
3255 +       export-objs += ip_conntrack_mms.o
3256 +endif
3257  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
3258  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
3259  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
3260 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
3261 +
3262 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
3263 +
3264  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
3265  
3266  # NAT helpers 
3267 @@ -30,6 +69,8 @@
3268  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
3269  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
3270  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
3271 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
3272 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
3273  
3274  # generic IP tables 
3275  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
3276 @@ -43,15 +84,39 @@
3277  # matches
3278  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
3279  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
3280 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
3281 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
3282 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
3283  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
3284 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
3285  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
3286  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
3287  
3288  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
3289  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
3290 +
3291 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
3292 +
3293  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
3294  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
3295  
3296 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
3297 +
3298 +
3299 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
3300 +
3301 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
3302 +
3303 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
3304 +
3305 +
3306 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
3307 +
3308 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
3309 +
3310 +
3311 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
3312 +
3313  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
3314  
3315  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
3316 @@ -60,28 +125,48 @@
3317  
3318  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
3319  
3320 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
3321 +
3322 +
3323 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
3324 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
3325  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
3326  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
3327 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
3328 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
3329  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
3330  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
3331 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
3332 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
3333  
3334  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
3335 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
3336  
3337  # targets
3338  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
3339 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
3340  obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
3341  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
3342  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
3343  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
3344 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
3345  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
3346  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
3347 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
3348  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
3349  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
3350  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
3351  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
3352  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
3353 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
3354 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
3355 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
3356 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
3357 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
3358 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
3359  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
3360  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
3361 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
3362  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
3363  
3364  # generic ARP tables
3365 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_core.c
3366 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_core.c      2004-05-10 04:31:55.000000000 +0200
3367 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_core.c  2004-05-18 12:38:02.000000000 +0200
3368 @@ -324,8 +324,9 @@
3369                 ip_conntrack_destroyed(ct);
3370  
3371         WRITE_LOCK(&ip_conntrack_lock);
3372 -       /* Delete us from our own list to prevent corruption later */
3373 -       list_del(&ct->sibling_list);
3374 +       /* Make sure don't leave any orphaned expectations lying around */
3375 +       if (ct->expecting)
3376 +               remove_expectations(ct, 1);
3377  
3378         /* Delete our master expectation */
3379         if (ct->master) {
3380 @@ -692,25 +693,22 @@
3381                              struct ip_conntrack_expect *, tuple);
3382         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
3383  
3384 -       /* If master is not in hash table yet (ie. packet hasn't left
3385 -          this machine yet), how can other end know about expected?
3386 -          Hence these are not the droids you are looking for (if
3387 -          master ct never got confirmed, we'd hold a reference to it
3388 -          and weird things would happen to future packets). */
3389 -       if (expected && !is_confirmed(expected->expectant))
3390 -               expected = NULL;
3391 -
3392 -       /* Look up the conntrack helper for master connections only */
3393 -       if (!expected)
3394 -               conntrack->helper = ip_ct_find_helper(&repl_tuple);
3395 +       if (expected) {
3396 +               /* If master is not in hash table yet (ie. packet hasn't left
3397 +                  this machine yet), how can other end know about expected?
3398 +                  Hence these are not the droids you are looking for (if
3399 +                  master ct never got confirmed, we'd hold a reference to it
3400 +                  and weird things would happen to future packets). */
3401 +               if (!is_confirmed(expected->expectant)) {
3402 +                       conntrack->helper = ip_ct_find_helper(&repl_tuple);
3403 +                       goto end;
3404 +               }
3405  
3406 -       /* If the expectation is dying, then this is a loser. */
3407 -       if (expected
3408 -           && expected->expectant->helper->timeout
3409 -           && ! del_timer(&expected->timeout))
3410 -               expected = NULL;
3411 +               /* Expectation is dying... */
3412 +               if (expected->expectant->helper->timeout
3413 +                   && !del_timer(&expected->timeout))
3414 +                       goto end;       
3415  
3416 -       if (expected) {
3417                 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3418                         conntrack, expected);
3419                 /* Welcome, Mr. Bond.  We've been expecting you... */
3420 @@ -718,16 +716,28 @@
3421                 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3422                 conntrack->master = expected;
3423                 expected->sibling = conntrack;
3424 +#if CONFIG_IP_NF_CONNTRACK_MARK
3425 +               conntrack->mark = expected->expectant->mark;
3426 +#endif
3427                 LIST_DELETE(&ip_conntrack_expect_list, expected);
3428                 expected->expectant->expecting--;
3429                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3430 -       }
3431 -       atomic_inc(&ip_conntrack_count);
3432 +
3433 +               /* this is a braindead... --pablo */
3434 +               atomic_inc(&ip_conntrack_count);
3435 +               WRITE_UNLOCK(&ip_conntrack_lock);
3436 +
3437 +               if (expected->expectfn)
3438 +                       expected->expectfn(conntrack);
3439 +
3440 +               goto ret;
3441 +       } else 
3442 +               conntrack->helper = ip_ct_find_helper(&repl_tuple);
3443 +
3444 +end:   atomic_inc(&ip_conntrack_count);
3445         WRITE_UNLOCK(&ip_conntrack_lock);
3446  
3447 -       if (expected && expected->expectfn)
3448 -               expected->expectfn(conntrack);
3449 -       return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3450 +ret:   return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3451  }
3452  
3453  /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3454 @@ -947,9 +957,8 @@
3455         atomic_set(&new->use, 1);
3456  
3457         /* add to expected list for this connection */
3458 -       list_add(&new->expected_list, &related_to->sibling_list);
3459 +       list_add_tail(&new->expected_list, &related_to->sibling_list);
3460         /* add to global list of expectations */
3461 -
3462         list_prepend(&ip_conntrack_expect_list, &new->list);
3463         /* add and start timer if required */
3464         if (related_to->helper->timeout) {
3465 @@ -1003,7 +1012,6 @@
3466  
3467         } else if (related_to->helper->max_expected && 
3468                    related_to->expecting >= related_to->helper->max_expected) {
3469 -               struct list_head *cur_item;
3470                 /* old == NULL */
3471                 if (!(related_to->helper->flags & 
3472                       IP_CT_HELPER_F_REUSE_EXPECT)) {
3473 @@ -1029,21 +1037,14 @@
3474                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3475   
3476                 /* choose the the oldest expectation to evict */
3477 -               list_for_each(cur_item, &related_to->sibling_list) { 
3478 -                       struct ip_conntrack_expect *cur;
3479 -
3480 -                       cur = list_entry(cur_item, 
3481 -                                        struct ip_conntrack_expect,
3482 -                                        expected_list);
3483 -                       if (cur->sibling == NULL) {
3484 -                               old = cur;
3485 +               list_for_each_entry(old, &related_to->sibling_list, 
3486 +                                                     expected_list)
3487 +                       if (old->sibling == NULL)
3488                                 break;
3489 -                       }
3490 -               }
3491  
3492 -               /* (!old) cannot happen, since related_to->expecting is the
3493 -                * number of unconfirmed expects */
3494 -               IP_NF_ASSERT(old);
3495 +               /* We cannot fail since related_to->expecting is the number
3496 +                * of unconfirmed expectations */
3497 +               IP_NF_ASSERT(old && old->sibling == NULL);
3498  
3499                 /* newnat14 does not reuse the real allocated memory
3500                  * structures but rather unexpects the old and
3501 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_egg.c
3502 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_egg.c       1970-01-01 01:00:00.000000000 +0100
3503 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_egg.c   2004-05-18 12:39:11.000000000 +0200
3504 @@ -0,0 +1,237 @@
3505 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3506 + * based on ip_conntrack_irc.c 
3507 + *
3508 + *      This module only supports the share userfile-send command,
3509 + *      used by eggdrops to share it's userfile.
3510 + *
3511 + *      There are no support for NAT at the moment.
3512 + *
3513 + *      This program is free software; you can redistribute it and/or
3514 + *      modify it under the terms of the GNU General Public License
3515 + *      as published by the Free Software Foundation; either version
3516 + *      2 of the License, or (at your option) any later version.
3517 + *
3518 + *     Module load syntax:
3519 + *     
3520 + *     please give the ports of all Eggdrops You have running
3521 + *      on your system, the default port is 3333.
3522 + *
3523 + *      2001-04-19: Security update. IP addresses are now compared
3524 + *                  to prevent unauthorized "related" access.
3525 + *
3526 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
3527 + *                 Port to netfilter 'newnat' API.
3528 + */
3529 +
3530 +#include <linux/module.h>
3531 +#include <linux/netfilter.h>
3532 +#include <linux/ip.h>
3533 +#include <net/checksum.h>
3534 +#include <net/tcp.h>
3535 +
3536 +#include <linux/netfilter_ipv4/lockhelp.h>
3537 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3538 +
3539 +#define MAX_PORTS 8
3540 +static int ports[MAX_PORTS];
3541 +static int ports_c = 0;
3542 +static unsigned int egg_timeout = 300;
3543 +
3544 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3545 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3546 +MODULE_LICENSE("GPL");
3547 +#ifdef MODULE_PARM
3548 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3549 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3550 +#endif
3551 +
3552 +DECLARE_LOCK(ip_egg_lock);
3553 +struct module *ip_conntrack_egg = THIS_MODULE;
3554 +
3555 +#if 0
3556 +#define DEBUGP printk
3557 +#else
3558 +#define DEBUGP(format, args...)
3559 +#endif
3560 +
3561 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3562 +/* tries to get the ip_addr and port out of a eggdrop command
3563 +   return value: -1 on failure, 0 on success 
3564 +   data                pointer to first byte of DCC command data
3565 +   data_end    pointer to last byte of dcc command data
3566 +   ip          returns parsed ip of dcc command
3567 +   port                returns parsed port of dcc command */
3568 +{
3569 +       if (data > data_end)
3570 +               return -1;
3571 +       
3572 +       *ip = simple_strtoul(data, &data, 10);
3573 +
3574 +       /* skip blanks between ip and port */
3575 +       while (*data == ' ' && data < data_end)
3576 +               data++;
3577 +
3578 +       *port = simple_strtoul(data, &data, 10);
3579 +       return 0;
3580 +}
3581 +
3582 +
3583 +static int help(const struct iphdr *iph, size_t len,
3584 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3585 +{
3586 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3587 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3588 +       char *data = (char *) tcph + tcph->doff * 4;
3589 +       char *data_limit;
3590 +       u_int32_t tcplen = len - iph->ihl * 4;
3591 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3592 +       int dir = CTINFO2DIR(ctinfo);
3593 +       int bytes_scanned = 0;
3594 +       struct ip_conntrack_expect exp;
3595 +
3596 +       u_int32_t egg_ip;
3597 +       u_int16_t egg_port;
3598 +
3599 +       DEBUGP("entered\n");
3600 +
3601 +       /* If packet is coming from IRC server */
3602 +       if (dir != IP_CT_DIR_REPLY)
3603 +               return NF_ACCEPT;
3604 +
3605 +       /* Until there's been traffic both ways, don't look in packets. */
3606 +       if (ctinfo != IP_CT_ESTABLISHED
3607 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3608 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
3609 +               return NF_ACCEPT;
3610 +       }
3611 +
3612 +       /* Not whole TCP header? */
3613 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3614 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3615 +               return NF_ACCEPT;
3616 +       }
3617 +
3618 +       /* Checksum invalid?  Ignore. */
3619 +       /* FIXME: Source route IP option packets --RR */
3620 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3621 +                        csum_partial((char *) tcph, tcplen, 0))) {
3622 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3623 +                       tcph, tcplen, NIPQUAD(iph->saddr),
3624 +                       NIPQUAD(iph->daddr));
3625 +               return NF_ACCEPT;
3626 +       }
3627 +
3628 +       data_limit = (char *) data + datalen;
3629 +       while (datalen > 5 && bytes_scanned < 128) {
3630 +               if (memcmp(data, "s us ", 5)) {
3631 +                       data++;
3632 +                       datalen--;
3633 +                       bytes_scanned++;
3634 +                       continue;
3635 +               }
3636 +
3637 +               data += 5;
3638 +
3639 +               DEBUGP("Userfile-share found in connection "
3640 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3641 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3642 +
3643 +               if (parse_command((char *) data, data_limit, &egg_ip,
3644 +                                 &egg_port)) {
3645 +                       DEBUGP("no data in userfile-share pkt\n");
3646 +                       return NF_ACCEPT;
3647 +               }
3648 +
3649 +               memset(&exp, 0, sizeof(exp));
3650 +
3651 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3652 +                       if (net_ratelimit())
3653 +                               printk("Forged Eggdrop command from "
3654 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3655 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3656 +                                      HIPQUAD(egg_ip), egg_port);
3657 +                       return NF_ACCEPT;
3658 +               }
3659 +
3660 +               exp.tuple.src.ip = iph->daddr;
3661 +               exp.tuple.src.u.tcp.port = 0;
3662 +               exp.tuple.dst.ip = htonl(egg_ip);
3663 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
3664 +               exp.tuple.dst.protonum = IPPROTO_TCP;
3665 +
3666 +               exp.mask.dst.u.tcp.port = 0xffff;
3667 +               exp.mask.dst.protonum = 0xffff;
3668 +
3669 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3670 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3671 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3672 +
3673 +               ip_conntrack_expect_related(ct, &exp);
3674 +               break;
3675 +       }
3676 +       return NF_ACCEPT;
3677 +}
3678 +
3679 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3680 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3681 +
3682 +static void deregister_helpers(void) {
3683 +       int i;
3684 +       
3685 +       for (i = 0; i < ports_c; i++) {
3686 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
3687 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
3688 +       }
3689 +}
3690 +
3691 +static int __init init(void)
3692 +{
3693 +       int i, ret;
3694 +       char *tmpname;
3695 +
3696 +       /* If no port given, default to standard eggdrop port */
3697 +       if (ports[0] == 0)
3698 +               ports[0] = 3333;
3699 +
3700 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3701 +               memset(&egg_helpers[i], 0,
3702 +                      sizeof(struct ip_conntrack_helper));
3703 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3704 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3705 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3706 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
3707 +               egg_helpers[i].max_expected = 1;
3708 +               egg_helpers[i].timeout = egg_timeout;
3709 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3710 +               egg_helpers[i].me = THIS_MODULE;
3711 +               egg_helpers[i].help = help;
3712 +
3713 +               tmpname = &egg_names[i][0];
3714 +               if (ports[i] == 3333)
3715 +                       sprintf(tmpname, "eggdrop");
3716 +               else
3717 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
3718 +               egg_helpers[i].name = tmpname;
3719 +
3720 +               DEBUGP("port #%d: %d\n", i, ports[i]);
3721 +
3722 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
3723 +
3724 +               if (ret) {
3725 +                       printk("ip_conntrack_egg: ERROR registering helper "
3726 +                               "for port %d\n", ports[i]);
3727 +                       deregister_helpers();
3728 +                       return 1;
3729 +               }
3730 +               ports_c++;
3731 +       }
3732 +       return 0;
3733 +}
3734 +
3735 +static void __exit fini(void)
3736 +{
3737 +       deregister_helpers();
3738 +}
3739 +
3740 +module_init(init);
3741 +module_exit(fini);
3742 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_h323.c
3743 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_h323.c      1970-01-01 01:00:00.000000000 +0100
3744 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_h323.c  2004-05-18 12:39:18.000000000 +0200
3745 @@ -0,0 +1,308 @@
3746 +/* 
3747 + * H.323 'brute force' extension for H.323 connection tracking. 
3748 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3749 + *
3750 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3751 + * (http://www.coritel.it/projects/sofia/nat/)
3752 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3753 + * the unregistered helpers to the conntrack entries.
3754 + */
3755 +
3756 +
3757 +#include <linux/module.h>
3758 +#include <linux/netfilter.h>
3759 +#include <linux/ip.h>
3760 +#include <net/checksum.h>
3761 +#include <net/tcp.h>
3762 +
3763 +#include <linux/netfilter_ipv4/lockhelp.h>
3764 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3765 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3766 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3767 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3768 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3769 +
3770 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3771 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3772 +MODULE_LICENSE("GPL");
3773 +
3774 +DECLARE_LOCK(ip_h323_lock);
3775 +struct module *ip_conntrack_h323 = THIS_MODULE;
3776 +
3777 +#if 0
3778 +#define DEBUGP printk
3779 +#else
3780 +#define DEBUGP(format, args...)
3781 +#endif
3782 +
3783 +/* FIXME: This should be in userspace.  Later. */
3784 +static int h245_help(const struct iphdr *iph, size_t len,
3785 +                    struct ip_conntrack *ct,
3786 +                    enum ip_conntrack_info ctinfo)
3787 +{
3788 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3789 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3790 +       unsigned char *data_limit;
3791 +       u_int32_t tcplen = len - iph->ihl * 4;
3792 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3793 +       int dir = CTINFO2DIR(ctinfo);
3794 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3795 +       struct ip_conntrack_expect expect, *exp = &expect;
3796 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3797 +       u_int16_t data_port;
3798 +       u_int32_t data_ip;
3799 +       unsigned int i;
3800 +
3801 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3802 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3803 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3804 +
3805 +       /* Can't track connections formed before we registered */
3806 +       if (!info)
3807 +               return NF_ACCEPT;
3808 +               
3809 +       /* Until there's been traffic both ways, don't look in packets. */
3810 +       if (ctinfo != IP_CT_ESTABLISHED
3811 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3812 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3813 +               return NF_ACCEPT;
3814 +       }
3815 +
3816 +       /* Not whole TCP header or too short packet? */
3817 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3818 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3819 +               return NF_ACCEPT;
3820 +       }
3821 +
3822 +       /* Checksum invalid?  Ignore. */
3823 +       /* FIXME: Source route IP option packets --RR */
3824 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3825 +                             csum_partial((char *)tcph, tcplen, 0))) {
3826 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3827 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3828 +                      NIPQUAD(iph->daddr));
3829 +               return NF_ACCEPT;
3830 +       }
3831 +
3832 +       data_limit = (unsigned char *) data + datalen;
3833 +       /* bytes: 0123   45
3834 +                 ipadrr port */
3835 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3836 +               data_ip = *((u_int32_t *)data);
3837 +               if (data_ip == iph->saddr) {
3838 +                       data_port = *((u_int16_t *)(data + 4));
3839 +                       memset(&expect, 0, sizeof(expect));
3840 +                       /* update the H.225 info */
3841 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3842 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3843 +                               NIPQUAD(iph->saddr), ntohs(data_port));
3844 +                       LOCK_BH(&ip_h323_lock);
3845 +                       info->is_h225 = H225_PORT + 1;
3846 +                       exp_info->port = data_port;
3847 +                       exp_info->dir = dir;
3848 +                       exp_info->offset = i;
3849 +
3850 +                       exp->seq = ntohl(tcph->seq) + i;
3851 +                   
3852 +                       exp->tuple = ((struct ip_conntrack_tuple)
3853 +                               { { ct->tuplehash[!dir].tuple.src.ip,
3854 +                                   { 0 } },
3855 +                                 { data_ip,
3856 +                                   { .tcp = { data_port } },
3857 +                                   IPPROTO_UDP }});
3858 +                       exp->mask = ((struct ip_conntrack_tuple)
3859 +                               { { 0xFFFFFFFF, { 0 } },
3860 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3861 +       
3862 +                       exp->expectfn = NULL;
3863 +                       
3864 +                       /* Ignore failure; should only happen with NAT */
3865 +                       ip_conntrack_expect_related(ct, exp);
3866 +
3867 +                       UNLOCK_BH(&ip_h323_lock);
3868 +               }
3869 +       }
3870 +
3871 +       return NF_ACCEPT;
3872 +
3873 +}
3874 +
3875 +/* H.245 helper is not registered! */
3876 +static struct ip_conntrack_helper h245 = 
3877 +       { { NULL, NULL },
3878 +          "H.245",                             /* name */
3879 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
3880 +          NULL,                                        /* module */
3881 +          8,                                   /* max_ expected */
3882 +          240,                                 /* timeout */
3883 +          { { 0, { 0 } },                      /* tuple */
3884 +            { 0, { 0 }, IPPROTO_TCP } },
3885 +          { { 0, { 0xFFFF } },                 /* mask */
3886 +            { 0, { 0 }, 0xFFFF } },
3887 +          h245_help                            /* helper */
3888 +       };
3889 +
3890 +static int h225_expect(struct ip_conntrack *ct)
3891 +{
3892 +       WRITE_LOCK(&ip_conntrack_lock);
3893 +       ct->helper = &h245;
3894 +       DEBUGP("h225_expect: helper for %p added\n", ct);
3895 +       WRITE_UNLOCK(&ip_conntrack_lock);
3896 +       
3897 +       return NF_ACCEPT;       /* unused */
3898 +}
3899 +
3900 +/* FIXME: This should be in userspace.  Later. */
3901 +static int h225_help(const struct iphdr *iph, size_t len,
3902 +                    struct ip_conntrack *ct,
3903 +                    enum ip_conntrack_info ctinfo)
3904 +{
3905 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3906 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3907 +       unsigned char *data_limit;
3908 +       u_int32_t tcplen = len - iph->ihl * 4;
3909 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3910 +       int dir = CTINFO2DIR(ctinfo);
3911 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3912 +       struct ip_conntrack_expect expect, *exp = &expect;
3913 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3914 +       u_int16_t data_port;
3915 +       u_int32_t data_ip;
3916 +       unsigned int i;
3917 +       
3918 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3919 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3920 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3921 +
3922 +       /* Can't track connections formed before we registered */
3923 +       if (!info)
3924 +               return NF_ACCEPT;
3925 +
3926 +       /* Until there's been traffic both ways, don't look in packets. */
3927 +       if (ctinfo != IP_CT_ESTABLISHED
3928 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3929 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3930 +               return NF_ACCEPT;
3931 +       }
3932 +
3933 +       /* Not whole TCP header or too short packet? */
3934 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3935 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3936 +               return NF_ACCEPT;
3937 +       }
3938 +
3939 +       /* Checksum invalid?  Ignore. */
3940 +       /* FIXME: Source route IP option packets --RR */
3941 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3942 +                             csum_partial((char *)tcph, tcplen, 0))) {
3943 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3944 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3945 +                      NIPQUAD(iph->daddr));
3946 +               return NF_ACCEPT;
3947 +       }
3948 +       
3949 +       data_limit = (unsigned char *) data + datalen;
3950 +       /* bytes: 0123   45
3951 +                 ipadrr port */
3952 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3953 +               data_ip = *((u_int32_t *)data);
3954 +               if (data_ip == iph->saddr) {
3955 +                       data_port = *((u_int16_t *)(data + 4));
3956 +                       if (data_port == tcph->source) {
3957 +                               /* Signal address */
3958 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3959 +                                       NIPQUAD(iph->saddr));
3960 +                               /* Update the H.225 info so that NAT can mangle the address/port
3961 +                                  even when we have no expected connection! */
3962 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3963 +                               LOCK_BH(&ip_h323_lock);
3964 +                               info->dir = dir;
3965 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3966 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
3967 +                               UNLOCK_BH(&ip_h323_lock);
3968 +#endif
3969 +                       } else {
3970 +                               memset(&expect, 0, sizeof(expect));
3971 +
3972 +                               /* update the H.225 info */
3973 +                               LOCK_BH(&ip_h323_lock);
3974 +                               info->is_h225 = H225_PORT;
3975 +                               exp_info->port = data_port;
3976 +                               exp_info->dir = dir;
3977 +                               exp_info->offset = i;
3978 +
3979 +                               exp->seq = ntohl(tcph->seq) + i;
3980 +
3981 +                               exp->tuple = ((struct ip_conntrack_tuple)
3982 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
3983 +                                           { 0 } },
3984 +                                         { data_ip,
3985 +                                           { .tcp = { data_port } },
3986 +                                           IPPROTO_TCP }});
3987 +                               exp->mask = ((struct ip_conntrack_tuple)
3988 +                                       { { 0xFFFFFFFF, { 0 } },
3989 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3990 +       
3991 +                               exp->expectfn = h225_expect;
3992 +                               
3993 +                               /* Ignore failure */
3994 +                               ip_conntrack_expect_related(ct, exp);
3995 +
3996 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3997 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3998 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
3999 +
4000 +                               UNLOCK_BH(&ip_h323_lock);
4001 +                       }  
4002 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4003 +               } else if (data_ip == iph->daddr) {
4004 +                       data_port = *((u_int16_t *)(data + 4));
4005 +                       if (data_port == tcph->dest) {
4006 +                               /* Signal address */
4007 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
4008 +                                       NIPQUAD(iph->daddr));
4009 +                               /* Update the H.225 info so that NAT can mangle the address/port
4010 +                                  even when we have no expected connection! */
4011 +                               LOCK_BH(&ip_h323_lock);
4012 +                               info->dir = dir;
4013 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
4014 +                               info->offset[IP_CT_DIR_REPLY] = i;
4015 +                               UNLOCK_BH(&ip_h323_lock);
4016 +                       }
4017 +#endif
4018 +               }
4019 +       }
4020 +
4021 +       return NF_ACCEPT;
4022 +
4023 +}
4024 +
4025 +static struct ip_conntrack_helper h225 = 
4026 +       { { NULL, NULL },
4027 +         "H.225",                                      /* name */
4028 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
4029 +         THIS_MODULE,                                  /* module */
4030 +         2,                                            /* max_expected */
4031 +         240,                                          /* timeout */
4032 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
4033 +           { 0, { 0 }, IPPROTO_TCP } },
4034 +         { { 0, { 0xFFFF } },                          /* mask */
4035 +           { 0, { 0 }, 0xFFFF } },
4036 +         h225_help                                     /* helper */
4037 +       };
4038 +
4039 +static int __init init(void)
4040 +{
4041 +       return ip_conntrack_helper_register(&h225);
4042 +}
4043 +
4044 +static void __exit fini(void)
4045 +{
4046 +       /* Unregister H.225 helper */   
4047 +       ip_conntrack_helper_unregister(&h225);
4048 +}
4049 +
4050 +EXPORT_SYMBOL(ip_h323_lock);
4051 +
4052 +module_init(init);
4053 +module_exit(fini);
4054 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_mms.c
4055 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_mms.c       1970-01-01 01:00:00.000000000 +0100
4056 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_mms.c   2004-05-18 12:39:36.000000000 +0200
4057 @@ -0,0 +1,308 @@
4058 +/* MMS extension for IP connection tracking
4059 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4060 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
4061 + *
4062 + * ip_conntrack_mms.c v0.3 2002-09-22
4063 + *
4064 + *      This program is free software; you can redistribute it and/or
4065 + *      modify it under the terms of the GNU General Public License
4066 + *      as published by the Free Software Foundation; either version
4067 + *      2 of the License, or (at your option) any later version.
4068 + *
4069 + *      Module load syntax:
4070 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
4071 + *
4072 + *      Please give the ports of all MMS servers You wish to connect to.
4073 + *      If you don't specify ports, the default will be TCP port 1755.
4074 + *
4075 + *      More info on MMS protocol, firewalls and NAT:
4076 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
4077 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
4078 + *
4079 + *      The SDP project people are reverse-engineering MMS:
4080 + *      http://get.to/sdp
4081 + */
4082 +
4083 +#include <linux/config.h>
4084 +#include <linux/module.h>
4085 +#include <linux/netfilter.h>
4086 +#include <linux/ip.h>
4087 +#include <linux/ctype.h>
4088 +#include <net/checksum.h>
4089 +#include <net/tcp.h>
4090 +
4091 +#include <linux/netfilter_ipv4/lockhelp.h>
4092 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4093 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
4094 +
4095 +DECLARE_LOCK(ip_mms_lock);
4096 +struct module *ip_conntrack_mms = THIS_MODULE;
4097 +
4098 +#define MAX_PORTS 8
4099 +static int ports[MAX_PORTS];
4100 +static int ports_c;
4101 +#ifdef MODULE_PARM
4102 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4103 +#endif
4104 +
4105 +#if 0 
4106 +#define DEBUGP printk
4107 +#else
4108 +#define DEBUGP(format, args...)
4109 +#endif
4110 +
4111 +EXPORT_SYMBOL(ip_mms_lock);
4112 +
4113 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4114 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
4115 +MODULE_LICENSE("GPL");
4116 +
4117 +/* #define isdigit(c) (c >= '0' && c <= '9') */
4118 +
4119 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
4120 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
4121 +{
4122 +       int i;
4123 +       for (i = 0; i < unicode_size; ++i) {
4124 +               string[i] = (char)(unicode[i]);
4125 +       }
4126 +       string[unicode_size] = 0x00;
4127 +}
4128 +
4129 +__inline static int atoi(char *s) 
4130 +{
4131 +       int i=0;
4132 +       while (isdigit(*s)) {
4133 +               i = i*10 + *(s++) - '0';
4134 +       }
4135 +       return i;
4136 +}
4137 +
4138 +/* convert ip address string like "192.168.0.10" to unsigned int */
4139 +__inline static u_int32_t asciiiptoi(char *s)
4140 +{
4141 +       unsigned int i, j, k;
4142 +
4143 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
4144 +               i+=atoi(s);
4145 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
4146 +                       ;
4147 +       }
4148 +       i+=atoi(s);
4149 +       return ntohl(i);
4150 +}
4151 +
4152 +int parse_mms(const char *data, 
4153 +             const unsigned int datalen,
4154 +             u_int32_t *mms_ip,
4155 +             u_int16_t *mms_proto,
4156 +             u_int16_t *mms_port,
4157 +             char **mms_string_b,
4158 +             char **mms_string_e,
4159 +             char **mms_padding_e)
4160 +{
4161 +       int unicode_size, i;
4162 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
4163 +       char getlengthstring[28];
4164 +       
4165 +       for(unicode_size=0; 
4166 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
4167 +           unicode_size++)
4168 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
4169 +                       return -1; /* out of bounds - incomplete packet */
4170 +       
4171 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
4172 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
4173 +       
4174 +       /* IP address ? */
4175 +       *mms_ip = asciiiptoi(tempstring+2);
4176 +       
4177 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
4178 +               
4179 +       /* protocol ? */
4180 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
4181 +               *mms_proto = IPPROTO_TCP;
4182 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
4183 +               *mms_proto = IPPROTO_UDP;
4184 +
4185 +       /* port ? */
4186 +       *mms_port = atoi(tempstring+7+i);
4187 +
4188 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
4189 +          unicode string, one to the end of the string, and one to the end 
4190 +          of the packet, since we must keep track of the number of bytes 
4191 +          between end of the unicode string and the end of packet (padding) */
4192 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
4193 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
4194 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
4195 +       return 0;
4196 +}
4197 +
4198 +
4199 +/* FIXME: This should be in userspace.  Later. */
4200 +static int help(const struct iphdr *iph, size_t len,
4201 +               struct ip_conntrack *ct,
4202 +               enum ip_conntrack_info ctinfo)
4203 +{
4204 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
4205 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4206 +       const char *data = (const char *)tcph + tcph->doff * 4;
4207 +       unsigned int tcplen = len - iph->ihl * 4;
4208 +       unsigned int datalen = tcplen - tcph->doff * 4;
4209 +       int dir = CTINFO2DIR(ctinfo);
4210 +       struct ip_conntrack_expect expect, *exp = &expect; 
4211 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
4212 +       
4213 +       u_int32_t mms_ip;
4214 +       u_int16_t mms_proto;
4215 +       char mms_proto_string[8];
4216 +       u_int16_t mms_port;
4217 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
4218 +            
4219 +       /* Until there's been traffic both ways, don't look in packets. */
4220 +       if (ctinfo != IP_CT_ESTABLISHED
4221 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4222 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
4223 +               return NF_ACCEPT;
4224 +       }
4225 +
4226 +       /* Not whole TCP header? */
4227 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
4228 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
4229 +               return NF_ACCEPT;
4230 +       }
4231 +
4232 +       /* Checksum invalid?  Ignore. */
4233 +       /* FIXME: Source route IP option packets --RR */
4234 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4235 +           csum_partial((char *)tcph, tcplen, 0))) {
4236 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4237 +                      tcph, tcplen, NIPQUAD(iph->saddr),
4238 +                      NIPQUAD(iph->daddr));
4239 +               return NF_ACCEPT;
4240 +       }
4241 +       
4242 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
4243 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
4244 +          the client has already sent a packet to the server with the server's hostname 
4245 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
4246 +          server will break the connection if this doesn't correspond to its own host 
4247 +          header. The client can also connect to an IP address; if it's the server's IP
4248 +          address, it will not break the connection. When doing DNAT on a connection 
4249 +          where the client uses a server's IP address, the nat module should detect
4250 +          this and change this string accordingly to the DNATed address. This should
4251 +          probably be done by checking for an IP address, then storing it as a member
4252 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
4253 +          */
4254 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
4255 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
4256 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
4257 +                      (u8)*(data+36), (u8)*(data+37), 
4258 +                      (u8)*(data+38), (u8)*(data+39),
4259 +                      datalen);
4260 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
4261 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
4262 +                       if(net_ratelimit())
4263 +                               /* FIXME: more verbose debugging ? */
4264 +                               printk(KERN_WARNING
4265 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
4266 +
4267 +               memset(&expect, 0, sizeof(expect));
4268 +
4269 +               sprintf(mms_proto_string, "(%u)", mms_proto);
4270 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
4271 +                      mms_proto == IPPROTO_TCP ? "TCP"
4272 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
4273 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4274 +                      NIPQUAD(mms_ip),
4275 +                      mms_port);
4276 +               
4277 +               /* it's possible that the client will just ask the server to tunnel
4278 +                  the stream over the same TCP session (from port 1755): there's 
4279 +                  shouldn't be a need to add an expectation in that case, but it
4280 +                  makes NAT packet mangling so much easier */
4281 +               LOCK_BH(&ip_mms_lock);
4282 +
4283 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
4284 +               
4285 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
4286 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
4287 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
4288 +               exp_mms_info->port    = mms_port;
4289 +               
4290 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
4291 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
4292 +               
4293 +               exp->tuple = ((struct ip_conntrack_tuple)
4294 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4295 +                             { mms_ip,
4296 +                               { .tcp = { (__u16) ntohs(mms_port) } },
4297 +                               mms_proto } }
4298 +                            );
4299 +               exp->mask  = ((struct ip_conntrack_tuple)
4300 +                            { { 0xFFFFFFFF, { 0 } },
4301 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4302 +               exp->expectfn = NULL;
4303 +               ip_conntrack_expect_related(ct, &expect);
4304 +               UNLOCK_BH(&ip_mms_lock);
4305 +       }
4306 +
4307 +       return NF_ACCEPT;
4308 +}
4309 +
4310 +static struct ip_conntrack_helper mms[MAX_PORTS];
4311 +static char mms_names[MAX_PORTS][10];
4312 +
4313 +/* Not __exit: called from init() */
4314 +static void fini(void)
4315 +{
4316 +       int i;
4317 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4318 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
4319 +                               ports[i]);
4320 +               ip_conntrack_helper_unregister(&mms[i]);
4321 +       }
4322 +}
4323 +
4324 +static int __init init(void)
4325 +{
4326 +       int i, ret;
4327 +       char *tmpname;
4328 +
4329 +       if (ports[0] == 0)
4330 +               ports[0] = MMS_PORT;
4331 +
4332 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4333 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
4334 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
4335 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
4336 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
4337 +               mms[i].mask.dst.protonum = 0xFFFF;
4338 +               mms[i].max_expected = 1;
4339 +               mms[i].timeout = 0;
4340 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4341 +               mms[i].me = THIS_MODULE;
4342 +               mms[i].help = help;
4343 +
4344 +               tmpname = &mms_names[i][0];
4345 +               if (ports[i] == MMS_PORT)
4346 +                       sprintf(tmpname, "mms");
4347 +               else
4348 +                       sprintf(tmpname, "mms-%d", ports[i]);
4349 +               mms[i].name = tmpname;
4350 +
4351 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
4352 +                               ports[i]);
4353 +               ret = ip_conntrack_helper_register(&mms[i]);
4354 +
4355 +               if (ret) {
4356 +                       fini();
4357 +                       return ret;
4358 +               }
4359 +               ports_c++;
4360 +       }
4361 +       return 0;
4362 +}
4363 +
4364 +module_init(init);
4365 +module_exit(fini);
4366 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
4367 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c        1970-01-01 01:00:00.000000000 +0100
4368 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_proto_sctp.c    2004-05-18 12:40:23.000000000 +0200
4369 @@ -0,0 +1,529 @@
4370 +/*
4371 + * Connection tracking protocol helper module for SCTP.
4372 + * 
4373 + * SCTP is defined in RFC 2960. References to various sections in this code 
4374 + * are to this RFC.
4375 + * 
4376 + * This program is free software; you can redistribute it and/or modify
4377 + * it under the terms of the GNU General Public License version 2 as
4378 + * published by the Free Software Foundation.
4379 + */
4380 +
4381 +#include <linux/types.h>
4382 +#include <linux/sched.h>
4383 +#include <linux/timer.h>
4384 +#include <linux/netfilter.h>
4385 +#include <linux/module.h>
4386 +#include <linux/in.h>
4387 +#include <linux/ip.h>
4388 +#include <linux/sctp.h>
4389 +#include <linux/string.h>
4390 +
4391 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4392 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4393 +#include <linux/netfilter_ipv4/lockhelp.h>
4394 +
4395 +#if 0
4396 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4397 +#else
4398 +#define DEBUGP(format, args...)
4399 +#endif
4400 +
4401 +/* Protects conntrack->proto.sctp */
4402 +static DECLARE_RWLOCK(sctp_lock);
4403 +
4404 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4405 +   closely.  They're more complex. --RR 
4406 +
4407 +   And so for me for SCTP :D -Kiran */
4408 +
4409 +static const char *sctp_conntrack_names[] = {
4410 +       "NONE",
4411 +       "CLOSED",
4412 +       "COOKIE_WAIT",
4413 +       "COOKIE_ECHOED",
4414 +       "ESTABLISHED",
4415 +       "SHUTDOWN_SENT",
4416 +       "SHUTDOWN_RECD",
4417 +       "SHUTDOWN_ACK_SENT",
4418 +};
4419 +
4420 +#define SECS  * HZ
4421 +#define MINS  * 60 SECS
4422 +#define HOURS * 60 MINS
4423 +#define DAYS  * 24 HOURS
4424 +
4425 +unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
4426 +unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
4427 +unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
4428 +unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
4429 +unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
4430 +unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
4431 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
4432 +
4433 +static unsigned long * sctp_timeouts[]
4434 += { 0,                                     /* SCTP_CONNTRACK_NONE  */
4435 +    &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
4436 +    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
4437 +    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
4438 +    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
4439 +    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4440 +    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4441 +    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4442 + };
4443 +
4444 +#define sNO SCTP_CONNTRACK_NONE
4445 +#define        sCL SCTP_CONNTRACK_CLOSED
4446 +#define        sCW SCTP_CONNTRACK_COOKIE_WAIT
4447 +#define        sCE SCTP_CONNTRACK_COOKIE_ECHOED
4448 +#define        sES SCTP_CONNTRACK_ESTABLISHED
4449 +#define        sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4450 +#define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4451 +#define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4452 +#define        sIV SCTP_CONNTRACK_MAX
4453 +
4454 +/* 
4455 +       These are the descriptions of the states:
4456 +
4457 +NOTE: These state names are tantalizingly similar to the states of an 
4458 +SCTP endpoint. But the interpretation of the states is a little different,
4459 +considering that these are the states of the connection and not of an end 
4460 +point. Please note the subtleties. -Kiran
4461 +
4462 +NONE              - Nothing so far.
4463 +COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
4464 +                    an INIT_ACK chunk in the reply direction.
4465 +COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
4466 +ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
4467 +SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
4468 +SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
4469 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4470 +                    to that of the SHUTDOWN chunk.
4471 +CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
4472 +                    the SHUTDOWN chunk. Connection is closed.
4473 +*/
4474 +
4475 +/* TODO
4476 + - I have assumed that the first INIT is in the original direction. 
4477 + This messes things when an INIT comes in the reply direction in CLOSED
4478 + state.
4479 + - Check the error type in the reply dir before transitioning from 
4480 +cookie echoed to closed.
4481 + - Sec 5.2.4 of RFC 2960
4482 + - Multi Homing support.
4483 +*/
4484 +
4485 +/* SCTP conntrack state transitions */
4486 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4487 +       {
4488 +/*     ORIGINAL        */
4489 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4490 +/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4491 +/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4492 +/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4493 +/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4494 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4495 +/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4496 +/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4497 +/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4498 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4499 +       },
4500 +       {
4501 +/*     REPLY   */
4502 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4503 +/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4504 +/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4505 +/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4506 +/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4507 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4508 +/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4509 +/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4510 +/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4511 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4512 +       }
4513 +};
4514 +
4515 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4516 +                            unsigned int dataoff,
4517 +                            struct ip_conntrack_tuple *tuple)
4518 +{
4519 +       sctp_sctphdr_t hdr;
4520 +
4521 +       DEBUGP(__FUNCTION__);
4522 +       DEBUGP("\n");
4523 +
4524 +       /* Actually only need first 8 bytes. */
4525 +       if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4526 +               return 0;
4527 +
4528 +       tuple->src.u.sctp.port = hdr.source;
4529 +       tuple->dst.u.sctp.port = hdr.dest;
4530 +
4531 +       return 1;
4532 +}
4533 +
4534 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4535 +                            const struct ip_conntrack_tuple *orig)
4536 +{
4537 +       DEBUGP(__FUNCTION__);
4538 +       DEBUGP("\n");
4539 +
4540 +       tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4541 +       tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4542 +       return 1;
4543 +}
4544 +
4545 +/* Print out the per-protocol part of the tuple. */
4546 +static unsigned int sctp_print_tuple(char *buffer,
4547 +                                    const struct ip_conntrack_tuple *tuple)
4548 +{
4549 +       DEBUGP(__FUNCTION__);
4550 +       DEBUGP("\n");
4551 +
4552 +       return sprintf(buffer, "sport=%hu dport=%hu ",
4553 +                      ntohs(tuple->src.u.sctp.port),
4554 +                      ntohs(tuple->dst.u.sctp.port));
4555 +}
4556 +
4557 +/* Print out the private part of the conntrack. */
4558 +static unsigned int sctp_print_conntrack(char *buffer,
4559 +                                        const struct ip_conntrack *conntrack)
4560 +{
4561 +       enum sctp_conntrack state;
4562 +
4563 +       DEBUGP(__FUNCTION__);
4564 +       DEBUGP("\n");
4565 +
4566 +       READ_LOCK(&sctp_lock);
4567 +       state = conntrack->proto.sctp.state;
4568 +       READ_UNLOCK(&sctp_lock);
4569 +
4570 +       return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4571 +}
4572 +
4573 +#define for_each_sctp_chunk(skb, sch, offset, count)   \
4574 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0;       \
4575 +       offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch));    \
4576 +       offset += (htons(sch.length) + 3) & ~3, count++)
4577 +
4578 +/* Some validity checks to make sure the chunks are fine */
4579 +static int do_basic_checks(struct ip_conntrack *conntrack,
4580 +                          const struct sk_buff *skb,
4581 +                          char *map)
4582 +{
4583 +       u_int32_t offset, count;
4584 +       sctp_chunkhdr_t sch;
4585 +       int flag;
4586 +
4587 +       DEBUGP(__FUNCTION__);
4588 +       DEBUGP("\n");
4589 +
4590 +       flag = 0;
4591 +
4592 +       for_each_sctp_chunk (skb, sch, offset, count) {
4593 +               DEBUGP("Chunk Num: %d  Type: %d\n", count, sch.type);
4594 +
4595 +               if (sch.type == SCTP_CID_INIT 
4596 +                       || sch.type == SCTP_CID_INIT_ACK
4597 +                       || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4598 +                       flag = 1;
4599 +               }
4600 +
4601 +               /* Cookie Ack/Echo chunks not the first OR 
4602 +                  Init / Init Ack / Shutdown compl chunks not the only chunks */
4603 +               if ((sch.type == SCTP_CID_COOKIE_ACK 
4604 +                       || sch.type == SCTP_CID_COOKIE_ECHO
4605 +                       || flag)
4606 +                    && count !=0 ) {
4607 +                       DEBUGP("Basic checks failed\n");
4608 +                       return 1;
4609 +               }
4610 +
4611 +               if (map) {
4612 +                       set_bit (sch.type, (void *)map);
4613 +               }
4614 +       }
4615 +
4616 +       DEBUGP("Basic checks passed\n");
4617 +       return 0;
4618 +}
4619 +
4620 +static int new_state(enum ip_conntrack_dir dir,
4621 +                    enum sctp_conntrack cur_state,
4622 +                    int chunk_type)
4623 +{
4624 +       int i;
4625 +
4626 +       DEBUGP(__FUNCTION__);
4627 +       DEBUGP("\n");
4628 +
4629 +       DEBUGP("Chunk type: %d\n", chunk_type);
4630 +
4631 +       switch (chunk_type) {
4632 +               case SCTP_CID_INIT: 
4633 +                       DEBUGP("SCTP_CID_INIT\n");
4634 +                       i = 0; break;
4635 +               case SCTP_CID_INIT_ACK: 
4636 +                       DEBUGP("SCTP_CID_INIT_ACK\n");
4637 +                       i = 1; break;
4638 +               case SCTP_CID_ABORT: 
4639 +                       DEBUGP("SCTP_CID_ABORT\n");
4640 +                       i = 2; break;
4641 +               case SCTP_CID_SHUTDOWN: 
4642 +                       DEBUGP("SCTP_CID_SHUTDOWN\n");
4643 +                       i = 3; break;
4644 +               case SCTP_CID_SHUTDOWN_ACK: 
4645 +                       DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4646 +                       i = 4; break;
4647 +               case SCTP_CID_ERROR: 
4648 +                       DEBUGP("SCTP_CID_ERROR\n");
4649 +                       i = 5; break;
4650 +               case SCTP_CID_COOKIE_ECHO: 
4651 +                       DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4652 +                       i = 6; break;
4653 +               case SCTP_CID_COOKIE_ACK: 
4654 +                       DEBUGP("SCTP_CID_COOKIE_ACK\n");
4655 +                       i = 7; break;
4656 +               case SCTP_CID_SHUTDOWN_COMPLETE: 
4657 +                       DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4658 +                       i = 8; break;
4659 +               default:
4660 +                       /* Other chunks like DATA, SACK, HEARTBEAT and
4661 +                       its ACK do not cause a change in state */
4662 +                       DEBUGP("Unknown chunk type, Will stay in %s\n", 
4663 +                                               sctp_conntrack_names[cur_state]);
4664 +                       return cur_state;
4665 +       }
4666 +
4667 +       DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
4668 +                       dir, sctp_conntrack_names[cur_state], chunk_type,
4669 +                       sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4670 +
4671 +       return sctp_conntracks[dir][i][cur_state];
4672 +}
4673 +
4674 +/* Returns verdict for packet, or -1 for invalid. */
4675 +static int sctp_packet(struct ip_conntrack *conntrack,
4676 +                      const struct sk_buff *skb,
4677 +                      enum ip_conntrack_info ctinfo)
4678 +{
4679 +       enum sctp_conntrack newconntrack, oldsctpstate;
4680 +       sctp_sctphdr_t sctph;
4681 +       sctp_chunkhdr_t sch;
4682 +       u_int32_t offset, count;
4683 +       char map[256 / sizeof (char)] = {0};
4684 +
4685 +       DEBUGP(__FUNCTION__);
4686 +       DEBUGP("\n");
4687 +
4688 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4689 +               return -1;
4690 +
4691 +       if (do_basic_checks(conntrack, skb, map) != 0)
4692 +               return -1;
4693 +
4694 +       /* Check the verification tag (Sec 8.5) */
4695 +       if (!test_bit(SCTP_CID_INIT, (void *)map)
4696 +               && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4697 +               && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4698 +               && !test_bit(SCTP_CID_ABORT, (void *)map)
4699 +               && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4700 +               && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4701 +               DEBUGP("Verification tag check failed\n");
4702 +               return -1;
4703 +       }
4704 +
4705 +       oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4706 +       for_each_sctp_chunk (skb, sch, offset, count) {
4707 +               WRITE_LOCK(&sctp_lock);
4708 +
4709 +               /* Special cases of Verification tag check (Sec 8.5.1) */
4710 +               if (sch.type == SCTP_CID_INIT) {
4711 +                       /* Sec 8.5.1 (A) */
4712 +                       if (sctph.vtag != 0) {
4713 +                               WRITE_UNLOCK(&sctp_lock);
4714 +                               return -1;
4715 +                       }
4716 +               } else if (sch.type == SCTP_CID_ABORT) {
4717 +                       /* Sec 8.5.1 (B) */
4718 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4719 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4720 +                                                       [1 - CTINFO2DIR(ctinfo)])) {
4721 +                               WRITE_UNLOCK(&sctp_lock);
4722 +                               return -1;
4723 +                       }
4724 +               } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4725 +                       /* Sec 8.5.1 (C) */
4726 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4727 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4728 +                                                       [1 - CTINFO2DIR(ctinfo)] 
4729 +                                       && (sch.flags & 1))) {
4730 +                               WRITE_UNLOCK(&sctp_lock);
4731 +                               return -1;
4732 +                       }
4733 +               } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4734 +                       /* Sec 8.5.1 (D) */
4735 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4736 +                               WRITE_UNLOCK(&sctp_lock);
4737 +                               return -1;
4738 +                       }
4739 +               }
4740 +
4741 +               oldsctpstate = conntrack->proto.sctp.state;
4742 +               newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4743 +
4744 +               /* Invalid */
4745 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4746 +                       DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4747 +                              CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4748 +                       WRITE_UNLOCK(&sctp_lock);
4749 +                       return -1;
4750 +               }
4751 +
4752 +               /* If it is an INIT or an INIT ACK note down the vtag */
4753 +               if (sch.type == SCTP_CID_INIT 
4754 +                       || sch.type == SCTP_CID_INIT_ACK) {
4755 +                       sctp_inithdr_t inithdr;
4756 +
4757 +                       if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4758 +                               &inithdr, sizeof(inithdr)) != 0) {
4759 +                                       WRITE_UNLOCK(&sctp_lock);
4760 +                                       return -1;
4761 +                       }
4762 +                       DEBUGP("Setting vtag %x for dir %d\n", 
4763 +                                       inithdr.init_tag, CTINFO2DIR(ctinfo));
4764 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4765 +               }
4766 +
4767 +               conntrack->proto.sctp.state = newconntrack;
4768 +               WRITE_UNLOCK(&sctp_lock);
4769 +       }
4770 +
4771 +       ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4772 +
4773 +       if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4774 +               && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4775 +               && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4776 +               DEBUGP("Setting assured bit\n");
4777 +               set_bit(IPS_ASSURED_BIT, &conntrack->status);
4778 +       }
4779 +
4780 +       return NF_ACCEPT;
4781 +}
4782 +
4783 +/* Called when a new connection for this protocol found. */
4784 +static int sctp_new(struct ip_conntrack *conntrack, 
4785 +                   const struct sk_buff *skb)
4786 +{
4787 +       enum sctp_conntrack newconntrack;
4788 +       sctp_sctphdr_t sctph;
4789 +       sctp_chunkhdr_t sch;
4790 +       u_int32_t offset, count;
4791 +       char map[256 / sizeof (char)] = {0};
4792 +
4793 +       DEBUGP(__FUNCTION__);
4794 +       DEBUGP("\n");
4795 +
4796 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4797 +               return -1;
4798 +
4799 +       if (do_basic_checks(conntrack, skb, map) != 0)
4800 +               return -1;
4801 +
4802 +       /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4803 +       if ((test_bit (SCTP_CID_ABORT, (void *)map))
4804 +               || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4805 +               || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4806 +               return -1;
4807 +       }
4808 +
4809 +       newconntrack = SCTP_CONNTRACK_MAX;
4810 +       for_each_sctp_chunk (skb, sch, offset, count) {
4811 +               /* Don't need lock here: this conntrack not in circulation yet */
4812 +               newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
4813 +                                               SCTP_CONNTRACK_NONE, sch.type);
4814 +
4815 +               /* Invalid: delete conntrack */
4816 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4817 +                       DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4818 +                       return 0;
4819 +               }
4820 +
4821 +               /* Copy the vtag into the state info */
4822 +               if (sch.type == SCTP_CID_INIT) {
4823 +                       if (sctph.vtag == 0) {
4824 +                               sctp_inithdr_t inithdr;
4825 +
4826 +                               if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t), 
4827 +                                       &inithdr, sizeof(inithdr)) != 0) {
4828 +                                               return -1;
4829 +                               }
4830 +
4831 +                               DEBUGP("Setting vtag %x for new conn\n", 
4832 +                                       inithdr.init_tag);
4833 +
4834 +                               conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
4835 +                                                               inithdr.init_tag;
4836 +                       } else {
4837 +                               /* Sec 8.5.1 (A) */
4838 +                               return -1;
4839 +                       }
4840 +               }
4841 +               /* If it is a shutdown ack OOTB packet, we expect a return
4842 +                  shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
4843 +               else {
4844 +                       DEBUGP("Setting vtag %x for new conn OOTB\n", 
4845 +                               sctph.vtag);
4846 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
4847 +               }
4848 +
4849 +               conntrack->proto.sctp.state = newconntrack;
4850 +       }
4851 +
4852 +       return 1;
4853 +}
4854 +
4855 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
4856 +                               const struct sk_buff *skb)
4857 +{
4858 +       /* To be implemented */
4859 +       return 0;
4860 +}
4861 +
4862 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
4863 +       .list            = { NULL, NULL }, 
4864 +       .proto           = IPPROTO_SCTP, 
4865 +       .name            = "sctp",
4866 +       .pkt_to_tuple    = sctp_pkt_to_tuple, 
4867 +       .invert_tuple    = sctp_invert_tuple, 
4868 +       .print_tuple     = sctp_print_tuple, 
4869 +       .print_conntrack = sctp_print_conntrack,
4870 +       .packet          = sctp_packet, 
4871 +       .new             = sctp_new, 
4872 +       .destroy         = NULL, 
4873 +       .exp_matches_pkt = sctp_exp_matches_pkt, 
4874 +       .me              = THIS_MODULE 
4875 +};
4876 +
4877 +int __init init(void)
4878 +{
4879 +       int ret;
4880 +
4881 +       ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
4882 +       DEBUGP("SCTP conntrack module loading %s\n", 
4883 +                                       ret ? "failed": "succeeded");
4884 +       return ret;
4885 +}
4886 +
4887 +void __exit fini(void)
4888 +{
4889 +       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
4890 +       DEBUGP("SCTP conntrack module unloaded\n");
4891 +}
4892 +
4893 +module_init(init);
4894 +module_exit(fini);
4895 +
4896 +MODULE_LICENSE("GPL");
4897 +MODULE_AUTHOR("Kiran Kumar Immidi");
4898 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
4899 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_quake3.c
4900 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_quake3.c    1970-01-01 01:00:00.000000000 +0100
4901 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_quake3.c        2004-05-18 12:40:06.000000000 +0200
4902 @@ -0,0 +1,156 @@
4903 +/* Quake3 extension for IP connection tracking
4904 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4905 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
4906 + *
4907 + * ip_conntrack_quake3.c v0.04 2002-08-31
4908 + *
4909 + *      This program is free software; you can redistribute it and/or
4910 + *      modify it under the terms of the GNU General Public License
4911 + *      as published by the Free Software Foundation; either version
4912 + *      2 of the License, or (at your option) any later version.
4913 + *
4914 + *      Module load syntax:
4915 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
4916 + *
4917 + *      please give the ports of all Quake3 master servers You wish to 
4918 + *      connect to. If you don't specify ports, the default will be UDP 
4919 + *      port 27950.
4920 + *
4921 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
4922 + */
4923 +
4924 +#include <linux/module.h>
4925 +#include <linux/ip.h>
4926 +#include <linux/udp.h>
4927 +
4928 +#include <linux/netfilter.h>
4929 +#include <linux/netfilter_ipv4/ip_tables.h>
4930 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4931 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
4932 +
4933 +struct module *ip_conntrack_quake3 = THIS_MODULE;
4934 +
4935 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4936 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
4937 +MODULE_LICENSE("GPL");
4938 +
4939 +#define MAX_PORTS 8
4940 +static int ports[MAX_PORTS];
4941 +static int ports_c = 0;
4942 +#ifdef MODULE_PARM
4943 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4944 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
4945 +#endif
4946 +
4947 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
4948 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
4949 +#if 0 
4950 +#define DEBUGP printk
4951 +#else
4952 +#define DEBUGP(format, args...)
4953 +#endif
4954 +
4955 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
4956 +
4957 +static int quake3_help(const struct iphdr *iph, size_t len,
4958 +       struct ip_conntrack *ct,
4959 +       enum ip_conntrack_info ctinfo)
4960 +{
4961 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
4962 +       int dir = CTINFO2DIR(ctinfo);
4963 +       struct ip_conntrack_expect exp;
4964 +       int i;
4965 +       
4966 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
4967 +       if (ctinfo != IP_CT_ESTABLISHED
4968 +           && ctinfo != IP_CT_IS_REPLY) {
4969 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
4970 +               return NF_ACCEPT;
4971 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
4972 +       
4973 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
4974 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
4975 +                   i+6 < ntohs(udph->len);
4976 +                   i+=7) {
4977 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
4978 +                              i, ntohs(udph->len),
4979 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
4980 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
4981 +
4982 +                       memset(&exp, 0, sizeof(exp));
4983 +
4984 +                       exp.tuple = ((struct ip_conntrack_tuple)
4985 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4986 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
4987 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
4988 +                                        IPPROTO_UDP } }
4989 +                                   );
4990 +                       exp.mask  = ((struct ip_conntrack_tuple)
4991 +                                    { { 0xFFFFFFFF, { 0 } },
4992 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
4993 +                       exp.expectfn = NULL;
4994 +
4995 +                       ip_conntrack_expect_related(ct, &exp);
4996 +               }
4997 +
4998 +       }
4999 +       
5000 +       return(NF_ACCEPT);
5001 +}
5002 +
5003 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5004 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
5005 +
5006 +static void fini(void)
5007 +{
5008 +       int i;
5009 +
5010 +       for(i = 0 ; (i < ports_c); i++) {
5011 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5012 +                                       ports[i]);
5013 +               ip_conntrack_helper_unregister(&quake3[i]);
5014 +       } 
5015 +}
5016 +
5017 +static int __init init(void)
5018 +{
5019 +       int i, ret;
5020 +       char *tmpname;
5021 +
5022 +       if(!ports[0])
5023 +               ports[0]=QUAKE3_MASTER_PORT;
5024 +
5025 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5026 +               /* Create helper structure */
5027 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5028 +
5029 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5030 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5031 +               quake3[i].mask.dst.protonum = 0xFFFF;
5032 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
5033 +               quake3[i].help = quake3_help;
5034 +               quake3[i].me = THIS_MODULE;
5035 +
5036 +               tmpname = &quake3_names[i][0];
5037 +               if (ports[i] == QUAKE3_MASTER_PORT)
5038 +                       sprintf(tmpname, "quake3");
5039 +               else
5040 +                       sprintf(tmpname, "quake3-%d", i);
5041 +               quake3[i].name = tmpname;
5042 +               
5043 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5044 +                      ports[i]);
5045 +
5046 +               ret=ip_conntrack_helper_register(&quake3[i]);
5047 +               if(ret) {
5048 +                       fini();
5049 +                       return(ret);
5050 +               }
5051 +               ports_c++;
5052 +       }
5053 +
5054 +       return(0);
5055 +}
5056 +
5057 +module_init(init);
5058 +module_exit(fini);
5059 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rsh.c
5060 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rsh.c       1970-01-01 01:00:00.000000000 +0100
5061 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rsh.c   2004-05-18 12:40:16.000000000 +0200
5062 @@ -0,0 +1,331 @@
5063 +/* RSH extension for IP connection tracking, Version 1.0
5064 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5065 + * based on HW's ip_conntrack_irc.c    
5066 + *
5067 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
5068 + *
5069 + *      This program is free software; you can redistribute it and/or
5070 + *      modify it under the terms of the GNU General Public License
5071 + *      as published by the Free Software Foundation; either version
5072 + *      2 of the License, or (at your option) any later version.
5073 + **
5074 + *     Module load syntax:
5075 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
5076 + *     
5077 + *     please give the ports of all RSH servers You wish to connect to.
5078 + *     If You don't specify ports, the default will be port 514
5079 + **
5080 + *      Note to all:
5081 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
5082 + *        unfortunately I babysit some sysadmins that won't migrate
5083 + *       their legacy crap, in our second tier.
5084 + */
5085 +
5086 +
5087 +/*
5088 + *  Some docco ripped from the net to teach me all there is to know about
5089 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
5090 + *  this module).
5091 + *
5092 + *  I have no idea what "unix rshd man pages" these guys have .. but that
5093 + *  is some pretty detailed docco!
5094 + **
5095 + *
5096 + *  4. Of the rsh protocol.
5097 + *  -----------------------
5098 + * 
5099 + *   The rshd listens on TCP port #514. The following info is from the unix
5100 + *   rshd man pages :
5101 + * 
5102 + *   "Service Request Protocol
5103 + * 
5104 + *    When the rshd daemon receives a service request, it initiates the
5105 + *    following protocol:
5106 + * 
5107 + *     1. The rshd daemon checks the source port number for the request.
5108 + *        If the port number is not in the range 0 through 1023, the rshd daemon
5109 + *        terminates the connection.
5110 + * 
5111 + *     2. The rshd daemon reads characters from the socket up to a null byte.
5112 + *        The string read is interpreted as an ASCII number (base 10). If this
5113 + *        number is nonzero, the rshd daemon interprets it as the port number
5114 + *        of a secondary stream to be used as standard error. A second connection
5115 + *        is created to the specified port on the client host. The source port
5116 + *        on the local host is in the range 0 through 1023.
5117 + * 
5118 + *     3. The rshd daemon uses the source address of the initial connection
5119 + *        request to determine the name of the client host. If the name cannot
5120 + *        be determined, the rshd daemon uses the dotted decimal representation
5121 + *        of the client host's address.
5122 + * 
5123 + *     4. The rshd daemon retrieves the following information from the initial
5124 + *        socket:
5125 + * 
5126 + *         * A null-terminated string of at most 16 bytes interpreted as
5127 + *           the user name of the user on the client host.
5128 + * 
5129 + *         * A null-terminated string of at most 16 bytes interpreted as
5130 + *           the user name to be used on the local server host.
5131 + * 
5132 + *         * Another null-terminated string interpreted as a command line
5133 + *           to be passed to a shell on the local server host.
5134 + * 
5135 + *     5. The rshd daemon attempts to validate the user using the following steps:
5136 + * 
5137 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
5138 + *            file and tries to switch to the home directory (using the chdir
5139 + *            subroutine). If either the lookup or the directory change fails,
5140 + *            the rshd daemon terminates the connection.
5141 + * 
5142 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
5143 + *            the /etc/hosts.equiv file to see if the name of the client
5144 + *            workstation is listed. If the client workstation is listed as an
5145 + *            equivalent host, the rshd daemon validates the user.
5146 + * 
5147 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
5148 + *            authenticate the user by checking the .rhosts file.
5149 + * 
5150 + *         d. If either the $HOME/.rhosts authentication fails or the
5151 + *            client host is not an equivalent host, the rshd daemon
5152 + *            terminates the connection.
5153 + * 
5154 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
5155 + *        on the initial connection and passes the command line to the user's
5156 + *        local login shell. The shell then inherits the network connections
5157 + *        established by the rshd daemon."
5158 + * 
5159 + */
5160 +
5161 +
5162 +#include <linux/module.h>
5163 +#include <linux/netfilter.h>
5164 +#include <linux/ip.h>
5165 +#include <net/checksum.h>
5166 +#include <net/tcp.h>
5167 +
5168 +#include <linux/netfilter_ipv4/lockhelp.h>
5169 +#include <linux/netfilter_ipv4/ip_tables.h>
5170 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5171 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
5172 +
5173 +#define MAX_PORTS 8
5174 +static int ports[MAX_PORTS];
5175 +static int ports_n_c = 0;
5176 +
5177 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
5178 +MODULE_DESCRIPTION("RSH connection tracking module");
5179 +MODULE_LICENSE("GPL");
5180 +#ifdef MODULE_PARM
5181 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5182 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
5183 +#endif
5184 +
5185 +DECLARE_LOCK(ip_rsh_lock);
5186 +struct module *ip_conntrack_rsh = THIS_MODULE;
5187 +
5188 +#if 0
5189 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
5190 +                                       format, ## args)
5191 +#else
5192 +#define DEBUGP(format, args...)
5193 +#endif
5194 +
5195 +
5196 +
5197 +/* FIXME: This should be in userspace.  Later. */
5198 +static int help(const struct iphdr *iph, size_t len,
5199 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5200 +{
5201 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5202 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5203 +       const char *data = (const char *) tcph + tcph->doff * 4;
5204 +       u_int32_t tcplen = len - iph->ihl * 4;
5205 +       int dir = CTINFO2DIR(ctinfo);
5206 +        struct ip_conntrack_expect expect, *exp = &expect;
5207 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
5208 +       u_int16_t port;
5209 +       int maxoctet;
5210 +
5211 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
5212 +        *  original array size used in rshd/glibc) -- is there a
5213 +        *  vulnerability in rshd.c in the looped port *= 10?
5214 +        */
5215 +
5216 +
5217 +       DEBUGP("entered\n");
5218 +
5219 +       /* bail if packet is not from RSH client */
5220 +       if (dir == IP_CT_DIR_REPLY)
5221 +               return NF_ACCEPT;
5222 +
5223 +       /* Until there's been traffic both ways, don't look in packets. */
5224 +       if (ctinfo != IP_CT_ESTABLISHED
5225 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5226 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
5227 +               return NF_ACCEPT;
5228 +       }
5229 +
5230 +       /* Not whole TCP header? */
5231 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5232 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
5233 +               return NF_ACCEPT;
5234 +       }
5235 +
5236 +       /* Checksum invalid?  Ignore. */
5237 +       /* FIXME: Source route IP option packets --RR */
5238 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5239 +                        csum_partial((char *) tcph, tcplen, 0))) {
5240 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5241 +                    tcph, tcplen, NIPQUAD(iph->saddr),
5242 +                    NIPQUAD(iph->daddr));
5243 +               return NF_ACCEPT;
5244 +       }
5245 +
5246 +       /* find the rsh stderr port */
5247 +       maxoctet = 4;
5248 +       port = 0;
5249 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
5250 +               if (*data < 0)
5251 +                       return(1);
5252 +               if (*data == 0)
5253 +                       break;
5254 +               if (*data < 48 || *data > 57) {
5255 +                       DEBUGP("these aren't the packets you're looking for ..\n");
5256 +                       return NF_ACCEPT;
5257 +               }
5258 +               port = port * 10 + ( *data - 48 );
5259 +       }
5260 +
5261 +       /* dont relate sessions that try to expose the client */
5262 +       DEBUGP("found port %u\n", port);
5263 +       if (port > 1023) {
5264 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
5265 +               return NF_ACCEPT;
5266 +       }
5267 +
5268 +
5269 +       LOCK_BH(&ip_rsh_lock);
5270 +
5271 +       /*  new(,related) connection is;
5272 +        *          reply + dst (uint)port + src port (0:1023)
5273 +        */
5274 +       memset(&expect, 0, sizeof(expect));
5275 +
5276 +       /*  save some discovered data, in case someone ever wants to write
5277 +        *  a NAT module for this bastard ..
5278 +        */
5279 +       exp_rsh_info->port = port;
5280 +
5281 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
5282 +
5283 +
5284 +       /* Watch out, Radioactive-Man! */
5285 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5286 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5287 +       exp->tuple.src.u.tcp.port = 0;
5288 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
5289 +       exp->tuple.dst.protonum = IPPROTO_TCP;
5290 +
5291 +       exp->mask.src.ip = 0xffffffff;
5292 +       exp->mask.dst.ip = 0xffffffff;
5293 +
5294 +       exp->mask.src.u.tcp.port = htons(0xfc00);
5295 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
5296 +       exp->mask.dst.protonum = 0xffff;
5297 +
5298 +       exp->expectfn = NULL;
5299 +
5300 +       ip_conntrack_expect_related(ct, &expect);
5301 +
5302 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5303 +               NIPQUAD(exp->tuple.src.ip),
5304 +               ntohs(exp->tuple.src.u.tcp.port),
5305 +               NIPQUAD(exp->tuple.dst.ip),
5306 +               ntohs(exp->tuple.dst.u.tcp.port));
5307 +
5308 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5309 +               NIPQUAD(exp->mask.src.ip),
5310 +               ntohs(exp->mask.src.u.tcp.port),
5311 +               NIPQUAD(exp->mask.dst.ip),
5312 +               ntohs(exp->mask.dst.u.tcp.port));
5313 +       UNLOCK_BH(&ip_rsh_lock);
5314 +
5315 +       return NF_ACCEPT;
5316 +}
5317 +
5318 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
5319 +
5320 +static void fini(void);
5321 +
5322 +static int __init init(void)
5323 +{
5324 +       int port, ret;
5325 +       static char name[10];
5326 +
5327 +
5328 +       /* If no port given, default to standard RSH port */
5329 +       if (ports[0] == 0)
5330 +               ports[0] = RSH_PORT;
5331 +
5332 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5333 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5334 +
5335 +                if (ports[port] == RSH_PORT)
5336 +                        sprintf(name, "rsh");
5337 +                else
5338 +                        sprintf(name, "rsh-%d", port);
5339 +
5340 +               rsh_helpers[port].name = name;
5341 +               rsh_helpers[port].me = THIS_MODULE;
5342 +               rsh_helpers[port].max_expected = 1;
5343 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5344 +               rsh_helpers[port].timeout = 0;
5345 +
5346 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5347 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
5348 +
5349 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
5350 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
5351 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
5352 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
5353 +
5354 +               rsh_helpers[port].help = help;
5355 +
5356 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5357 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5358 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
5359 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
5360 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
5361 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
5362 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5363 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
5364 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
5365 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
5366 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
5367 +
5368 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
5369 +
5370 +               if (ret) {
5371 +                       printk("ERROR registering port %d\n",
5372 +                               ports[port]);
5373 +                       fini();
5374 +                       return -EBUSY;
5375 +               }
5376 +               ports_n_c++;
5377 +       }
5378 +       return 0;
5379 +}
5380 +
5381 +/* This function is intentionally _NOT_ defined as __exit, because 
5382 + * it is needed by the init function */
5383 +static void fini(void)
5384 +{
5385 +       int port;
5386 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5387 +               DEBUGP("unregistering port %d\n", ports[port]);
5388 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
5389 +       }
5390 +}
5391 +
5392 +module_init(init);
5393 +module_exit(fini);
5394 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rtsp.c
5395 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_rtsp.c      1970-01-01 01:00:00.000000000 +0100
5396 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_rtsp.c  2004-05-18 12:40:21.000000000 +0200
5397 @@ -0,0 +1,507 @@
5398 +/*
5399 + * RTSP extension for IP connection tracking
5400 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5401 + * based on ip_conntrack_irc.c
5402 + *
5403 + *      This program is free software; you can redistribute it and/or
5404 + *      modify it under the terms of the GNU General Public License
5405 + *      as published by the Free Software Foundation; either version
5406 + *      2 of the License, or (at your option) any later version.
5407 + *
5408 + * Module load syntax:
5409 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5410 + *                              max_outstanding=n setup_timeout=secs
5411 + *
5412 + * If no ports are specified, the default will be port 554.
5413 + *
5414 + * With max_outstanding you can define the maximum number of not yet
5415 + * answered SETUP requests per RTSP session (default 8).
5416 + * With setup_timeout you can specify how long the system waits for
5417 + * an expected data channel (default 300 seconds).
5418 + */
5419 +
5420 +#include <linux/config.h>
5421 +#include <linux/module.h>
5422 +#include <linux/netfilter.h>
5423 +#include <linux/ip.h>
5424 +#include <net/checksum.h>
5425 +#include <net/tcp.h>
5426 +
5427 +#include <linux/netfilter_ipv4/lockhelp.h>
5428 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5429 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5430 +
5431 +#include <linux/ctype.h>
5432 +#define NF_NEED_STRNCASECMP
5433 +#define NF_NEED_STRTOU16
5434 +#define NF_NEED_STRTOU32
5435 +#define NF_NEED_NEXTLINE
5436 +#include <linux/netfilter_helpers.h>
5437 +#define NF_NEED_MIME_NEXTLINE
5438 +#include <linux/netfilter_mime.h>
5439 +
5440 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5441 +
5442 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5443 +#ifdef IP_NF_RTSP_DEBUG
5444 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5445 +#else
5446 +#define DEBUGP(fmt, args...)
5447 +#endif
5448 +
5449 +#define MAX_PORTS 8
5450 +static int ports[MAX_PORTS];
5451 +static int num_ports = 0;
5452 +static int max_outstanding = 8;
5453 +static unsigned int setup_timeout = 300;
5454 +
5455 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5456 +MODULE_DESCRIPTION("RTSP connection tracking module");
5457 +MODULE_LICENSE("GPL");
5458 +#ifdef MODULE_PARM
5459 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5460 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5461 +MODULE_PARM(max_outstanding, "i");
5462 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5463 +MODULE_PARM(setup_timeout, "i");
5464 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5465 +#endif
5466 +
5467 +DECLARE_LOCK(ip_rtsp_lock);
5468 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5469 +
5470 +/*
5471 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5472 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
5473 + * ports so keep this reasonably high.  If this is too low, you will see a
5474 + * lot of "no free client map entries" messages.
5475 + */
5476 +#define MAX_PORT_MAPS 16
5477 +
5478 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5479 +
5480 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5481 +
5482 +/*
5483 + * Parse an RTSP packet.
5484 + *
5485 + * Returns zero if parsing failed.
5486 + *
5487 + * Parameters:
5488 + *  IN      ptcp        tcp data pointer
5489 + *  IN      tcplen      tcp data len
5490 + *  IN/OUT  ptcpoff     points to current tcp offset
5491 + *  OUT     phdrsoff    set to offset of rtsp headers
5492 + *  OUT     phdrslen    set to length of rtsp headers
5493 + *  OUT     pcseqoff    set to offset of CSeq header
5494 + *  OUT     pcseqlen    set to length of CSeq header
5495 + */
5496 +static int
5497 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5498 +                   uint* phdrsoff, uint* phdrslen,
5499 +                   uint* pcseqoff, uint* pcseqlen)
5500 +{
5501 +    uint    entitylen = 0;
5502 +    uint    lineoff;
5503 +    uint    linelen;
5504 +
5505 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5506 +    {
5507 +        return 0;
5508 +    }
5509 +
5510 +    *phdrsoff = *ptcpoff;
5511 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5512 +    {
5513 +        if (linelen == 0)
5514 +        {
5515 +            if (entitylen > 0)
5516 +            {
5517 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5518 +            }
5519 +            break;
5520 +        }
5521 +        if (lineoff+linelen > tcplen)
5522 +        {
5523 +            INFOP("!! overrun !!\n");
5524 +            break;
5525 +        }
5526 +
5527 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5528 +        {
5529 +            *pcseqoff = lineoff;
5530 +            *pcseqlen = linelen;
5531 +        }
5532 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5533 +        {
5534 +            uint off = lineoff+15;
5535 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
5536 +            nf_strtou32(ptcp+off, &entitylen);
5537 +        }
5538 +    }
5539 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
5540 +
5541 +    return 1;
5542 +}
5543 +
5544 +/*
5545 + * Find lo/hi client ports (if any) in transport header
5546 + * In:
5547 + *   ptcp, tcplen = packet
5548 + *   tranoff, tranlen = buffer to search
5549 + *
5550 + * Out:
5551 + *   pport_lo, pport_hi = lo/hi ports (host endian)
5552 + *
5553 + * Returns nonzero if any client ports found
5554 + *
5555 + * Note: it is valid (and expected) for the client to request multiple
5556 + * transports, so we need to parse the entire line.
5557 + */
5558 +static int
5559 +rtsp_parse_transport(char* ptran, uint tranlen,
5560 +                     struct ip_ct_rtsp_expect* prtspexp)
5561 +{
5562 +    int     rc = 0;
5563 +    uint    off = 0;
5564 +
5565 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5566 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
5567 +    {
5568 +        INFOP("sanity check failed\n");
5569 +        return 0;
5570 +    }
5571 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5572 +    off += 10;
5573 +    SKIP_WSPACE(ptran, tranlen, off);
5574 +
5575 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
5576 +    while (off < tranlen)
5577 +    {
5578 +        const char* pparamend;
5579 +        uint        nextparamoff;
5580 +
5581 +        pparamend = memchr(ptran+off, ',', tranlen-off);
5582 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5583 +        nextparamoff = pparamend-ptran;
5584 +
5585 +        while (off < nextparamoff)
5586 +        {
5587 +            const char* pfieldend;
5588 +            uint        nextfieldoff;
5589 +
5590 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5591 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5592 +
5593 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
5594 +            {
5595 +                u_int16_t   port;
5596 +                uint        numlen;
5597 +
5598 +                off += 12;
5599 +                numlen = nf_strtou16(ptran+off, &port);
5600 +                off += numlen;
5601 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
5602 +                {
5603 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
5604 +                }
5605 +                else
5606 +                {
5607 +                    prtspexp->loport = prtspexp->hiport = port;
5608 +                    if (ptran[off] == '-')
5609 +                    {
5610 +                        off++;
5611 +                        numlen = nf_strtou16(ptran+off, &port);
5612 +                        off += numlen;
5613 +                        prtspexp->pbtype = pb_range;
5614 +                        prtspexp->hiport = port;
5615 +
5616 +                        // If we have a range, assume rtp:
5617 +                        // loport must be even, hiport must be loport+1
5618 +                        if ((prtspexp->loport & 0x0001) != 0 ||
5619 +                            prtspexp->hiport != prtspexp->loport+1)
5620 +                        {
5621 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
5622 +                                   prtspexp->loport, prtspexp->hiport);
5623 +                            prtspexp->loport &= 0xfffe;
5624 +                            prtspexp->hiport = prtspexp->loport+1;
5625 +                        }
5626 +                    }
5627 +                    else if (ptran[off] == '/')
5628 +                    {
5629 +                        off++;
5630 +                        numlen = nf_strtou16(ptran+off, &port);
5631 +                        off += numlen;
5632 +                        prtspexp->pbtype = pb_discon;
5633 +                        prtspexp->hiport = port;
5634 +                    }
5635 +                    rc = 1;
5636 +                }
5637 +            }
5638 +
5639 +            /*
5640 +             * Note we don't look for the destination parameter here.
5641 +             * If we are using NAT, the NAT module will handle it.  If not,
5642 +             * and the client is sending packets elsewhere, the expectation
5643 +             * will quietly time out.
5644 +             */
5645 +
5646 +            off = nextfieldoff;
5647 +        }
5648 +
5649 +        off = nextparamoff;
5650 +    }
5651 +
5652 +    return rc;
5653 +}
5654 +
5655 +/*** conntrack functions ***/
5656 +
5657 +/* outbound packet: client->server */
5658 +static int
5659 +help_out(const struct iphdr* iph, size_t pktlen,
5660 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5661 +{
5662 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
5663 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
5664 +    uint    tcplen = pktlen - iph->ihl * 4;
5665 +    char*   pdata = (char*)tcph + tcph->doff * 4;
5666 +    uint    datalen = tcplen - tcph->doff * 4;
5667 +    uint    dataoff = 0;
5668 +
5669 +    struct ip_conntrack_expect exp;
5670 +
5671 +    while (dataoff < datalen)
5672 +    {
5673 +        uint    cmdoff = dataoff;
5674 +        uint    hdrsoff = 0;
5675 +        uint    hdrslen = 0;
5676 +        uint    cseqoff = 0;
5677 +        uint    cseqlen = 0;
5678 +        uint    lineoff = 0;
5679 +        uint    linelen = 0;
5680 +        uint    off;
5681 +        int     rc;
5682 +
5683 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
5684 +                                &hdrsoff, &hdrslen,
5685 +                                &cseqoff, &cseqlen))
5686 +        {
5687 +            break;      /* not a valid message */
5688 +        }
5689 +
5690 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5691 +        {
5692 +            continue;   /* not a SETUP message */
5693 +        }
5694 +        DEBUGP("found a setup message\n");
5695 +
5696 +        memset(&exp, 0, sizeof(exp));
5697 +
5698 +        off = 0;
5699 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5700 +                                &lineoff, &linelen))
5701 +        {
5702 +            if (linelen == 0)
5703 +            {
5704 +                break;
5705 +            }
5706 +            if (off > hdrsoff+hdrslen)
5707 +            {
5708 +                INFOP("!! overrun !!");
5709 +                break;
5710 +            }
5711 +
5712 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5713 +            {
5714 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5715 +                                     &exp.help.exp_rtsp_info);
5716 +            }
5717 +        }
5718 +
5719 +        if (exp.help.exp_rtsp_info.loport == 0)
5720 +        {
5721 +            DEBUGP("no udp transports found\n");
5722 +            continue;   /* no udp transports found */
5723 +        }
5724 +
5725 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5726 +              (int)exp.help.exp_rtsp_info.pbtype,
5727 +              exp.help.exp_rtsp_info.loport,
5728 +              exp.help.exp_rtsp_info.hiport);
5729 +
5730 +        LOCK_BH(&ip_rtsp_lock);
5731 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5732 +        exp.help.exp_rtsp_info.len = hdrslen;
5733 +
5734 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5735 +        exp.mask.src.ip  = 0xffffffff;
5736 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5737 +        exp.mask.dst.ip  = 0xffffffff;
5738 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5739 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5740 +        exp.tuple.dst.protonum = IPPROTO_UDP;
5741 +        exp.mask.dst.protonum  = 0xffff;
5742 +
5743 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5744 +                NIPQUAD(exp.tuple.src.ip),
5745 +                ntohs(exp.tuple.src.u.tcp.port),
5746 +                NIPQUAD(exp.tuple.dst.ip),
5747 +                ntohs(exp.tuple.dst.u.tcp.port));
5748 +
5749 +        /* pass the request off to the nat helper */
5750 +        rc = ip_conntrack_expect_related(ct, &exp);
5751 +        UNLOCK_BH(&ip_rtsp_lock);
5752 +        if (rc == 0)
5753 +        {
5754 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
5755 +        }
5756 +        else
5757 +        {
5758 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5759 +        }
5760 +    }
5761 +
5762 +    return NF_ACCEPT;
5763 +}
5764 +
5765 +/* inbound packet: server->client */
5766 +static int
5767 +help_in(const struct iphdr* iph, size_t pktlen,
5768 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5769 +{
5770 +    return NF_ACCEPT;
5771 +}
5772 +
5773 +static int
5774 +help(const struct iphdr* iph, size_t pktlen,
5775 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5776 +{
5777 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5778 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5779 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
5780 +
5781 +    /* Until there's been traffic both ways, don't look in packets. */
5782 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5783 +    {
5784 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
5785 +        return NF_ACCEPT;
5786 +    }
5787 +
5788 +    /* Not whole TCP header? */
5789 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5790 +    {
5791 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5792 +        return NF_ACCEPT;
5793 +    }
5794 +
5795 +    /* Checksum invalid?  Ignore. */
5796 +    /* FIXME: Source route IP option packets --RR */
5797 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5798 +                     csum_partial((char*)tcph, tcplen, 0)))
5799 +    {
5800 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5801 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5802 +        return NF_ACCEPT;
5803 +    }
5804 +
5805 +    switch (CTINFO2DIR(ctinfo))
5806 +    {
5807 +    case IP_CT_DIR_ORIGINAL:
5808 +        help_out(iph, pktlen, ct, ctinfo);
5809 +        break;
5810 +    case IP_CT_DIR_REPLY:
5811 +        help_in(iph, pktlen, ct, ctinfo);
5812 +        break;
5813 +    }
5814 +
5815 +    return NF_ACCEPT;
5816 +}
5817 +
5818 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5819 +static char rtsp_names[MAX_PORTS][10];
5820 +
5821 +/* This function is intentionally _NOT_ defined as __exit */
5822 +static void
5823 +fini(void)
5824 +{
5825 +    int i;
5826 +    for (i = 0; i < num_ports; i++)
5827 +    {
5828 +        DEBUGP("unregistering port %d\n", ports[i]);
5829 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5830 +    }
5831 +}
5832 +
5833 +static int __init
5834 +init(void)
5835 +{
5836 +    int i, ret;
5837 +    struct ip_conntrack_helper *hlpr;
5838 +    char *tmpname;
5839 +
5840 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5841 +
5842 +    if (max_outstanding < 1)
5843 +    {
5844 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5845 +        return -EBUSY;
5846 +    }
5847 +    if (setup_timeout < 0)
5848 +    {
5849 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5850 +        return -EBUSY;
5851 +    }
5852 +
5853 +    /* If no port given, default to standard rtsp port */
5854 +    if (ports[0] == 0)
5855 +    {
5856 +        ports[0] = RTSP_PORT;
5857 +    }
5858 +
5859 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5860 +    {
5861 +        hlpr = &rtsp_helpers[i];
5862 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5863 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5864 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
5865 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
5866 +        hlpr->mask.dst.protonum = 0xFFFF;
5867 +        hlpr->max_expected = max_outstanding;
5868 +        hlpr->timeout = setup_timeout;
5869 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5870 +        hlpr->me = ip_conntrack_rtsp;
5871 +        hlpr->help = help;
5872 +
5873 +        tmpname = &rtsp_names[i][0];
5874 +        if (ports[i] == RTSP_PORT)
5875 +        {
5876 +            sprintf(tmpname, "rtsp");
5877 +        }
5878 +        else
5879 +        {
5880 +            sprintf(tmpname, "rtsp-%d", i);
5881 +        }
5882 +        hlpr->name = tmpname;
5883 +
5884 +        DEBUGP("port #%d: %d\n", i, ports[i]);
5885 +
5886 +        ret = ip_conntrack_helper_register(hlpr);
5887 +
5888 +        if (ret)
5889 +        {
5890 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5891 +            fini();
5892 +            return -EBUSY;
5893 +        }
5894 +        num_ports++;
5895 +    }
5896 +    return 0;
5897 +}
5898 +
5899 +#ifdef CONFIG_IP_NF_NAT_NEEDED
5900 +EXPORT_SYMBOL(ip_rtsp_lock);
5901 +#endif
5902 +
5903 +module_init(init);
5904 +module_exit(fini);
5905 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_standalone.c
5906 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-05-10 04:32:29.000000000 +0200
5907 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-05-18 12:39:22.000000000 +0200
5908 @@ -110,6 +110,9 @@
5909                 len += sprintf(buffer + len, "[ASSURED] ");
5910         len += sprintf(buffer + len, "use=%u ",
5911                        atomic_read(&conntrack->ct_general.use));
5912 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5913 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5914 +#endif
5915         len += sprintf(buffer + len, "\n");
5916  
5917         return len;
5918 @@ -633,6 +636,7 @@
5919  EXPORT_SYMBOL(ip_conntrack_alter_reply);
5920  EXPORT_SYMBOL(ip_conntrack_destroyed);
5921  EXPORT_SYMBOL(ip_conntrack_get);
5922 +EXPORT_SYMBOL(__ip_conntrack_confirm);
5923  EXPORT_SYMBOL(need_ip_conntrack);
5924  EXPORT_SYMBOL(ip_conntrack_helper_register);
5925  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5926 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6/net/ipv4/netfilter/ip_conntrack_talk.c
5927 --- linux-2.6.6.org/net/ipv4/netfilter/ip_conntrack_talk.c      1970-01-01 01:00:00.000000000 +0100
5928 +++ linux-2.6.6/net/ipv4/netfilter/ip_conntrack_talk.c  2004-05-18 12:40:50.000000000 +0200
5929 @@ -0,0 +1,360 @@
5930 +/* 
5931 + * talk extension for IP connection tracking. 
5932 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5933 + *
5934 + *      This program is free software; you can redistribute it and/or
5935 + *      modify it under the terms of the GNU General Public License
5936 + *      as published by the Free Software Foundation; either version
5937 + *      2 of the License, or (at your option) any later version.
5938 + **
5939 + *     Module load syntax:
5940 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5941 + *
5942 + *             talk=[0|1]      disable|enable old talk support
5943 + *            ntalk=[0|1]      disable|enable ntalk support
5944 + *           ntalk2=[0|1]      disable|enable ntalk2 support
5945 + *
5946 + *     The default is talk=1 ntalk=1 ntalk2=1
5947 + *
5948 + *     The helper does not support simultaneous talk requests.
5949 + **
5950 + *
5951 + *             ASCII art on talk protocols
5952 + *     
5953 + *     
5954 + *     caller server               callee server
5955 + *             |     \           /
5956 + *             |       \       /
5957 + *             |         \   /
5958 + *             |           /  
5959 + *             |         /   \
5960 + *           2 |     1 /       \ 3
5961 + *     caller client  ----------- callee client
5962 + *                              4
5963 + *
5964 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
5965 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5966 + *     3. callee client <-> caller server: LOOK_UP invitation
5967 + *     4. callee client <-> caller client: talk data channel
5968 + *
5969 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
5970 + *      draft-hunter-talk-00.txt
5971 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
5972 + */
5973 +#include <linux/config.h>
5974 +#include <linux/module.h>
5975 +#include <linux/netfilter.h>
5976 +#include <linux/ip.h>
5977 +#include <net/checksum.h>
5978 +#include <net/udp.h>
5979 +
5980 +#include <linux/netfilter_ipv4/lockhelp.h>
5981 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5982 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5983 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5984 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5985 +
5986 +/* Default all talk protocols are supported */
5987 +static int talk = 1;
5988 +static int ntalk = 1;
5989 +static int ntalk2 = 1;
5990 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5991 +MODULE_DESCRIPTION("talk connection tracking module");
5992 +MODULE_LICENSE("GPL");
5993 +#ifdef MODULE_PARM
5994 +MODULE_PARM(talk, "i");
5995 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5996 +MODULE_PARM(ntalk, "i");
5997 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5998 +MODULE_PARM(ntalk2, "i");
5999 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
6000 +#endif
6001 +
6002 +DECLARE_LOCK(ip_talk_lock);
6003 +struct module *ip_conntrack_talk = THIS_MODULE;
6004 +
6005 +#if 0
6006 +#define DEBUGP printk
6007 +#else
6008 +#define DEBUGP(format, args...)
6009 +#endif
6010 +
6011 +static int talk_expect(struct ip_conntrack *ct);
6012 +static int ntalk_expect(struct ip_conntrack *ct);
6013 +
6014 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
6015 +
6016 +static int talk_help_response(const struct iphdr *iph, size_t len,
6017 +                             struct ip_conntrack *ct,
6018 +                             enum ip_conntrack_info ctinfo,
6019 +                             int talk_port,
6020 +                             u_char mode,
6021 +                             u_char type,
6022 +                             u_char answer,
6023 +                             struct talk_addr *addr)
6024 +{
6025 +       int dir = CTINFO2DIR(ctinfo);
6026 +       struct ip_conntrack_expect expect, *exp = &expect;
6027 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
6028 +
6029 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
6030 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
6031 +               type, answer);
6032 +
6033 +       if (!(answer == SUCCESS && type == mode))
6034 +               return NF_ACCEPT;
6035 +       
6036 +       memset(&expect, 0, sizeof(expect));
6037 +       
6038 +       if (type == ANNOUNCE) {
6039 +
6040 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
6041 +
6042 +               /* update the talk info */
6043 +               LOCK_BH(&ip_talk_lock);
6044 +               exp_talk_info->port = htons(talk_port);
6045 +
6046 +               /* expect callee client -> caller server message */
6047 +               exp->tuple = ((struct ip_conntrack_tuple)
6048 +                       { { ct->tuplehash[dir].tuple.src.ip,
6049 +                           { 0 } },
6050 +                         { ct->tuplehash[dir].tuple.dst.ip,
6051 +                           { .tcp = { htons(talk_port) } },
6052 +                           IPPROTO_UDP }});
6053 +               exp->mask = ((struct ip_conntrack_tuple)
6054 +                       { { 0xFFFFFFFF, { 0 } },
6055 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6056 +               
6057 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
6058 +
6059 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
6060 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
6061 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
6062 +
6063 +               /* Ignore failure; should only happen with NAT */
6064 +               ip_conntrack_expect_related(ct, &expect);
6065 +               UNLOCK_BH(&ip_talk_lock);
6066 +       }
6067 +       if (type == LOOK_UP) {
6068 +
6069 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
6070 +
6071 +               /* update the talk info */
6072 +               LOCK_BH(&ip_talk_lock);
6073 +               exp_talk_info->port = addr->ta_port;
6074 +
6075 +               /* expect callee client -> caller client connection */
6076 +               exp->tuple = ((struct ip_conntrack_tuple)
6077 +                       { { ct->tuplehash[!dir].tuple.src.ip,
6078 +                           { 0 } },
6079 +                         { addr->ta_addr,
6080 +                           { addr->ta_port },
6081 +                           IPPROTO_TCP }});
6082 +               exp->mask = ((struct ip_conntrack_tuple)
6083 +                       { { 0xFFFFFFFF, { 0 } },
6084 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6085 +               
6086 +               exp->expectfn = NULL;
6087 +               
6088 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
6089 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
6090 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
6091 +
6092 +               /* Ignore failure; should only happen with NAT */
6093 +               ip_conntrack_expect_related(ct, &expect);
6094 +               UNLOCK_BH(&ip_talk_lock);
6095 +       }
6096 +                   
6097 +       return NF_ACCEPT;
6098 +}
6099 +
6100 +/* FIXME: This should be in userspace.  Later. */
6101 +static int talk_help(const struct iphdr *iph, size_t len,
6102 +                    struct ip_conntrack *ct,
6103 +                    enum ip_conntrack_info ctinfo,
6104 +                    int talk_port,
6105 +                    u_char mode)
6106 +{
6107 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
6108 +       const char *data = (const char *)udph + sizeof(struct udphdr);
6109 +       int dir = CTINFO2DIR(ctinfo);
6110 +       size_t udplen;
6111 +
6112 +       DEBUGP("ip_ct_talk_help: help entered\n");
6113 +
6114 +       /* Until there's been traffic both ways, don't look in packets. */
6115 +       if (ctinfo != IP_CT_ESTABLISHED
6116 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6117 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
6118 +               return NF_ACCEPT;
6119 +       }
6120 +
6121 +       /* Not whole UDP header? */
6122 +       udplen = len - iph->ihl * 4;
6123 +       if (udplen < sizeof(struct udphdr)) {
6124 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
6125 +               return NF_ACCEPT;
6126 +       }
6127 +
6128 +       /* Checksum invalid?  Ignore. */
6129 +       /* FIXME: Source route IP option packets --RR */
6130 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6131 +                             csum_partial((char *)udph, udplen, 0))) {
6132 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6133 +                      udph, udplen, NIPQUAD(iph->saddr),
6134 +                      NIPQUAD(iph->daddr));
6135 +               return NF_ACCEPT;
6136 +       }
6137 +       
6138 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6139 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
6140 +
6141 +       if (dir == IP_CT_DIR_ORIGINAL)
6142 +               return NF_ACCEPT;
6143 +               
6144 +       if (talk_port == TALK_PORT
6145 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6146 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6147 +                                         ((struct talk_response *)data)->type, 
6148 +                                         ((struct talk_response *)data)->answer,
6149 +                                         &(((struct talk_response *)data)->addr));
6150 +       else if (talk_port == NTALK_PORT
6151 +                 && ntalk
6152 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6153 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6154 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6155 +                                         ((struct ntalk_response *)data)->type, 
6156 +                                         ((struct ntalk_response *)data)->answer,
6157 +                                         &(((struct ntalk_response *)data)->addr));
6158 +       else if (talk_port == NTALK_PORT
6159 +                && ntalk2
6160 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6161 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6162 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6163 +                                         ((struct ntalk2_response *)data)->type, 
6164 +                                         ((struct ntalk2_response *)data)->answer,
6165 +                                         &(((struct ntalk2_response *)data)->addr));
6166 +       else {
6167 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
6168 +                      (unsigned)udplen - sizeof(struct udphdr), 
6169 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6170 +               return NF_ACCEPT;
6171 +       }
6172 +}
6173 +
6174 +static int lookup_help(const struct iphdr *iph, size_t len,
6175 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6176 +{
6177 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
6178 +}
6179 +
6180 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
6181 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6182 +{
6183 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
6184 +}
6185 +
6186 +static struct ip_conntrack_helper lookup_helpers[2] = 
6187 +       { { { NULL, NULL },
6188 +           "talk",                                     /* name */
6189 +           0,                                          /* flags */
6190 +           NULL,                                       /* module */
6191 +           1,                                          /* max_expected */
6192 +           240,                                        /* timeout */
6193 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
6194 +             { 0, { 0 }, IPPROTO_UDP } },
6195 +           { { 0, { 0xFFFF } },                        /* mask */
6196 +             { 0, { 0 }, 0xFFFF } },
6197 +           lookup_help },                              /* helper */
6198 +          { { NULL, NULL },
6199 +            "ntalk",                                   /* name */
6200 +           0,                                          /* flags */
6201 +           NULL,                                       /* module */
6202 +           1,                                          /* max_expected */
6203 +           240,                                        /* timeout */
6204 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
6205 +             { 0, { 0 }, IPPROTO_UDP } },
6206 +           { { 0, { 0xFFFF } },                        /* mask */
6207 +             { 0, { 0 }, 0xFFFF } },
6208 +           lookup_nhelp }                              /* helper */
6209 +        };
6210 +
6211 +static int talk_expect(struct ip_conntrack *ct)
6212 +{
6213 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
6214 +       WRITE_LOCK(&ip_conntrack_lock);
6215 +       ct->helper = &lookup_helpers[0];
6216 +       WRITE_UNLOCK(&ip_conntrack_lock);
6217 +        
6218 +       return NF_ACCEPT;       /* unused */
6219 +}
6220 +
6221 +static int ntalk_expect(struct ip_conntrack *ct)
6222 +{
6223 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
6224 +       WRITE_LOCK(&ip_conntrack_lock);
6225 +       ct->helper = &lookup_helpers[1];
6226 +       WRITE_UNLOCK(&ip_conntrack_lock);
6227 +        
6228 +       return NF_ACCEPT;       /* unused */
6229 +}
6230 +
6231 +static int help(const struct iphdr *iph, size_t len,
6232 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6233 +{
6234 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
6235 +}
6236 +
6237 +static int nhelp(const struct iphdr *iph, size_t len,
6238 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6239 +{
6240 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
6241 +}
6242 +
6243 +static struct ip_conntrack_helper talk_helpers[2] = 
6244 +       { { { NULL, NULL },
6245 +           "talk",                                     /* name */
6246 +           0,                                          /* flags */
6247 +           THIS_MODULE,                                /* module */
6248 +           1,                                          /* max_expected */
6249 +           240,                                        /* timeout */
6250 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
6251 +             { 0, { 0 }, IPPROTO_UDP } },
6252 +           { { 0, { 0xFFFF } },                        /* mask */
6253 +             { 0, { 0 }, 0xFFFF } },
6254 +           help },                                     /* helper */
6255 +          { { NULL, NULL },
6256 +           "ntalk",                                    /* name */
6257 +           0,                                          /* flags */
6258 +           THIS_MODULE,                                /* module */
6259 +           1,                                          /* max_expected */
6260 +           240,                                        /* timeout */
6261 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
6262 +             { 0, { 0 }, IPPROTO_UDP } },
6263 +           { { 0, { 0xFFFF } },                        /* mask */
6264 +             { 0, { 0 }, 0xFFFF } },
6265 +           nhelp }                                     /* helper */
6266 +       };
6267 +
6268 +static int __init init(void)
6269 +{
6270 +       if (talk > 0)
6271 +               ip_conntrack_helper_register(&talk_helpers[0]);
6272 +       if (ntalk > 0 || ntalk2 > 0)
6273 +               ip_conntrack_helper_register(&talk_helpers[1]);
6274 +               
6275 +       return 0;
6276 +}
6277 +
6278 +static void __exit fini(void)
6279 +{
6280 +       if (talk > 0)
6281 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
6282 +       if (ntalk > 0 || ntalk2 > 0)
6283 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
6284 +}
6285 +
6286 +EXPORT_SYMBOL(ip_talk_lock);
6287 +
6288 +module_init(init);
6289 +module_exit(fini);
6290 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.6/net/ipv4/netfilter/ip_nat_core.c
6291 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_core.c    2004-05-10 04:32:01.000000000 +0200
6292 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_core.c        2004-05-18 12:35:39.000000000 +0200
6293 @@ -816,7 +816,7 @@
6294  
6295                 /* Have to grab read lock before sibling_list traversal */
6296                 READ_LOCK(&ip_conntrack_lock);
6297 -               list_for_each(cur_item, &ct->sibling_list) { 
6298 +               list_for_each_prev(cur_item, &ct->sibling_list) { 
6299                         exp = list_entry(cur_item, struct ip_conntrack_expect, 
6300                                          expected_list);
6301                                          
6302 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6/net/ipv4/netfilter/ip_nat_h323.c
6303 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_h323.c    1970-01-01 01:00:00.000000000 +0100
6304 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_h323.c        2004-05-18 12:39:18.000000000 +0200
6305 @@ -0,0 +1,419 @@
6306 +/* 
6307 + * H.323 'brute force' extension for NAT alteration. 
6308 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6309 + *
6310 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6311 + * (http://www.coritel.it/projects/sofia/nat.html)
6312 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6313 + * the unregistered helpers to the conntrack entries.
6314 + */
6315 +
6316 +
6317 +#include <linux/module.h>
6318 +#include <linux/netfilter.h>
6319 +#include <linux/ip.h>
6320 +#include <net/checksum.h>
6321 +#include <net/tcp.h>
6322 +
6323 +#include <linux/netfilter_ipv4/lockhelp.h>
6324 +#include <linux/netfilter_ipv4/ip_nat.h>
6325 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6326 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6327 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6328 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6329 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6330 +
6331 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6332 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6333 +MODULE_LICENSE("GPL");
6334 +
6335 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6336 +struct module *ip_nat_h323 = THIS_MODULE;
6337 +
6338 +#if 0
6339 +#define DEBUGP printk
6340 +#else
6341 +#define DEBUGP(format, args...)
6342 +#endif
6343 +
6344 +/* FIXME: Time out? --RR */
6345 +
6346 +static unsigned int 
6347 +h225_nat_expected(struct sk_buff **pskb,
6348 +                 unsigned int hooknum,
6349 +                 struct ip_conntrack *ct,
6350 +                 struct ip_nat_info *info);
6351 +
6352 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6353 +                                 struct ip_conntrack_expect *exp,
6354 +                                 struct ip_nat_info *info,
6355 +                                 enum ip_conntrack_info ctinfo,
6356 +                                 unsigned int hooknum,
6357 +                                 struct sk_buff **pskb);
6358 +                 
6359 +static struct ip_nat_helper h245 = 
6360 +       { { NULL, NULL },
6361 +          "H.245",                             /* name */
6362 +         0,                                    /* flags */
6363 +         NULL,                                 /* module */
6364 +         { { 0, { 0 } },                       /* tuple */
6365 +           { 0, { 0 }, IPPROTO_TCP } },
6366 +         { { 0, { 0xFFFF } },                  /* mask */
6367 +           { 0, { 0 }, 0xFFFF } },
6368 +         h225_nat_help,                        /* helper */
6369 +         h225_nat_expected                     /* expectfn */
6370 +       };
6371 +
6372 +static unsigned int
6373 +h225_nat_expected(struct sk_buff **pskb,
6374 +                 unsigned int hooknum,
6375 +                 struct ip_conntrack *ct,
6376 +                 struct ip_nat_info *info)
6377 +{
6378 +       struct ip_nat_multi_range mr;
6379 +       u_int32_t newdstip, newsrcip, newip;
6380 +       u_int16_t port;
6381 +       struct ip_ct_h225_expect *exp_info;
6382 +       struct ip_ct_h225_master *master_info;
6383 +       struct ip_conntrack *master = master_ct(ct);
6384 +       unsigned int is_h225, ret;
6385 +       
6386 +       IP_NF_ASSERT(info);
6387 +       IP_NF_ASSERT(master);
6388 +
6389 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6390 +
6391 +       DEBUGP("h225_nat_expected: We have a connection!\n");
6392 +       master_info = &ct->master->expectant->help.ct_h225_info;
6393 +       exp_info = &ct->master->help.exp_h225_info;
6394 +
6395 +       LOCK_BH(&ip_h323_lock);
6396 +
6397 +       DEBUGP("master: ");
6398 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6399 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6400 +       DEBUGP("conntrack: ");
6401 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6402 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6403 +               /* Make connection go to the client. */
6404 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6405 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6406 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6407 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6408 +       } else {
6409 +               /* Make the connection go to the server */
6410 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6411 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6412 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6413 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6414 +       }
6415 +       port = exp_info->port;
6416 +       is_h225 = master_info->is_h225 == H225_PORT;
6417 +       UNLOCK_BH(&ip_h323_lock);
6418 +       
6419 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6420 +               newip = newsrcip;
6421 +       else
6422 +               newip = newdstip;
6423 +
6424 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6425 +
6426 +       mr.rangesize = 1;
6427 +       /* We don't want to manip the per-protocol, just the IPs... */
6428 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6429 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6430 +
6431 +       /* ... unless we're doing a MANIP_DST, in which case, make
6432 +          sure we map to the correct port */
6433 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6434 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6435 +               mr.range[0].min = mr.range[0].max
6436 +                       = ((union ip_conntrack_manip_proto)
6437 +                               { .tcp = { port } });
6438 +       }
6439 +
6440 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
6441 +       
6442 +       if (is_h225) {
6443 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6444 +               /* NAT expectfn called with ip_nat_lock write-locked */
6445 +               info->helper = &h245;
6446 +       }
6447 +       return ret;
6448 +}
6449 +
6450 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6451 +                                    struct sk_buff **pskb,
6452 +                                    enum ip_conntrack_info ctinfo)
6453 +{
6454 +       struct iphdr *iph = (*pskb)->nh.iph;
6455 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6456 +       char *data = (char *) tcph + tcph->doff * 4;
6457 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6458 +       u_int32_t datalen = tcplen - tcph->doff*4;
6459 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
6460 +       u_int32_t newip;
6461 +       u_int16_t port;
6462 +       int i;
6463 +
6464 +       MUST_BE_LOCKED(&ip_h323_lock);
6465 +
6466 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
6467 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6468 +                       ? "yes" : "no",
6469 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6470 +                       ? "yes" : "no");
6471 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6472 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6473 +               return 1;
6474 +
6475 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
6476 +               info->offset[IP_CT_DIR_ORIGINAL], 
6477 +               info->offset[IP_CT_DIR_REPLY],
6478 +               tcplen);
6479 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6480 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6481 +
6482 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
6483 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
6484 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6485 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6486 +               if (!between(info->seq[i], ntohl(tcph->seq), 
6487 +                            ntohl(tcph->seq) + datalen))
6488 +                       continue;
6489 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6490 +                            ntohl(tcph->seq) + datalen)) {
6491 +                       /* Partial retransmisison. It's a cracker being funky. */
6492 +                       if (net_ratelimit()) {
6493 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6494 +                                    info->seq[i],
6495 +                                    ntohl(tcph->seq),
6496 +                                    ntohl(tcph->seq) + datalen);
6497 +                       }
6498 +                       return 0;
6499 +               }
6500 +
6501 +               /* Change address inside packet to match way we're mapping
6502 +                  this connection. */
6503 +               if (i == IP_CT_DIR_ORIGINAL) {
6504 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6505 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6506 +               } else {
6507 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
6508 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6509 +               }
6510 +
6511 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
6512 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6513 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6514 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6515 +
6516 +               /* Modify the packet */
6517 +               *(u_int32_t *)(data + info->offset[i]) = newip;
6518 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
6519 +       
6520 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
6521 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6522 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6523 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6524 +       }
6525 +
6526 +       /* fix checksum information */
6527 +
6528 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6529 +                                    datalen, 0);
6530 +
6531 +       tcph->check = 0;
6532 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6533 +                                  csum_partial((char *)tcph, tcph->doff*4,
6534 +                                          (*pskb)->csum));
6535 +       ip_send_check(iph);
6536 +
6537 +       return 1;
6538 +}
6539 +
6540 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6541 +                          struct ip_conntrack *ct,
6542 +                          struct sk_buff **pskb,
6543 +                          enum ip_conntrack_info ctinfo,
6544 +                          struct ip_conntrack_expect *expect)
6545 +{
6546 +       u_int32_t newip;
6547 +       u_int16_t port;
6548 +       struct ip_conntrack_tuple newtuple;
6549 +       struct iphdr *iph = (*pskb)->nh.iph;
6550 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6551 +       char *data = (char *) tcph + tcph->doff * 4;
6552 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6553 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6554 +       int is_h225;
6555 +
6556 +       MUST_BE_LOCKED(&ip_h323_lock);
6557 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6558 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6559 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6560 +
6561 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
6562 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6563 +               /* Partial retransmisison. It's a cracker being funky. */
6564 +               if (net_ratelimit()) {
6565 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6566 +                            expect->seq,
6567 +                            ntohl(tcph->seq),
6568 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6569 +               }
6570 +               return 0;
6571 +       }
6572 +
6573 +       /* Change address inside packet to match way we're mapping
6574 +          this connection. */
6575 +       if (info->dir == IP_CT_DIR_REPLY) {
6576 +               /* Must be where client thinks server is */
6577 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6578 +               /* Expect something from client->server */
6579 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6580 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6581 +       } else {
6582 +               /* Must be where server thinks client is */
6583 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6584 +               /* Expect something from server->client */
6585 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6586 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6587 +       }
6588 +
6589 +       is_h225 = (master_info->is_h225 == H225_PORT);
6590 +
6591 +       if (is_h225) {
6592 +               newtuple.dst.protonum = IPPROTO_TCP;
6593 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6594 +       } else {
6595 +               newtuple.dst.protonum = IPPROTO_UDP;
6596 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6597 +       }
6598 +       
6599 +       /* Try to get same port: if not, try to change it. */
6600 +       for (port = ntohs(info->port); port != 0; port++) {
6601 +               if (is_h225)
6602 +                       newtuple.dst.u.tcp.port = htons(port);
6603 +               else
6604 +                       newtuple.dst.u.udp.port = htons(port);
6605 +
6606 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6607 +                       break;
6608 +       }
6609 +       if (port == 0) {
6610 +               DEBUGP("h323_data_fixup: no free port found!\n");
6611 +               return 0;
6612 +       }
6613 +
6614 +       port = htons(port);
6615 +
6616 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
6617 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6618 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6619 +
6620 +       /* Modify the packet */
6621 +       *(u_int32_t *)(data + info->offset) = newip;
6622 +       *(u_int16_t *)(data + info->offset + 4) = port;
6623 +       
6624 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
6625 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6626 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6627 +
6628 +       /* fix checksum information  */
6629 +       /* FIXME: usually repeated multiple times in the case of H.245! */
6630 +
6631 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6632 +                                    tcplen - tcph->doff*4, 0);
6633 +
6634 +       tcph->check = 0;
6635 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6636 +                                  csum_partial((char *)tcph, tcph->doff*4,
6637 +                                          (*pskb)->csum));
6638 +       ip_send_check(iph);
6639 +
6640 +       return 1;
6641 +}
6642 +
6643 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6644 +                                 struct ip_conntrack_expect *exp,
6645 +                                 struct ip_nat_info *info,
6646 +                                 enum ip_conntrack_info ctinfo,
6647 +                                 unsigned int hooknum,
6648 +                                 struct sk_buff **pskb)
6649 +{
6650 +       int dir;
6651 +       struct ip_ct_h225_expect *exp_info;
6652 +       
6653 +       /* Only mangle things once: original direction in POST_ROUTING
6654 +          and reply direction on PRE_ROUTING. */
6655 +       dir = CTINFO2DIR(ctinfo);
6656 +       DEBUGP("nat_h323: dir %s at hook %s\n",
6657 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6658 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6659 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6660 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6661 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6662 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6663 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6664 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6665 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6666 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6667 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6668 +               return NF_ACCEPT;
6669 +       }
6670 +
6671 +       if (!exp) {
6672 +               LOCK_BH(&ip_h323_lock);
6673 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6674 +                       UNLOCK_BH(&ip_h323_lock);
6675 +                       return NF_DROP;
6676 +               }
6677 +               UNLOCK_BH(&ip_h323_lock);
6678 +               return NF_ACCEPT;
6679 +       }
6680 +               
6681 +       exp_info = &exp->help.exp_h225_info;
6682 +
6683 +       LOCK_BH(&ip_h323_lock);
6684 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6685 +               UNLOCK_BH(&ip_h323_lock);
6686 +               return NF_DROP;
6687 +       }
6688 +       UNLOCK_BH(&ip_h323_lock);
6689 +
6690 +       return NF_ACCEPT;
6691 +}
6692 +
6693 +static struct ip_nat_helper h225 = 
6694 +       { { NULL, NULL },
6695 +         "H.225",                                      /* name */
6696 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
6697 +         THIS_MODULE,                                  /* module */
6698 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
6699 +           { 0, { 0 }, IPPROTO_TCP } },
6700 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
6701 +           { 0, { 0 }, 0xFFFF } },
6702 +         h225_nat_help,                                /* helper */
6703 +         h225_nat_expected                             /* expectfn */
6704 +       };
6705 +
6706 +static int __init init(void)
6707 +{
6708 +       int ret;
6709 +       
6710 +       ret = ip_nat_helper_register(&h225);
6711 +
6712 +       if (ret != 0)
6713 +               printk("ip_nat_h323: cannot initialize the module!\n");
6714 +
6715 +       return ret;
6716 +}
6717 +
6718 +static void __exit fini(void)
6719 +{
6720 +       ip_nat_helper_unregister(&h225);
6721 +}
6722 +
6723 +module_init(init);
6724 +module_exit(fini);
6725 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6/net/ipv4/netfilter/ip_nat_mms.c
6726 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_mms.c     1970-01-01 01:00:00.000000000 +0100
6727 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_mms.c 2004-05-18 12:39:36.000000000 +0200
6728 @@ -0,0 +1,350 @@
6729 +/* MMS extension for TCP NAT alteration.
6730 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6731 + * based on ip_nat_ftp.c and ip_nat_irc.c
6732 + *
6733 + * ip_nat_mms.c v0.3 2002-09-22
6734 + *
6735 + *      This program is free software; you can redistribute it and/or
6736 + *      modify it under the terms of the GNU General Public License
6737 + *      as published by the Free Software Foundation; either version
6738 + *      2 of the License, or (at your option) any later version.
6739 + *
6740 + *      Module load syntax:
6741 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6742 + *
6743 + *      Please give the ports of all MMS servers You wish to connect to.
6744 + *      If you don't specify ports, the default will be TCP port 1755.
6745 + *
6746 + *      More info on MMS protocol, firewalls and NAT:
6747 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6748 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6749 + *
6750 + *      The SDP project people are reverse-engineering MMS:
6751 + *      http://get.to/sdp
6752 + */
6753 +
6754 +/* FIXME: issue with UDP & fragmentation with this URL: 
6755 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
6756 +   may be related to out-of-order first packets:
6757 +   basically the expectation is set up correctly, then the server sends
6758 +   a first UDP packet which is fragmented plus arrives out-of-order.
6759 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
6760 +   an ICMP unreachable back to the server */
6761 +
6762 +#include <linux/module.h>
6763 +#include <linux/netfilter_ipv4.h>
6764 +#include <linux/ip.h>
6765 +#include <linux/tcp.h>
6766 +#include <net/tcp.h>
6767 +#include <linux/netfilter_ipv4/ip_nat.h>
6768 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6769 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6770 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6771 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6772 +
6773 +#if 0 
6774 +#define DEBUGP printk
6775 +#define DUMP_BYTES(address, counter)                                \
6776 +({                                                                  \
6777 +       int temp_counter;                                           \
6778 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6779 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
6780 +       };                                                          \
6781 +       DEBUGP("\n");                                               \
6782 +})
6783 +#else
6784 +#define DEBUGP(format, args...)
6785 +#define DUMP_BYTES(address, counter)
6786 +#endif
6787 +
6788 +#define MAX_PORTS 8
6789 +static int ports[MAX_PORTS];
6790 +static int ports_c = 0;
6791 +
6792 +#ifdef MODULE_PARM
6793 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6794 +#endif
6795 +
6796 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6797 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6798 +MODULE_LICENSE("GPL");
6799 +
6800 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6801 +
6802 +/* FIXME: Time out? --RR */
6803 +
6804 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6805 +                          struct ip_conntrack *ct,
6806 +                          struct sk_buff **pskb,
6807 +                          enum ip_conntrack_info ctinfo,
6808 +                          struct ip_conntrack_expect *expect)
6809 +{
6810 +       u_int32_t newip;
6811 +       struct ip_conntrack_tuple t;
6812 +       struct iphdr *iph = (*pskb)->nh.iph;
6813 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6814 +       char *data = (char *)tcph + tcph->doff * 4;
6815 +       int i, j, k, port;
6816 +       u_int16_t mms_proto;
6817 +
6818 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6819 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6820 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6821 +
6822 +       int zero_padding;
6823 +
6824 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6825 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6826 +       char proto_string[6];
6827 +       
6828 +       MUST_BE_LOCKED(&ip_mms_lock);
6829 +
6830 +       /* what was the protocol again ? */
6831 +       mms_proto = expect->tuple.dst.protonum;
6832 +       sprintf(proto_string, "%u", mms_proto);
6833 +       
6834 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6835 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6836 +              mms_proto == IPPROTO_UDP ? "UDP"
6837 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6838 +       
6839 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6840 +
6841 +       /* Alter conntrack's expectations. */
6842 +       t = expect->tuple;
6843 +       t.dst.ip = newip;
6844 +       for (port = ct_mms_info->port; port != 0; port++) {
6845 +               t.dst.u.tcp.port = htons(port);
6846 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
6847 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6848 +                       break;
6849 +               }
6850 +       }
6851 +       
6852 +       if(port == 0)
6853 +               return 0;
6854 +
6855 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6856 +               NIPQUAD(newip),
6857 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6858 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6859 +               port);
6860 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6861 +       
6862 +       memset(unicode_buffer, 0, sizeof(char)*75);
6863 +
6864 +       for (i=0; i<strlen(buffer); ++i)
6865 +               *(unicode_buffer+i*2)=*(buffer+i);
6866 +       
6867 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6868 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6869 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6870 +       
6871 +       /* add end of packet to it */
6872 +       for (j=0; j<ct_mms_info->padding; ++j) {
6873 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
6874 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6875 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6876 +       }
6877 +
6878 +       /* pad with zeroes at the end ? see explanation of weird math below */
6879 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6880 +       for (k=0; k<zero_padding; ++k)
6881 +               *(unicode_buffer+i*2+j+k)= (char)0;
6882 +       
6883 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6884 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6885 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6886 +       
6887 +       /* explanation, before I forget what I did:
6888 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6889 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
6890 +          but note that things may have to be padded with zeroes to align by 8 
6891 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
6892 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6893 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
6894 +       *mms_messageLength = *mms_chunkLenLV*8;
6895 +       
6896 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6897 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6898 +       
6899 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
6900 +                                expect->seq - ntohl(tcph->seq),
6901 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6902 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6903 +       DUMP_BYTES(unicode_buffer, 60);
6904 +       
6905 +       return 1;
6906 +}
6907 +
6908 +static unsigned int
6909 +mms_nat_expected(struct sk_buff **pskb,
6910 +                 unsigned int hooknum,
6911 +                 struct ip_conntrack *ct,
6912 +                 struct ip_nat_info *info)
6913 +{
6914 +       struct ip_nat_multi_range mr;
6915 +       u_int32_t newdstip, newsrcip, newip;
6916 +
6917 +       struct ip_conntrack *master = master_ct(ct);
6918 +
6919 +       IP_NF_ASSERT(info);
6920 +       IP_NF_ASSERT(master);
6921 +
6922 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6923 +
6924 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6925 +
6926 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6927 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6928 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6929 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6930 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6931 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6932 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
6933 +
6934 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6935 +               newip = newsrcip;
6936 +       else
6937 +               newip = newdstip;
6938 +
6939 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6940 +
6941 +       mr.rangesize = 1;
6942 +       /* We don't want to manip the per-protocol, just the IPs. */
6943 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6944 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6945 +
6946 +       return ip_nat_setup_info(ct, &mr, hooknum);
6947 +}
6948 +
6949 +
6950 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6951 +                        struct ip_conntrack_expect *exp,
6952 +                        struct ip_nat_info *info,
6953 +                        enum ip_conntrack_info ctinfo,
6954 +                        unsigned int hooknum,
6955 +                        struct sk_buff **pskb)
6956 +{
6957 +       struct iphdr *iph = (*pskb)->nh.iph;
6958 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6959 +       unsigned int datalen;
6960 +       int dir;
6961 +       struct ip_ct_mms_expect *ct_mms_info;
6962 +
6963 +       if (!exp)
6964 +               DEBUGP("ip_nat_mms: no exp!!");
6965 +
6966 +       ct_mms_info = &exp->help.exp_mms_info;
6967 +       
6968 +       /* Only mangle things once: original direction in POST_ROUTING
6969 +          and reply direction on PRE_ROUTING. */
6970 +       dir = CTINFO2DIR(ctinfo);
6971 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6972 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6973 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6974 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6975 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6976 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6977 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6978 +               return NF_ACCEPT;
6979 +       }
6980 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6981 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6982 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6983 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6984 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6985 +       
6986 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6987 +       
6988 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6989 +              exp->seq + ct_mms_info->len,
6990 +              ntohl(tcph->seq),
6991 +              ntohl(tcph->seq) + datalen);
6992 +       
6993 +       LOCK_BH(&ip_mms_lock);
6994 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
6995 +       if (between(exp->seq + ct_mms_info->len,
6996 +           ntohl(tcph->seq),
6997 +           ntohl(tcph->seq) + datalen)) {
6998 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6999 +                       UNLOCK_BH(&ip_mms_lock);
7000 +                       return NF_DROP;
7001 +               }
7002 +       } else {
7003 +               /* Half a match?  This means a partial retransmisison.
7004 +                  It's a cracker being funky. */
7005 +               if (net_ratelimit()) {
7006 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
7007 +                              exp->seq, ct_mms_info->len,
7008 +                              ntohl(tcph->seq),
7009 +                              ntohl(tcph->seq) + datalen);
7010 +               }
7011 +               UNLOCK_BH(&ip_mms_lock);
7012 +               return NF_DROP;
7013 +       }
7014 +       UNLOCK_BH(&ip_mms_lock);
7015 +       
7016 +       return NF_ACCEPT;
7017 +}
7018 +
7019 +static struct ip_nat_helper mms[MAX_PORTS];
7020 +static char mms_names[MAX_PORTS][10];
7021 +
7022 +/* Not __exit: called from init() */
7023 +static void fini(void)
7024 +{
7025 +       int i;
7026 +
7027 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7028 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
7029 +               ip_nat_helper_unregister(&mms[i]);
7030 +       }
7031 +}
7032 +
7033 +static int __init init(void)
7034 +{
7035 +       int i, ret = 0;
7036 +       char *tmpname;
7037 +
7038 +       if (ports[0] == 0)
7039 +               ports[0] = MMS_PORT;
7040 +
7041 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7042 +
7043 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
7044 +
7045 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
7046 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
7047 +               mms[i].mask.dst.protonum = 0xFFFF;
7048 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
7049 +               mms[i].help = mms_nat_help;
7050 +               mms[i].me = THIS_MODULE;
7051 +               mms[i].flags = 0;
7052 +               mms[i].expect = mms_nat_expected;
7053 +
7054 +               tmpname = &mms_names[i][0];
7055 +               if (ports[i] == MMS_PORT)
7056 +                       sprintf(tmpname, "mms");
7057 +               else
7058 +                       sprintf(tmpname, "mms-%d", i);
7059 +               mms[i].name = tmpname;
7060 +
7061 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
7062 +                               ports[i]);
7063 +               ret = ip_nat_helper_register(&mms[i]);
7064 +
7065 +               if (ret) {
7066 +                       printk("ip_nat_mms: error registering "
7067 +                              "helper for port %d\n", ports[i]);
7068 +                       fini();
7069 +                       return ret;
7070 +               }
7071 +               ports_c++;
7072 +       }
7073 +
7074 +       return ret;
7075 +}
7076 +
7077 +module_init(init);
7078 +module_exit(fini);
7079 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6/net/ipv4/netfilter/ip_nat_quake3.c
7080 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_quake3.c  1970-01-01 01:00:00.000000000 +0100
7081 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_quake3.c      2004-05-18 12:40:06.000000000 +0200
7082 @@ -0,0 +1,249 @@
7083 +/* Quake3 extension for UDP NAT alteration.
7084 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7085 + * based on ip_nat_ftp.c and ip_nat_tftp.c
7086 + *
7087 + * ip_nat_quake3.c v0.0.3 2002-08-31
7088 + *
7089 + *      This program is free software; you can redistribute it and/or
7090 + *      modify it under the terms of the GNU General Public License
7091 + *      as published by the Free Software Foundation; either version
7092 + *      2 of the License, or (at your option) any later version.
7093 + *
7094 + *      Module load syntax:
7095 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
7096 + *
7097 + *      please give the ports of all Quake3 master servers You wish to
7098 + *      connect to. If you don't specify ports, the default will be UDP
7099 + *      port 27950.
7100 + *
7101 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
7102 + *
7103 + *      Notes: 
7104 + *      - If you're one of those people who would try anything to lower
7105 + *        latency while playing Quake (and who isn't :-) ), you may want to
7106 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
7107 + *        outgoing UDP traffic.
7108 + *        This will make ip_conntrack_quake3 add the necessary expectations,
7109 + *        but there will be no overhead for client->server UDP streams. If
7110 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
7111 + *        hook for every packet in the client->server UDP stream.
7112 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
7113 + *        The IP addresses in the master connection payload (=IP addresses
7114 + *        of Quake servers) have no relation with the master server so
7115 + *        DNAT'ing the master connection to a server should not change the
7116 + *        expected connections.
7117 + *      - Not tested due to lack of equipment:
7118 + *        - multiple Quake3 clients behind one MASQUERADE gateway
7119 + *        - what if Quake3 client is running on router too
7120 + */
7121 +
7122 +#include <linux/module.h>
7123 +#include <linux/netfilter_ipv4.h>
7124 +#include <linux/ip.h>
7125 +#include <linux/udp.h>
7126 +
7127 +#include <linux/netfilter.h>
7128 +#include <linux/netfilter_ipv4/ip_tables.h>
7129 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7130 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
7131 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7132 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7133 +
7134 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7135 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
7136 +MODULE_LICENSE("GPL");
7137 +
7138 +#define MAX_PORTS 8
7139 +
7140 +static int ports[MAX_PORTS];
7141 +static int ports_c = 0;
7142 +#ifdef MODULE_PARM
7143 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7144 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7145 +#endif
7146 +
7147 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7148 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7149 +#if 0 
7150 +#define DEBUGP printk
7151 +#else
7152 +#define DEBUGP(format, args...)
7153 +#endif
7154 +
7155 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7156 +
7157 +static unsigned int 
7158 +quake3_nat_help(struct ip_conntrack *ct,
7159 +                struct ip_conntrack_expect *exp,
7160 +                struct ip_nat_info *info,
7161 +                enum ip_conntrack_info ctinfo,
7162 +                unsigned int hooknum,
7163 +                struct sk_buff **pskb)
7164 +{
7165 +       struct iphdr *iph = (*pskb)->nh.iph;
7166 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7167 +       struct ip_conntrack_tuple repl;
7168 +       int dir = CTINFO2DIR(ctinfo);
7169 +       int i;
7170 +       
7171 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7172 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7173 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7174 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7175 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7176 +             );
7177 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7178 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7179 +       
7180 +       /* Only mangle things once: original direction in POST_ROUTING
7181 +          and reply direction on PRE_ROUTING. */
7182 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7183 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7184 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7185 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7186 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7187 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7188 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7189 +               return NF_ACCEPT;
7190 +       }
7191 +
7192 +       if (!exp) {
7193 +               DEBUGP("no conntrack expectation to modify\n");
7194 +               return NF_ACCEPT;
7195 +       }
7196 +
7197 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7198 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7199 +                   i+6 < ntohs(udph->len);
7200 +                   i+=7) {
7201 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
7202 +                              i, ntohs(udph->len),
7203 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7204 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7205 +                       
7206 +                       memset(&repl, 0, sizeof(repl));
7207 +
7208 +                       repl.dst.protonum = IPPROTO_UDP;
7209 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7210 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7211 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
7212 +                       
7213 +                       ip_conntrack_change_expect(exp, &repl);
7214 +               }
7215 +       }
7216 +       return NF_ACCEPT;
7217 +}
7218 +
7219 +static unsigned int 
7220 +quake3_nat_expected(struct sk_buff **pskb,
7221 +                    unsigned int hooknum,
7222 +                    struct ip_conntrack *ct, 
7223 +                    struct ip_nat_info *info) 
7224 +{
7225 +       const struct ip_conntrack *master = ct->master->expectant;
7226 +       struct ip_nat_multi_range mr;
7227 +       u_int32_t newsrcip, newdstip, newip;
7228 +#if 0 
7229 +       const struct ip_conntrack_tuple *repl =
7230 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7231 +       struct iphdr *iph = (*pskb)->nh.iph;
7232 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
7233 +#endif
7234 +
7235 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7236 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7237 +
7238 +       IP_NF_ASSERT(info);
7239 +       IP_NF_ASSERT(master);
7240 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7241 +       
7242 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7243 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7244 +       
7245 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7246 +               newip = newsrcip;
7247 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7248 +                      "newsrc: %u.%u.%u.%u\n",
7249 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7250 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7251 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7252 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7253 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7254 +                      NIPQUAD(newip));
7255 +               
7256 +       } else {
7257 +               newip = newdstip;
7258 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7259 +                      "newdst: %u.%u.%u.%u\n",
7260 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7261 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7262 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7263 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7264 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7265 +                      NIPQUAD(newip));
7266 +       }
7267 +       
7268 +       mr.rangesize = 1;
7269 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7270 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
7271 +
7272 +       return ip_nat_setup_info(ct,&mr,hooknum);
7273 +}
7274 +
7275 +static struct ip_nat_helper quake3[MAX_PORTS];
7276 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
7277 +
7278 +static void fini(void)
7279 +{
7280 +       int i;
7281 +       
7282 +       for (i = 0 ; i < ports_c; i++) {
7283 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7284 +                      ip_nat_helper_unregister(&quake3[i]);
7285 +       }
7286 +}
7287 +
7288 +static int __init init(void)
7289 +       {
7290 +               int i, ret = 0;
7291 +               char *tmpname;
7292 +
7293 +               if (!ports[0])
7294 +                       ports[0] = QUAKE3_MASTER_PORT;
7295 +               
7296 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7297 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7298 +
7299 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7300 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7301 +                       quake3[i].mask.dst.protonum = 0xFFFF;
7302 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
7303 +                       quake3[i].help = quake3_nat_help;
7304 +                       quake3[i].flags = 0;
7305 +                       quake3[i].me = THIS_MODULE;
7306 +                       quake3[i].expect = quake3_nat_expected;
7307 +                       
7308 +                       tmpname = &quake3_names[i][0];
7309 +                       if (ports[i] == QUAKE3_MASTER_PORT)
7310 +                               sprintf(tmpname, "quake3");
7311 +                       else
7312 +                               sprintf(tmpname, "quake3-%d", i);
7313 +                       quake3[i].name = tmpname;
7314 +                       
7315 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7316 +                              ports[i], quake3[i].name);
7317 +                       ret = ip_nat_helper_register(&quake3[i]);
7318 +                       
7319 +                       if (ret) {
7320 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
7321 +                                      ports[i]);
7322 +                               fini();
7323 +                               return ret;
7324 +                       }
7325 +                       ports_c++;
7326 +               }
7327 +               return ret;
7328 +       }
7329 +       
7330 +module_init(init);
7331 +module_exit(fini);
7332 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.6/net/ipv4/netfilter/ip_nat_rtsp.c
7333 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rtsp.c    1970-01-01 01:00:00.000000000 +0100
7334 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_rtsp.c        2004-05-18 12:40:21.000000000 +0200
7335 @@ -0,0 +1,621 @@
7336 +/*
7337 + * RTSP extension for TCP NAT alteration
7338 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7339 + * based on ip_nat_irc.c
7340 + *
7341 + *      This program is free software; you can redistribute it and/or
7342 + *      modify it under the terms of the GNU General Public License
7343 + *      as published by the Free Software Foundation; either version
7344 + *      2 of the License, or (at your option) any later version.
7345 + *
7346 + * Module load syntax:
7347 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7348 + *                           stunaddr=<address>
7349 + *                           destaction=[auto|strip|none]
7350 + *
7351 + * If no ports are specified, the default will be port 554 only.
7352 + *
7353 + * stunaddr specifies the address used to detect that a client is using STUN.
7354 + * If this address is seen in the destination parameter, it is assumed that
7355 + * the client has already punched a UDP hole in the firewall, so we don't
7356 + * mangle the client_port.  If none is specified, it is autodetected.  It
7357 + * only needs to be set if you have multiple levels of NAT.  It should be
7358 + * set to the external address that the STUN clients detect.  Note that in
7359 + * this case, it will not be possible for clients to use UDP with servers
7360 + * between the NATs.
7361 + *
7362 + * If no destaction is specified, auto is used.
7363 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
7364 + *   destaction=strip: always strip destination parameter (not recommended).
7365 + *   destaction=none:  do not touch destination parameter (not recommended).
7366 + */
7367 +
7368 +#include <linux/module.h>
7369 +#include <linux/netfilter_ipv4.h>
7370 +#include <linux/ip.h>
7371 +#include <linux/tcp.h>
7372 +#include <linux/kernel.h>
7373 +#include <net/tcp.h>
7374 +#include <linux/netfilter_ipv4/ip_nat.h>
7375 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7376 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7377 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7378 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7379 +
7380 +#include <linux/inet.h>
7381 +#include <linux/ctype.h>
7382 +#define NF_NEED_STRNCASECMP
7383 +#define NF_NEED_STRTOU16
7384 +#include <linux/netfilter_helpers.h>
7385 +#define NF_NEED_MIME_NEXTLINE
7386 +#include <linux/netfilter_mime.h>
7387 +
7388 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7389 +#ifdef IP_NF_RTSP_DEBUG
7390 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7391 +#else
7392 +#define DEBUGP(fmt, args...)
7393 +#endif
7394 +
7395 +#define MAX_PORTS       8
7396 +#define DSTACT_AUTO     0
7397 +#define DSTACT_STRIP    1
7398 +#define DSTACT_NONE     2
7399 +
7400 +static int      ports[MAX_PORTS];
7401 +static char*    stunaddr = NULL;
7402 +static char*    destaction = NULL;
7403 +
7404 +static int       num_ports = 0;
7405 +static u_int32_t extip = 0;
7406 +static int       dstact = 0;
7407 +
7408 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7409 +MODULE_DESCRIPTION("RTSP network address translation module");
7410 +MODULE_LICENSE("GPL");
7411 +#ifdef MODULE_PARM
7412 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7413 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7414 +MODULE_PARM(stunaddr, "s");
7415 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7416 +MODULE_PARM(destaction, "s");
7417 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7418 +#endif
7419 +
7420 +/* protects rtsp part of conntracks */
7421 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7422 +
7423 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7424 +
7425 +/*** helper functions ***/
7426 +
7427 +static void
7428 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7429 +{
7430 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
7431 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7432 +
7433 +    *pptcpdata = (char*)tcph + tcph->doff*4;
7434 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7435 +}
7436 +
7437 +/*** nat functions ***/
7438 +
7439 +/*
7440 + * Mangle the "Transport:" header:
7441 + *   - Replace all occurences of "client_port=<spec>"
7442 + *   - Handle destination parameter
7443 + *
7444 + * In:
7445 + *   ct, ctinfo = conntrack context
7446 + *   pskb       = packet
7447 + *   tranoff    = Transport header offset from TCP data
7448 + *   tranlen    = Transport header length (incl. CRLF)
7449 + *   rport_lo   = replacement low  port (host endian)
7450 + *   rport_hi   = replacement high port (host endian)
7451 + *
7452 + * Returns packet size difference.
7453 + *
7454 + * Assumes that a complete transport header is present, ending with CR or LF
7455 + */
7456 +static int
7457 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7458 +                 struct ip_conntrack_expect* exp,
7459 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
7460 +{
7461 +    char*       ptcp;
7462 +    uint        tcplen;
7463 +    char*       ptran;
7464 +    char        rbuf1[16];      /* Replacement buffer (one port) */
7465 +    uint        rbuf1len;       /* Replacement len (one port) */
7466 +    char        rbufa[16];      /* Replacement buffer (all ports) */
7467 +    uint        rbufalen;       /* Replacement len (all ports) */
7468 +    u_int32_t   newip;
7469 +    u_int16_t   loport, hiport;
7470 +    uint        off = 0;
7471 +    uint        diff;           /* Number of bytes we removed */
7472 +
7473 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7474 +    struct ip_conntrack_tuple t;
7475 +
7476 +    char    szextaddr[15+1];
7477 +    uint    extaddrlen;
7478 +    int     is_stun;
7479 +
7480 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7481 +    ptran = ptcp+tranoff;
7482 +
7483 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7484 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7485 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
7486 +    {
7487 +        INFOP("sanity check failed\n");
7488 +        return 0;
7489 +    }
7490 +    off += 10;
7491 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7492 +
7493 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7494 +    t = exp->tuple;
7495 +    t.dst.ip = newip;
7496 +
7497 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7498 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7499 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7500 +
7501 +    rbuf1len = rbufalen = 0;
7502 +    switch (prtspexp->pbtype)
7503 +    {
7504 +    case pb_single:
7505 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7506 +        {
7507 +            t.dst.u.udp.port = htons(loport);
7508 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7509 +            {
7510 +                DEBUGP("using port %hu\n", loport);
7511 +                break;
7512 +            }
7513 +        }
7514 +        if (loport != 0)
7515 +        {
7516 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7517 +            rbufalen = sprintf(rbufa, "%hu", loport);
7518 +        }
7519 +        break;
7520 +    case pb_range:
7521 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7522 +        {
7523 +            t.dst.u.udp.port = htons(loport);
7524 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7525 +            {
7526 +                hiport = loport + ~exp->mask.dst.u.udp.port;
7527 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
7528 +                break;
7529 +            }
7530 +        }
7531 +        if (loport != 0)
7532 +        {
7533 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7534 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7535 +        }
7536 +        break;
7537 +    case pb_discon:
7538 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7539 +        {
7540 +            t.dst.u.udp.port = htons(loport);
7541 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7542 +            {
7543 +                DEBUGP("using port %hu (1 of 2)\n", loport);
7544 +                break;
7545 +            }
7546 +        }
7547 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7548 +        {
7549 +            t.dst.u.udp.port = htons(hiport);
7550 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7551 +            {
7552 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
7553 +                break;
7554 +            }
7555 +        }
7556 +        if (loport != 0 && hiport != 0)
7557 +        {
7558 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7559 +            if (hiport == loport+1)
7560 +            {
7561 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7562 +            }
7563 +            else
7564 +            {
7565 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7566 +            }
7567 +        }
7568 +        break;
7569 +    }
7570 +
7571 +    if (rbuf1len == 0)
7572 +    {
7573 +        return 0;   /* cannot get replacement port(s) */
7574 +    }
7575 +
7576 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
7577 +    while (off < tranlen)
7578 +    {
7579 +        uint        saveoff;
7580 +        const char* pparamend;
7581 +        uint        nextparamoff;
7582 +
7583 +        pparamend = memchr(ptran+off, ',', tranlen-off);
7584 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7585 +        nextparamoff = pparamend-ptcp;
7586 +
7587 +        /*
7588 +         * We pass over each param twice.  On the first pass, we look for a
7589 +         * destination= field.  It is handled by the security policy.  If it
7590 +         * is present, allowed, and equal to our external address, we assume
7591 +         * that STUN is being used and we leave the client_port= field alone.
7592 +         */
7593 +        is_stun = 0;
7594 +        saveoff = off;
7595 +        while (off < nextparamoff)
7596 +        {
7597 +            const char* pfieldend;
7598 +            uint        nextfieldoff;
7599 +
7600 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7601 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7602 +
7603 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7604 +            {
7605 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7606 +                {
7607 +                    is_stun = 1;
7608 +                }
7609 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7610 +                {
7611 +                    diff = nextfieldoff-off;
7612 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7613 +                                                         off, diff, NULL, 0))
7614 +                    {
7615 +                        /* mangle failed, all we can do is bail */
7616 +                        return 0;
7617 +                    }
7618 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7619 +                    ptran = ptcp+tranoff;
7620 +                    tranlen -= diff;
7621 +                    nextparamoff -= diff;
7622 +                    nextfieldoff -= diff;
7623 +                }
7624 +            }
7625 +
7626 +            off = nextfieldoff;
7627 +        }
7628 +        if (is_stun)
7629 +        {
7630 +            continue;
7631 +        }
7632 +        off = saveoff;
7633 +        while (off < nextparamoff)
7634 +        {
7635 +            const char* pfieldend;
7636 +            uint        nextfieldoff;
7637 +
7638 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7639 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7640 +
7641 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
7642 +            {
7643 +                u_int16_t   port;
7644 +                uint        numlen;
7645 +                uint        origoff;
7646 +                uint        origlen;
7647 +                char*       rbuf    = rbuf1;
7648 +                uint        rbuflen = rbuf1len;
7649 +
7650 +                off += 12;
7651 +                origoff = (ptran-ptcp)+off;
7652 +                origlen = 0;
7653 +                numlen = nf_strtou16(ptran+off, &port);
7654 +                off += numlen;
7655 +                origlen += numlen;
7656 +                if (port != prtspexp->loport)
7657 +                {
7658 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
7659 +                }
7660 +                else
7661 +                {
7662 +                    if (ptran[off] == '-' || ptran[off] == '/')
7663 +                    {
7664 +                        off++;
7665 +                        origlen++;
7666 +                        numlen = nf_strtou16(ptran+off, &port);
7667 +                        off += numlen;
7668 +                        origlen += numlen;
7669 +                        rbuf = rbufa;
7670 +                        rbuflen = rbufalen;
7671 +                    }
7672 +
7673 +                    /*
7674 +                     * note we cannot just memcpy() if the sizes are the same.
7675 +                     * the mangle function does skb resizing, checks for a
7676 +                     * cloned skb, and updates the checksums.
7677 +                     *
7678 +                     * parameter 4 below is offset from start of tcp data.
7679 +                     */
7680 +                    diff = origlen-rbuflen;
7681 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7682 +                                              origoff, origlen, rbuf, rbuflen))
7683 +                    {
7684 +                        /* mangle failed, all we can do is bail */
7685 +                        return 0;
7686 +                    }
7687 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7688 +                    ptran = ptcp+tranoff;
7689 +                    tranlen -= diff;
7690 +                    nextparamoff -= diff;
7691 +                    nextfieldoff -= diff;
7692 +                }
7693 +            }
7694 +
7695 +            off = nextfieldoff;
7696 +        }
7697 +
7698 +        off = nextparamoff;
7699 +    }
7700 +
7701 +    return 1;
7702 +}
7703 +
7704 +static unsigned int
7705 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7706 +{
7707 +    struct ip_nat_multi_range mr;
7708 +    u_int32_t newdstip, newsrcip, newip;
7709 +
7710 +    struct ip_conntrack *master = master_ct(ct);
7711 +
7712 +    IP_NF_ASSERT(info);
7713 +    IP_NF_ASSERT(master);
7714 +
7715 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7716 +
7717 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7718 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7719 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7720 +
7721 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7722 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7723 +
7724 +    mr.rangesize = 1;
7725 +    /* We don't want to manip the per-protocol, just the IPs. */
7726 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7727 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
7728 +
7729 +    return ip_nat_setup_info(ct, &mr, hooknum);
7730 +}
7731 +
7732 +static uint
7733 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7734 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7735 +{
7736 +    char*   ptcp;
7737 +    uint    tcplen;
7738 +    uint    hdrsoff;
7739 +    uint    hdrslen;
7740 +    uint    lineoff;
7741 +    uint    linelen;
7742 +    uint    off;
7743 +
7744 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7745 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7746 +
7747 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7748 +
7749 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7750 +
7751 +    hdrsoff = exp->seq - ntohl(tcph->seq);
7752 +    hdrslen = prtspexp->len;
7753 +    off = hdrsoff;
7754 +
7755 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7756 +    {
7757 +        if (linelen == 0)
7758 +        {
7759 +            break;
7760 +        }
7761 +        if (off > hdrsoff+hdrslen)
7762 +        {
7763 +            INFOP("!! overrun !!");
7764 +            break;
7765 +        }
7766 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7767 +
7768 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7769 +        {
7770 +            uint oldtcplen = tcplen;
7771 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7772 +            {
7773 +                break;
7774 +            }
7775 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7776 +            hdrslen -= (oldtcplen-tcplen);
7777 +            off -= (oldtcplen-tcplen);
7778 +            lineoff -= (oldtcplen-tcplen);
7779 +            linelen -= (oldtcplen-tcplen);
7780 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7781 +        }
7782 +    }
7783 +
7784 +    return NF_ACCEPT;
7785 +}
7786 +
7787 +static uint
7788 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7789 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7790 +{
7791 +    /* XXX: unmangle */
7792 +    return NF_ACCEPT;
7793 +}
7794 +
7795 +static uint
7796 +help(struct ip_conntrack* ct,
7797 +     struct ip_conntrack_expect* exp,
7798 +     struct ip_nat_info* info,
7799 +     enum ip_conntrack_info ctinfo,
7800 +     unsigned int hooknum,
7801 +     struct sk_buff** pskb)
7802 +{
7803 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
7804 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7805 +    uint datalen;
7806 +    int dir;
7807 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
7808 +    int rc = NF_ACCEPT;
7809 +
7810 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7811 +    {
7812 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7813 +        return NF_ACCEPT;
7814 +    }
7815 +
7816 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
7817 +
7818 +    /*
7819 +     * Only mangle things once: original direction in POST_ROUTING
7820 +     * and reply direction on PRE_ROUTING.
7821 +     */
7822 +    dir = CTINFO2DIR(ctinfo);
7823 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7824 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7825 +    {
7826 +        DEBUGP("Not touching dir %s at hook %s\n",
7827 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7828 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7829 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7830 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7831 +        return NF_ACCEPT;
7832 +    }
7833 +    DEBUGP("got beyond not touching\n");
7834 +
7835 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7836 +
7837 +    LOCK_BH(&ip_rtsp_lock);
7838 +    /* Ensure the packet contains all of the marked data */
7839 +    if (!between(exp->seq + ct_rtsp_info->len,
7840 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7841 +    {
7842 +        /* Partial retransmission?  Probably a hacker. */
7843 +        if (net_ratelimit())
7844 +        {
7845 +            INFOP("partial packet %u/%u in %u/%u\n",
7846 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7847 +        }
7848 +        UNLOCK_BH(&ip_rtsp_lock);
7849 +        return NF_DROP;
7850 +    }
7851 +
7852 +    switch (dir)
7853 +    {
7854 +    case IP_CT_DIR_ORIGINAL:
7855 +        rc = help_out(ct, ctinfo, exp, pskb);
7856 +        break;
7857 +    case IP_CT_DIR_REPLY:
7858 +        rc = help_in(ct, ctinfo, exp, pskb);
7859 +        break;
7860 +    }
7861 +    UNLOCK_BH(&ip_rtsp_lock);
7862 +
7863 +    return rc;
7864 +}
7865 +
7866 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7867 +static char rtsp_names[MAX_PORTS][10];
7868 +
7869 +/* This function is intentionally _NOT_ defined as  __exit */
7870 +static void
7871 +fini(void)
7872 +{
7873 +    int i;
7874 +
7875 +    for (i = 0; i < num_ports; i++)
7876 +    {
7877 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
7878 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7879 +    }
7880 +}
7881 +
7882 +static int __init
7883 +init(void)
7884 +{
7885 +    int ret = 0;
7886 +    int i;
7887 +    struct ip_nat_helper* hlpr;
7888 +    char* tmpname;
7889 +
7890 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7891 +
7892 +    if (ports[0] == 0)
7893 +    {
7894 +        ports[0] = RTSP_PORT;
7895 +    }
7896 +
7897 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7898 +    {
7899 +        hlpr = &ip_nat_rtsp_helpers[i];
7900 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
7901 +
7902 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
7903 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7904 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
7905 +        hlpr->mask.dst.protonum = 0xFFFF;
7906 +        hlpr->help = help;
7907 +        hlpr->flags = 0;
7908 +        hlpr->me = THIS_MODULE;
7909 +        hlpr->expect = expected;
7910 +
7911 +        tmpname = &rtsp_names[i][0];
7912 +        if (ports[i] == RTSP_PORT)
7913 +        {
7914 +                sprintf(tmpname, "rtsp");
7915 +        }
7916 +        else
7917 +        {
7918 +                sprintf(tmpname, "rtsp-%d", i);
7919 +        }
7920 +        hlpr->name = tmpname;
7921 +
7922 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7923 +        ret = ip_nat_helper_register(hlpr);
7924 +
7925 +        if (ret)
7926 +        {
7927 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7928 +            fini();
7929 +            return 1;
7930 +        }
7931 +        num_ports++;
7932 +    }
7933 +    if (stunaddr != NULL)
7934 +    {
7935 +        extip = in_aton(stunaddr);
7936 +    }
7937 +    if (destaction != NULL)
7938 +    {
7939 +        if (strcmp(destaction, "auto") == 0)
7940 +        {
7941 +            dstact = DSTACT_AUTO;
7942 +        }
7943 +        if (strcmp(destaction, "strip") == 0)
7944 +        {
7945 +            dstact = DSTACT_STRIP;
7946 +        }
7947 +        if (strcmp(destaction, "none") == 0)
7948 +        {
7949 +            dstact = DSTACT_NONE;
7950 +        }
7951 +    }
7952 +    return ret;
7953 +}
7954 +
7955 +module_init(init);
7956 +module_exit(fini);
7957 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.6/net/ipv4/netfilter/ip_nat_rule.c
7958 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_rule.c    2004-05-10 04:32:28.000000000 +0200
7959 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_rule.c        2004-05-18 12:38:32.000000000 +0200
7960 @@ -75,7 +75,7 @@
7961                 0,
7962                 sizeof(struct ipt_entry),
7963                 sizeof(struct ipt_standard),
7964 -               0, { 0, 0 }, { } },
7965 +               0, NULL, 0, { 0, 0 }, { } },
7966               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7967                 -NF_ACCEPT - 1 } },
7968             /* POST_ROUTING */
7969 @@ -83,7 +83,7 @@
7970                 0,
7971                 sizeof(struct ipt_entry),
7972                 sizeof(struct ipt_standard),
7973 -               0, { 0, 0 }, { } },
7974 +               0, NULL, 0, { 0, 0 }, { } },
7975               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7976                 -NF_ACCEPT - 1 } },
7977             /* LOCAL_OUT */
7978 @@ -91,7 +91,7 @@
7979                 0,
7980                 sizeof(struct ipt_entry),
7981                 sizeof(struct ipt_standard),
7982 -               0, { 0, 0 }, { } },
7983 +               0, NULL, 0, { 0, 0 }, { } },
7984               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7985                 -NF_ACCEPT - 1 } }
7986      },
7987 @@ -100,7 +100,7 @@
7988         0,
7989         sizeof(struct ipt_entry),
7990         sizeof(struct ipt_error),
7991 -       0, { 0, 0 }, { } },
7992 +       0, NULL, 0, { 0, 0 }, { } },
7993        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7994           { } },
7995         "ERROR"
7996 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6/net/ipv4/netfilter/ip_nat_standalone.c
7997 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_standalone.c      2004-05-10 04:33:12.000000000 +0200
7998 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_standalone.c  2004-05-18 12:39:22.000000000 +0200
7999 @@ -175,6 +175,45 @@
8000         return do_bindings(ct, ctinfo, info, hooknum, pskb);
8001  }
8002  
8003 +struct nat_route_key
8004 +{
8005 +       u_int32_t addr;
8006 +#ifdef CONFIG_XFRM
8007 +       u_int16_t port;
8008 +#endif
8009 +};
8010 +
8011 +static inline void
8012 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
8013 +{
8014 +       struct iphdr *iph = skb->nh.iph;
8015 +
8016 +       key->addr = which ? iph->daddr : iph->saddr;
8017 +#ifdef CONFIG_XFRM
8018 +       key->port = 0;
8019 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8020 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8021 +               key->port = ports[which];
8022 +       }
8023 +#endif
8024 +}
8025 +
8026 +static inline int
8027 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
8028 +{
8029 +       struct iphdr *iph = skb->nh.iph;
8030 +
8031 +       if (key->addr != (which ? iph->daddr : iph->saddr))
8032 +               return 1;
8033 +#ifdef CONFIG_XFRM
8034 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8035 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8036 +               if (key->port != ports[which])
8037 +                       return 1;
8038 +       }
8039 +#endif
8040 +}
8041 +
8042  static unsigned int
8043  ip_nat_out(unsigned int hooknum,
8044            struct sk_buff **pskb,
8045 @@ -182,6 +221,9 @@
8046            const struct net_device *out,
8047            int (*okfn)(struct sk_buff *))
8048  {
8049 +       struct nat_route_key key;
8050 +       unsigned int ret;
8051 +
8052         /* root is playing with raw sockets. */
8053         if ((*pskb)->len < sizeof(struct iphdr)
8054             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8055 @@ -204,7 +246,29 @@
8056                         return NF_STOLEN;
8057         }
8058  
8059 -       return ip_nat_fn(hooknum, pskb, in, out, okfn);
8060 +       nat_route_key_get(*pskb, &key, 0);
8061 +       ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8062 +
8063 +       if (ret != NF_DROP && ret != NF_STOLEN
8064 +           && nat_route_key_compare(*pskb, &key, 0)) {
8065 +               if (ip_route_me_harder(pskb) != 0)
8066 +                       ret = NF_DROP;
8067 +#ifdef CONFIG_XFRM
8068 +               /*
8069 +                * POST_ROUTING hook is called with fixed outfn, we need
8070 +                * to manually confirm the packet and direct it to the
8071 +                * transformers if a policy matches.
8072 +                */
8073 +               else if ((*pskb)->dst->xfrm != NULL) {
8074 +                       ret = ip_conntrack_confirm(*pskb);
8075 +                       if (ret != NF_DROP) {
8076 +                               dst_output(*pskb);
8077 +                               ret = NF_STOLEN;
8078 +                       }
8079 +               }
8080 +#endif
8081 +       }
8082 +       return ret;
8083  }
8084  
8085  #ifdef CONFIG_IP_NF_NAT_LOCAL
8086 @@ -215,7 +279,7 @@
8087                 const struct net_device *out,
8088                 int (*okfn)(struct sk_buff *))
8089  {
8090 -       u_int32_t saddr, daddr;
8091 +       struct nat_route_key key;
8092         unsigned int ret;
8093  
8094         /* root is playing with raw sockets. */
8095 @@ -223,14 +287,14 @@
8096             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8097                 return NF_ACCEPT;
8098  
8099 -       saddr = (*pskb)->nh.iph->saddr;
8100 -       daddr = (*pskb)->nh.iph->daddr;
8101 -
8102 +       nat_route_key_get(*pskb, &key, 1);
8103         ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8104 +
8105         if (ret != NF_DROP && ret != NF_STOLEN
8106 -           && ((*pskb)->nh.iph->saddr != saddr
8107 -               || (*pskb)->nh.iph->daddr != daddr))
8108 -               return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
8109 +           && nat_route_key_compare(*pskb, &key, 1)) {
8110 +               if (ip_route_me_harder(pskb) != 0)
8111 +                       ret = NF_DROP;
8112 +       }
8113         return ret;
8114  }
8115  #endif
8116 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6/net/ipv4/netfilter/ip_nat_talk.c
8117 --- linux-2.6.6.org/net/ipv4/netfilter/ip_nat_talk.c    1970-01-01 01:00:00.000000000 +0100
8118 +++ linux-2.6.6/net/ipv4/netfilter/ip_nat_talk.c        2004-05-18 12:40:50.000000000 +0200
8119 @@ -0,0 +1,473 @@
8120 +/* 
8121 + * talk extension for UDP NAT alteration. 
8122 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8123 + *
8124 + *      This program is free software; you can redistribute it and/or
8125 + *      modify it under the terms of the GNU General Public License
8126 + *      as published by the Free Software Foundation; either version
8127 + *      2 of the License, or (at your option) any later version.
8128 + **
8129 + *     Module load syntax:
8130 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
8131 + *
8132 + *             talk=[0|1]      disable|enable old talk support
8133 + *            ntalk=[0|1]      disable|enable ntalk support
8134 + *           ntalk2=[0|1]      disable|enable ntalk2 support
8135 + *
8136 + *     The default is talk=1 ntalk=1 ntalk2=1
8137 + *
8138 + *  
8139 + */
8140 +#include <linux/module.h>
8141 +#include <linux/netfilter_ipv4.h>
8142 +#include <linux/ip.h>
8143 +#include <linux/udp.h>
8144 +#include <linux/kernel.h>
8145 +#include <net/tcp.h>
8146 +#include <net/udp.h>
8147 +
8148 +#include <linux/netfilter_ipv4/ip_nat.h>
8149 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8150 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8151 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8152 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8153 +
8154 +/* Default all talk protocols are supported */
8155 +static int talk   = 1;
8156 +static int ntalk  = 1;
8157 +static int ntalk2 = 1;
8158 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8159 +MODULE_DESCRIPTION("talk network address translation module");
8160 +#ifdef MODULE_PARM
8161 +MODULE_PARM(talk, "i");
8162 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8163 +MODULE_PARM(ntalk, "i");
8164 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8165 +MODULE_PARM(ntalk2, "i");
8166 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8167 +#endif
8168 +
8169 +#if 0
8170 +#define DEBUGP printk
8171 +#define IP_NAT_TALK_DEBUG
8172 +#else
8173 +#define DEBUGP(format, args...)
8174 +#endif
8175 +
8176 +/* FIXME: Time out? --RR */
8177 +
8178 +static int
8179 +mangle_packet(struct sk_buff **pskb,
8180 +             struct ip_conntrack *ct,
8181 +             u_int32_t newip,
8182 +             u_int16_t port,
8183 +             struct talk_addr *addr,
8184 +             struct talk_addr *ctl_addr)
8185 +{
8186 +       struct iphdr *iph = (*pskb)->nh.iph;
8187 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8188 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
8189 +
8190 +       /* Fortunately talk sends a structure with the address and
8191 +          port in it. The size of the packet won't change. */
8192 +
8193 +       if (ctl_addr == NULL) {
8194 +               /* response */
8195 +               if (addr->ta_addr == INADDR_ANY)
8196 +                       return 1;
8197 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8198 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8199 +                      NIPQUAD(newip), ntohs(port));
8200 +               addr->ta_addr = newip;
8201 +               addr->ta_port = port;
8202 +       } else {
8203 +               /* message */
8204 +               if (addr->ta_addr != INADDR_ANY) {
8205 +                       /* Change address inside packet to match way we're mapping
8206 +                          this connection. */
8207 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8208 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8209 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
8210 +                              ntohs(addr->ta_port));
8211 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8212 +               }
8213 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8214 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8215 +                      NIPQUAD(newip), ntohs(port));
8216 +               ctl_addr->ta_addr = newip;
8217 +               ctl_addr->ta_port = port;
8218 +       }
8219 +
8220 +       /* Fix checksums */
8221 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8222 +       udph->check = 0;
8223 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8224 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8225 +               
8226 +       ip_send_check(iph);
8227 +       return 1;
8228 +}
8229 +
8230 +static int talk_help_msg(struct ip_conntrack *ct,
8231 +                        struct sk_buff **pskb,
8232 +                        u_char type,
8233 +                        struct talk_addr *addr,
8234 +                        struct talk_addr *ctl_addr)
8235 +{
8236 +       u_int32_t newip;
8237 +       u_int16_t port;
8238 +       
8239 +       unsigned int verdict = NF_ACCEPT;
8240 +
8241 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8242 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8243 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8244 +               type);
8245 +
8246 +       /* Change address inside packet to match way we're mapping
8247 +          this connection. */
8248 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8249 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8250 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8251 +               NIPQUAD(newip), ntohs(port));
8252 +
8253 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8254 +               verdict = NF_DROP;
8255 +
8256 +       return verdict;
8257 +}
8258 +
8259 +static int talk_help_response(struct ip_conntrack *ct,
8260 +                             struct ip_conntrack_expect *exp,
8261 +                             struct sk_buff **pskb,
8262 +                             u_char type,
8263 +                             u_char answer,
8264 +                             struct talk_addr *addr)
8265 +{
8266 +       u_int32_t newip;
8267 +       u_int16_t port;
8268 +       struct ip_conntrack_tuple t;
8269 +       struct ip_ct_talk_expect *ct_talk_info;
8270 +
8271 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8272 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8273 +               type, answer);
8274 +       
8275 +       LOCK_BH(&ip_talk_lock);
8276 +       ct_talk_info = &exp->help.exp_talk_info;
8277 +
8278 +       if (!(answer == SUCCESS 
8279 +             && (type == LOOK_UP || type == ANNOUNCE)
8280 +             && exp != NULL)) {
8281 +               UNLOCK_BH(&ip_talk_lock);
8282 +               return NF_ACCEPT;
8283 +       }
8284 +               
8285 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
8286 +               ntohs(ct_talk_info->port), 
8287 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8288 +
8289 +       /* Change address inside packet to match way we're mapping
8290 +          this connection. */
8291 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
8292 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
8293 +       /* We can read expect here without conntrack lock, since it's
8294 +          only set in ip_conntrack_talk , with ip_talk_lock held
8295 +          writable */ 
8296 +       t = exp->tuple;
8297 +       t.dst.ip = newip;
8298 +
8299 +       /* Try to get same port: if not, try to change it. */
8300 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8301 +               if (type == LOOK_UP)
8302 +                       t.dst.u.tcp.port = htons(port);
8303 +               else
8304 +                       t.dst.u.udp.port = htons(port);
8305 +
8306 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
8307 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8308 +                       break;
8309 +               }
8310 +       }
8311 +       UNLOCK_BH(&ip_talk_lock);
8312 +
8313 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8314 +               return NF_DROP;
8315 +       
8316 +       return NF_ACCEPT;
8317 +}
8318 +
8319 +static unsigned int talk_help(struct ip_conntrack *ct,
8320 +                             struct ip_conntrack_expect *exp,
8321 +                             struct ip_nat_info *info,
8322 +                             enum ip_conntrack_info ctinfo,
8323 +                             unsigned int hooknum,
8324 +                             struct sk_buff **pskb,
8325 +                             int talk_port)
8326 +{
8327 +       struct iphdr *iph = (*pskb)->nh.iph;
8328 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8329 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8330 +       char *data = (char *)udph + sizeof(struct udphdr);
8331 +       int dir;
8332 +
8333 +       /* Only mangle things once: original direction in POST_ROUTING
8334 +          and reply direction on PRE_ROUTING. */
8335 +       dir = CTINFO2DIR(ctinfo);
8336 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8337 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8338 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8339 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8340 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8341 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8342 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8343 +               return NF_ACCEPT;
8344 +       }
8345 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8346 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8347 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8348 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8349 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8350 +              NIPQUAD(iph->saddr), ntohs(udph->source),
8351 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
8352 +              talk_port);
8353 +
8354 +       /* Because conntrack does not drop packets, checking must be repeated here... */
8355 +       if (talk_port == TALK_PORT) {
8356 +               if (dir == IP_CT_DIR_ORIGINAL
8357 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8358 +                       return talk_help_msg(ct, pskb,
8359 +                                            ((struct talk_msg *)data)->type, 
8360 +                                            &(((struct talk_msg *)data)->addr),
8361 +                                            &(((struct talk_msg *)data)->ctl_addr));
8362 +               else if (dir == IP_CT_DIR_REPLY
8363 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8364 +                       return talk_help_response(ct, exp, pskb,
8365 +                                                 ((struct talk_response *)data)->type, 
8366 +                                                 ((struct talk_response *)data)->answer,
8367 +                                                 &(((struct talk_response *)data)->addr));
8368 +               else {  
8369 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8370 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
8371 +                              (unsigned)udplen - sizeof(struct udphdr), 
8372 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8373 +                       return NF_DROP;
8374 +               }
8375 +       } else {
8376 +               if (dir == IP_CT_DIR_ORIGINAL) {
8377 +                       if (ntalk
8378 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8379 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8380 +                               return talk_help_msg(ct, pskb,
8381 +                                                    ((struct ntalk_msg *)data)->type, 
8382 +                                                    &(((struct ntalk_msg *)data)->addr),
8383 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
8384 +                       else if (ntalk2
8385 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8386 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8387 +                                && udplen == sizeof(struct udphdr) 
8388 +                                             + sizeof(struct ntalk2_msg) 
8389 +                                             + ((struct ntalk2_msg *)data)->extended)
8390 +                               return talk_help_msg(ct, pskb,
8391 +                                                    ((struct ntalk2_msg *)data)->type, 
8392 +                                                    &(((struct ntalk2_msg *)data)->addr),
8393 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
8394 +                       else {
8395 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
8396 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8397 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8398 +                               return NF_DROP;
8399 +                       }
8400 +               } else {
8401 +                       if (ntalk
8402 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8403 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8404 +                               return talk_help_response(ct, exp, pskb,
8405 +                                                         ((struct ntalk_response *)data)->type, 
8406 +                                                         ((struct ntalk_response *)data)->answer,
8407 +                                                         &(((struct ntalk_response *)data)->addr));
8408 +                       else if (ntalk2
8409 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8410 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8411 +                               return talk_help_response(ct, exp, pskb,
8412 +                                                         ((struct ntalk2_response *)data)->type, 
8413 +                                                         ((struct ntalk2_response *)data)->answer,
8414 +                                                         &(((struct ntalk2_response *)data)->addr));
8415 +                       else {
8416 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
8417 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8418 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8419 +                               return NF_DROP;
8420 +                       }
8421 +               }
8422 +       }
8423 +}
8424 +
8425 +static unsigned int help(struct ip_conntrack *ct,
8426 +                        struct ip_conntrack_expect *exp,
8427 +                        struct ip_nat_info *info,
8428 +                        enum ip_conntrack_info ctinfo,
8429 +                        unsigned int hooknum,
8430 +                        struct sk_buff **pskb)
8431 +{
8432 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8433 +}
8434 +
8435 +static unsigned int nhelp(struct ip_conntrack *ct,
8436 +                         struct ip_conntrack_expect *exp,
8437 +                         struct ip_nat_info *info,
8438 +                         enum ip_conntrack_info ctinfo,
8439 +                         unsigned int hooknum,
8440 +                         struct sk_buff **pskb)
8441 +{
8442 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8443 +}
8444 +
8445 +static unsigned int
8446 +talk_nat_expected(struct sk_buff **pskb,
8447 +                 unsigned int hooknum,
8448 +                 struct ip_conntrack *ct,
8449 +                 struct ip_nat_info *info);
8450 +
8451 +static struct ip_nat_helper talk_helpers[2] = 
8452 +       { { { NULL, NULL },
8453 +            "talk",                                    /* name */
8454 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8455 +            THIS_MODULE,                               /* module */
8456 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8457 +              { 0, { 0 }, IPPROTO_UDP } },
8458 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8459 +              { 0, { 0 }, 0xFFFF } },
8460 +            help,                                      /* helper */
8461 +            talk_nat_expected },                       /* expectfn */
8462 +         { { NULL, NULL },
8463 +            "ntalk",                                   /* name */
8464 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8465 +            THIS_MODULE,                                       /* module */
8466 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8467 +              { 0, { 0 }, IPPROTO_UDP } },
8468 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8469 +              { 0, { 0 }, 0xFFFF } },
8470 +            nhelp,                                     /* helper */
8471 +            talk_nat_expected }                                /* expectfn */
8472 +       };
8473 +          
8474 +static unsigned int
8475 +talk_nat_expected(struct sk_buff **pskb,
8476 +                 unsigned int hooknum,
8477 +                 struct ip_conntrack *ct,
8478 +                 struct ip_nat_info *info)
8479 +{
8480 +       struct ip_nat_multi_range mr;
8481 +       u_int32_t newdstip, newsrcip, newip;
8482 +       u_int16_t port;
8483 +       unsigned int ret;
8484 +       
8485 +       struct ip_conntrack *master = master_ct(ct);
8486 +
8487 +       IP_NF_ASSERT(info);
8488 +       IP_NF_ASSERT(master);
8489 +
8490 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8491 +
8492 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8493 +
8494 +       LOCK_BH(&ip_talk_lock);
8495 +       port = ct->master->help.exp_talk_info.port;
8496 +       UNLOCK_BH(&ip_talk_lock);
8497 +
8498 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8499 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8500 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8501 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8502 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8503 +              ct, master);
8504 +
8505 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8506 +               /* Callee client -> caller server */
8507 +#ifdef IP_NAT_TALK_DEBUG
8508 +               struct iphdr *iph = (*pskb)->nh.iph;
8509 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
8510 +
8511 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8512 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
8513 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
8514 +#endif
8515 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8516 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8517 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8518 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8519 +       } else {
8520 +               /* Callee client -> caller client */
8521 +#ifdef IP_NAT_TALK_DEBUG
8522 +               struct iphdr *iph = (*pskb)->nh.iph;
8523 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8524 +
8525 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8526 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
8527 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
8528 +#endif
8529 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8530 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8531 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8532 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8533 +       }
8534 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8535 +               newip = newsrcip;
8536 +       else
8537 +               newip = newdstip;
8538 +
8539 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8540 +
8541 +       mr.rangesize = 1;
8542 +       /* We don't want to manip the per-protocol, just the IPs... */
8543 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8544 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8545 +       
8546 +       /* ... unless we're doing a MANIP_DST, in which case, make
8547 +          sure we map to the correct port */
8548 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8549 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8550 +               mr.range[0].min = mr.range[0].max
8551 +                       = ((union ip_conntrack_manip_proto)
8552 +                               { .udp = { port } });
8553 +       }
8554 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
8555 +
8556 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8557 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8558 +               /* NAT expectfn called with ip_nat_lock write-locked */
8559 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
8560 +       }
8561 +       return ret;
8562 +}
8563 +
8564 +static int __init init(void)
8565 +{
8566 +       int ret = 0;
8567 +
8568 +       if (talk > 0) {
8569 +               ret = ip_nat_helper_register(&talk_helpers[0]);
8570 +
8571 +               if (ret != 0)
8572 +                       return ret;
8573 +       }
8574 +       if (ntalk > 0 || ntalk2 > 0) {
8575 +               ret = ip_nat_helper_register(&talk_helpers[1]);
8576 +
8577 +               if (ret != 0 && talk > 0)
8578 +                       ip_nat_helper_unregister(&talk_helpers[0]);
8579 +       }
8580 +       return ret;
8581 +}
8582 +
8583 +static void __exit fini(void)
8584 +{
8585 +       if (talk > 0)
8586 +               ip_nat_helper_unregister(&talk_helpers[0]);
8587 +       if (ntalk > 0 || ntalk2 > 0)
8588 +               ip_nat_helper_unregister(&talk_helpers[1]);
8589 +}
8590 +
8591 +module_init(init);
8592 +module_exit(fini);
8593 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_pool.c linux-2.6.6/net/ipv4/netfilter/ip_pool.c
8594 --- linux-2.6.6.org/net/ipv4/netfilter/ip_pool.c        1970-01-01 01:00:00.000000000 +0100
8595 +++ linux-2.6.6/net/ipv4/netfilter/ip_pool.c    2004-05-18 12:36:48.000000000 +0200
8596 @@ -0,0 +1,334 @@
8597 +/* Kernel module for IP pool management */
8598 +
8599 +#include <linux/module.h>
8600 +#include <linux/ip.h>
8601 +#include <linux/skbuff.h>
8602 +#include <linux/netfilter_ipv4/ip_tables.h>
8603 +#include <linux/netfilter_ipv4/ip_pool.h>
8604 +#include <linux/errno.h>
8605 +#include <asm/uaccess.h>
8606 +#include <asm/bitops.h>
8607 +#include <linux/interrupt.h>
8608 +#include <linux/spinlock.h>
8609 +
8610 +#if 0
8611 +#define DP printk
8612 +#else
8613 +#define DP(format, args...)
8614 +#endif
8615 +
8616 +MODULE_LICENSE("GPL");
8617 +
8618 +#define NR_POOL 16
8619 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8620 +
8621 +struct ip_pool {
8622 +       u_int32_t first_ip;     /* host byte order, included in range */
8623 +       u_int32_t last_ip;      /* host byte order, included in range */
8624 +       void *members;          /* the bitmap proper */
8625 +       int nr_use;             /* total nr. of tests through this */
8626 +       int nr_match;           /* total nr. of matches through this */
8627 +       rwlock_t lock;
8628 +};
8629 +
8630 +static struct ip_pool *POOL;
8631 +
8632 +static inline struct ip_pool *lookup(ip_pool_t index)
8633 +{
8634 +       if (index < 0 || index >= nr_pool) {
8635 +               DP("ip_pool:lookup: bad index %d\n", index);
8636 +               return 0;
8637 +       }
8638 +       return POOL+index;
8639 +}
8640 +
8641 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8642 +{
8643 +        struct ip_pool *pool = lookup(index);
8644 +       int res = 0;
8645 +
8646 +       if (!pool || !pool->members)
8647 +               return 0;
8648 +       read_lock_bh(&pool->lock);
8649 +       if (pool->members) {
8650 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
8651 +                       addr -= pool->first_ip;
8652 +                       if (test_bit(addr, pool->members)) {
8653 +                               res = 1;
8654 +#ifdef CONFIG_IP_POOL_STATISTICS
8655 +                               pool->nr_match++;
8656 +#endif
8657 +                       }
8658 +               }
8659 +#ifdef CONFIG_IP_POOL_STATISTICS
8660 +               pool->nr_use++;
8661 +#endif
8662 +       }
8663 +       read_unlock_bh(&pool->lock);
8664 +       return res;
8665 +}
8666 +EXPORT_SYMBOL(ip_pool_match);
8667 +
8668 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8669 +{
8670 +       struct ip_pool *pool;
8671 +       int res = -1;
8672 +
8673 +       pool = lookup(index);
8674 +       if (    !pool || !pool->members
8675 +            || addr < pool->first_ip || addr > pool->last_ip)
8676 +               return -1;
8677 +       read_lock_bh(&pool->lock);
8678 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8679 +               addr -= pool->first_ip;
8680 +               res = isdel
8681 +                       ? (0 != test_and_clear_bit(addr, pool->members))
8682 +                       : (0 != test_and_set_bit(addr, pool->members));
8683 +       }
8684 +       read_unlock_bh(&pool->lock);
8685 +       return res;
8686 +}
8687 +
8688 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8689 +{
8690 +       int res = pool_change(index,addr,isdel);
8691 +
8692 +       if (!isdel) res = !res;
8693 +       return res;
8694 +}
8695 +EXPORT_SYMBOL(ip_pool_mod);
8696 +
8697 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8698 +{
8699 +       return 4*((((b-a+8)/8)+3)/4);
8700 +}
8701 +
8702 +static inline int poolbytes(ip_pool_t index)
8703 +{
8704 +       struct ip_pool *pool = lookup(index);
8705 +
8706 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8707 +}
8708 +
8709 +static int setpool(
8710 +       struct sock *sk,
8711 +       int optval,
8712 +       void *user,
8713 +       unsigned int len
8714 +) {
8715 +       struct ip_pool_request req;
8716 +
8717 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8718 +       if (!capable(CAP_NET_ADMIN))
8719 +               return -EPERM;
8720 +       if (optval != SO_IP_POOL)
8721 +               return -EBADF;
8722 +       if (len != sizeof(req))
8723 +               return -EINVAL;
8724 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
8725 +               return -EFAULT;
8726 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
8727 +       return -EINVAL;
8728 +}
8729 +
8730 +static int getpool(
8731 +       struct sock *sk,
8732 +       int optval,
8733 +       void *user,
8734 +       int *len
8735 +) {
8736 +       struct ip_pool_request req;
8737 +       struct ip_pool *pool;
8738 +       ip_pool_t i;
8739 +       int newbytes;
8740 +       void *newmembers;
8741 +       int res;
8742 +
8743 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
8744 +       if (!capable(CAP_NET_ADMIN))
8745 +               return -EINVAL;
8746 +       if (optval != SO_IP_POOL)
8747 +               return -EINVAL;
8748 +       if (*len != sizeof(req)) {
8749 +               return -EFAULT;
8750 +       }
8751 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
8752 +               return -EFAULT;
8753 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
8754 +       if (req.op < IP_POOL_BAD001) {
8755 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
8756 +               return -EFAULT;
8757 +       }
8758 +       switch(req.op) {
8759 +       case IP_POOL_HIGH_NR:
8760 +               DP("ip_pool HIGH_NR\n");
8761 +               req.index = IP_POOL_NONE;
8762 +               for (i=0; i<nr_pool; i++)
8763 +                       if (POOL[i].members)
8764 +                               req.index = i;
8765 +               return copy_to_user(user, &req, sizeof(req));
8766 +       case IP_POOL_LOOKUP:
8767 +               DP("ip_pool LOOKUP\n");
8768 +               pool = lookup(req.index);
8769 +               if (!pool)
8770 +                       return -EINVAL;
8771 +               if (!pool->members)
8772 +                       return -EBADF;
8773 +               req.addr = htonl(pool->first_ip);
8774 +               req.addr2 = htonl(pool->last_ip);
8775 +               return copy_to_user(user, &req, sizeof(req));
8776 +       case IP_POOL_USAGE:
8777 +               DP("ip_pool USE\n");
8778 +               pool = lookup(req.index);
8779 +               if (!pool)
8780 +                       return -EINVAL;
8781 +               if (!pool->members)
8782 +                       return -EBADF;
8783 +               req.addr = pool->nr_use;
8784 +               req.addr2 = pool->nr_match;
8785 +               return copy_to_user(user, &req, sizeof(req));
8786 +       case IP_POOL_TEST_ADDR:
8787 +               DP("ip_pool TEST 0x%08x\n", req.addr);
8788 +               pool = lookup(req.index);
8789 +               if (!pool)
8790 +                       return -EINVAL;
8791 +               res = 0;
8792 +               read_lock_bh(&pool->lock);
8793 +               if (!pool->members) {
8794 +                       DP("ip_pool TEST_ADDR no members in pool\n");
8795 +                       res = -EBADF;
8796 +                       goto unlock_and_return_res;
8797 +               }
8798 +               req.addr = ntohl(req.addr);
8799 +               if (req.addr < pool->first_ip) {
8800 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
8801 +                       res = -ERANGE;
8802 +                       goto unlock_and_return_res;
8803 +               }
8804 +               if (req.addr > pool->last_ip) {
8805 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
8806 +                       res = -ERANGE;
8807 +                       goto unlock_and_return_res;
8808 +               }
8809 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
8810 +                                       pool->members));
8811 +               read_unlock_bh(&pool->lock);
8812 +               return copy_to_user(user, &req, sizeof(req));
8813 +       case IP_POOL_FLUSH:
8814 +               DP("ip_pool FLUSH not yet implemented.\n");
8815 +               return -EBUSY;
8816 +       case IP_POOL_DESTROY:
8817 +               DP("ip_pool DESTROY not yet implemented.\n");
8818 +               return -EBUSY;
8819 +       case IP_POOL_INIT:
8820 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
8821 +               pool = lookup(req.index);
8822 +               if (!pool)
8823 +                       return -EINVAL;
8824 +               req.addr = ntohl(req.addr);
8825 +               req.addr2 = ntohl(req.addr2);
8826 +               if (req.addr > req.addr2) {
8827 +                       DP("ip_pool INIT bad ip range\n");
8828 +                       return -EINVAL;
8829 +               }
8830 +               newbytes = bitmap_bytes(req.addr, req.addr2);
8831 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
8832 +               if (!newmembers) {
8833 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
8834 +                       return -ENOMEM;
8835 +               }
8836 +               memset(newmembers, 0, newbytes);
8837 +               write_lock_bh(&pool->lock);
8838 +               if (pool->members) {
8839 +                       DP("ip_pool INIT pool %d exists\n", req.index);
8840 +                       kfree(newmembers);
8841 +                       res = -EBUSY;
8842 +                       goto unlock_and_return_res;
8843 +               }
8844 +               pool->first_ip = req.addr;
8845 +               pool->last_ip = req.addr2;
8846 +               pool->nr_use = 0;
8847 +               pool->nr_match = 0;
8848 +               pool->members = newmembers;
8849 +               write_unlock_bh(&pool->lock);
8850 +               return 0;
8851 +       case IP_POOL_ADD_ADDR:
8852 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
8853 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
8854 +               return copy_to_user(user, &req, sizeof(req));
8855 +       case IP_POOL_DEL_ADDR:
8856 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
8857 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
8858 +               return copy_to_user(user, &req, sizeof(req));
8859 +       default:
8860 +               DP("ip_pool:getpool bad op %d\n", req.op);
8861 +               return -EINVAL;
8862 +       }
8863 +       return -EINVAL;
8864 +
8865 +unlock_and_return_res:
8866 +       if (pool)
8867 +               read_unlock_bh(&pool->lock);
8868 +       return res;
8869 +}
8870 +
8871 +static struct nf_sockopt_ops so_pool
8872 += { { NULL, NULL }, PF_INET,
8873 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
8874 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
8875 +    0, NULL };
8876 +
8877 +MODULE_PARM(nr_pool, "i");
8878 +
8879 +static int __init init(void)
8880 +{
8881 +       ip_pool_t i;
8882 +       int res;
8883 +
8884 +       if (nr_pool < 1) {
8885 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
8886 +               return -EINVAL;
8887 +       }
8888 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
8889 +       if (!POOL) {
8890 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
8891 +                       nr_pool);
8892 +               return -ENOMEM;
8893 +       }
8894 +       for (i=0; i<nr_pool; i++) {
8895 +               POOL[i].first_ip = 0;
8896 +               POOL[i].last_ip = 0;
8897 +               POOL[i].members = 0;
8898 +               POOL[i].nr_use = 0;
8899 +               POOL[i].nr_match = 0;
8900 +               POOL[i].lock = RW_LOCK_UNLOCKED;
8901 +       }
8902 +       res = nf_register_sockopt(&so_pool);
8903 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
8904 +       if (res != 0) {
8905 +               kfree(POOL);
8906 +               POOL = 0;
8907 +       }
8908 +       return res;
8909 +}
8910 +
8911 +static void __exit fini(void)
8912 +{
8913 +       ip_pool_t i;
8914 +
8915 +       DP("ip_pool:fini BYEBYE\n");
8916 +       nf_unregister_sockopt(&so_pool);
8917 +       for (i=0; i<nr_pool; i++) {
8918 +               if (POOL[i].members) {
8919 +                       kfree(POOL[i].members);
8920 +                       POOL[i].members = 0;
8921 +               }
8922 +       }
8923 +       kfree(POOL);
8924 +       POOL = 0;
8925 +       DP("ip_pool:fini these are the famous last words\n");
8926 +       return;
8927 +}
8928 +
8929 +module_init(init);
8930 +module_exit(fini);
8931 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6/net/ipv4/netfilter/ip_tables.c
8932 --- linux-2.6.6.org/net/ipv4/netfilter/ip_tables.c      2004-05-10 04:32:26.000000000 +0200
8933 +++ linux-2.6.6/net/ipv4/netfilter/ip_tables.c  2004-05-18 12:39:16.000000000 +0200
8934 @@ -29,6 +29,14 @@
8935  
8936  #include <linux/netfilter_ipv4/ip_tables.h>
8937  
8938 +static const char *hooknames[] = { 
8939 +       [NF_IP_PRE_ROUTING] "PREROUTING",
8940 +       [NF_IP_LOCAL_IN] "INPUT",
8941 +       [NF_IP_FORWARD] "FORWARD",
8942 +       [NF_IP_LOCAL_OUT] "OUTPUT",
8943 +       [NF_IP_POST_ROUTING] "POSTROUTING",
8944 +};
8945 +
8946  MODULE_LICENSE("GPL");
8947  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8948  MODULE_DESCRIPTION("IPv4 packet filter");
8949 @@ -326,6 +334,12 @@
8950  
8951                         t = ipt_get_target(e);
8952                         IP_NF_ASSERT(t->u.kernel.target);
8953 +
8954 +                       /* The packet traced and the rule isn't an unconditional return/END. */
8955 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {       
8956 +                               nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8957 +                                             table->name, e->chainname, e->rulenum);
8958 +                       }
8959                         /* Standard target? */
8960                         if (!t->u.kernel.target->target) {
8961                                 int v;
8962 @@ -343,7 +357,7 @@
8963                                         continue;
8964                                 }
8965                                 if (table_base + v
8966 -                                   != (void *)e + e->next_offset) {
8967 +                                   != (void *)e + e->next_offset && !(e->ip.flags & IPT_F_GOTO)) {
8968                                         /* Save old back ptr in next entry */
8969                                         struct ipt_entry *next
8970                                                 = (void *)e + e->next_offset;
8971 @@ -352,7 +366,6 @@
8972                                         /* set back pointer to next entry */
8973                                         back = next;
8974                                 }
8975 -
8976                                 e = get_entry(table_base, v);
8977                         } else {
8978                                 /* Targets which reenter must return
8979 @@ -478,6 +491,29 @@
8980         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8981  }
8982  
8983 +static inline int
8984 +find_error_target(struct ipt_entry *s, 
8985 +                 struct ipt_entry *e,
8986 +                 char **chainname)
8987 +{
8988 +       struct ipt_entry_target *t;
8989 +       static struct ipt_entry *found = NULL;
8990 +
8991 +       if (s == e) {
8992 +               if (!found)
8993 +                       return 0;
8994 +               t = ipt_get_target(found);
8995 +               if (strcmp(t->u.user.name, 
8996 +                          IPT_ERROR_TARGET) == 0) {
8997 +                       *chainname = t->data;
8998 +                       return 1;
8999 +               }
9000 +       } else
9001 +               found = s;
9002 +       
9003 +       return 0;
9004 +}
9005 +
9006  /* All zeroes == unconditional rule. */
9007  static inline int
9008  unconditional(const struct ipt_ip *ip)
9009 @@ -497,6 +533,8 @@
9010  mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
9011  {
9012         unsigned int hook;
9013 +       char *chainname = NULL;
9014 +       u_int32_t rulenum;
9015  
9016         /* No recursion; use packet counter to save back ptrs (reset
9017            to 0 as we leave), and comefrom to save source hook bitmask */
9018 @@ -510,6 +548,8 @@
9019  
9020                 /* Set initial back pointer. */
9021                 e->counters.pcnt = pos;
9022 +               rulenum = 1;
9023 +               chainname = (char *) hooknames[hook];
9024  
9025                 for (;;) {
9026                         struct ipt_standard_target *t
9027 @@ -522,6 +562,8 @@
9028                         }
9029                         e->comefrom
9030                                 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
9031 +                       e->rulenum = rulenum++;
9032 +                       e->chainname = chainname;
9033  
9034                         /* Unconditional return/END. */
9035                         if (e->target_offset == sizeof(struct ipt_entry)
9036 @@ -531,6 +573,10 @@
9037                             && unconditional(&e->ip)) {
9038                                 unsigned int oldpos, size;
9039  
9040 +                               /* Set unconditional rulenum to zero. */
9041 +                               e->rulenum = 0;
9042 +                               e->counters.bcnt = 0;
9043 +
9044                                 /* Return: backtrack through the last
9045                                    big jump. */
9046                                 do {
9047 @@ -556,6 +602,11 @@
9048                                                 (newinfo->entries + pos);
9049                                 } while (oldpos == pos + e->next_offset);
9050  
9051 +                               /* Restore chainname, rulenum. */
9052 +                               chainname = e->chainname;
9053 +                               rulenum = e->counters.bcnt;
9054 +                               e->counters.bcnt = 0;
9055 +
9056                                 /* Move along one */
9057                                 size = e->next_offset;
9058                                 e = (struct ipt_entry *)
9059 @@ -571,6 +622,17 @@
9060                                         /* This a jump; chase it. */
9061                                         duprintf("Jump rule %u -> %u\n",
9062                                                  pos, newpos);
9063 +                                       e->counters.bcnt = rulenum++;
9064 +                                       rulenum = 1;
9065 +                                       e = (struct ipt_entry *)
9066 +                                               (newinfo->entries + newpos);
9067 +                                       if (IPT_ENTRY_ITERATE(newinfo->entries,
9068 +                                                             newinfo->size,
9069 +                                                             find_error_target,
9070 +                                                             e, &chainname) == 0) {
9071 +                                               printk("ip_tables: table screwed up!\n");
9072 +                                               return 0;
9073 +                                       }
9074                                 } else {
9075                                         /* ... this is a fallthru */
9076                                         newpos = pos + e->next_offset;
9077 @@ -1716,9 +1778,9 @@
9078  };
9079  
9080  #ifdef CONFIG_PROC_FS
9081 -static inline int print_name(const char *i,
9082 -                            off_t start_offset, char *buffer, int length,
9083 -                            off_t *pos, unsigned int *count)
9084 +static int print_name(const char *i,
9085 +                      off_t start_offset, char *buffer, int length,
9086 +                      off_t *pos, unsigned int *count)
9087  {
9088         if ((*count)++ >= start_offset) {
9089                 unsigned int namelen;
9090 @@ -1752,6 +1814,15 @@
9091         return pos;
9092  }
9093  
9094 +static inline int print_target(const struct ipt_target *t,
9095 +                               off_t start_offset, char *buffer, int length,
9096 +                               off_t *pos, unsigned int *count)
9097 +{
9098 +       if (t == &ipt_standard_target || t == &ipt_error_target)
9099 +               return 0;
9100 +       return print_name((char *)t, start_offset, buffer, length, pos, count);
9101 +}
9102 +
9103  static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
9104  {
9105         off_t pos = 0;
9106 @@ -1760,7 +1831,7 @@
9107         if (down_interruptible(&ipt_mutex) != 0)
9108                 return 0;
9109  
9110 -       LIST_FIND(&ipt_target, print_name, void *,
9111 +       LIST_FIND(&ipt_target, print_target, struct ipt_target *,
9112                   offset, buffer, length, &pos, &count);
9113         
9114         up(&ipt_mutex);
9115 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6/net/ipv4/netfilter/ipt_CONNMARK.c
9116 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_CONNMARK.c   1970-01-01 01:00:00.000000000 +0100
9117 +++ linux-2.6.6/net/ipv4/netfilter/ipt_CONNMARK.c       2004-05-18 12:38:02.000000000 +0200
9118 @@ -0,0 +1,118 @@
9119 +/* This kernel module is used to modify the connection mark values, or
9120 + * to optionally restore the skb nfmark from the connection mark
9121 + *
9122 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9123 + * by Henrik Nordstrom <hno@marasystems.com>
9124 + *
9125 + * This program is free software; you can redistribute it and/or modify
9126 + * it under the terms of the GNU General Public License as published by
9127 + * the Free Software Foundation; either version 2 of the License, or
9128 + * (at your option) any later version.
9129 + *
9130 + * This program is distributed in the hope that it will be useful,
9131 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9132 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9133 + * GNU General Public License for more details.
9134 + *
9135 + * You should have received a copy of the GNU General Public License
9136 + * along with this program; if not, write to the Free Software
9137 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
9138 + */
9139 +#include <linux/module.h>
9140 +#include <linux/skbuff.h>
9141 +#include <linux/ip.h>
9142 +#include <net/checksum.h>
9143 +
9144 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9145 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
9146 +MODULE_LICENSE("GPL");
9147 +
9148 +#include <linux/netfilter_ipv4/ip_tables.h>
9149 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
9150 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9151 +
9152 +static unsigned int
9153 +target(struct sk_buff **pskb,
9154 +       const struct net_device *in,
9155 +       const struct net_device *out,
9156 +       unsigned int hooknum,
9157 +       const void *targinfo,
9158 +       void *userinfo)
9159 +{
9160 +       const struct ipt_connmark_target_info *markinfo = targinfo;
9161 +       unsigned long diff;
9162 +       unsigned long nfmark;
9163 +       unsigned long newmark;
9164 +
9165 +       enum ip_conntrack_info ctinfo;
9166 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
9167 +       if (ct) {
9168 +           switch(markinfo->mode) {
9169 +           case IPT_CONNMARK_SET:
9170 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
9171 +               if (newmark != ct->mark)
9172 +                   ct->mark = newmark;
9173 +               break;
9174 +           case IPT_CONNMARK_SAVE:
9175 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
9176 +               if (ct->mark != newmark)
9177 +                   ct->mark = newmark;
9178 +               break;
9179 +           case IPT_CONNMARK_RESTORE:
9180 +               nfmark = (*pskb)->nfmark;
9181 +               diff = (ct->mark ^ nfmark & markinfo->mask);
9182 +               if (diff != 0) {
9183 +                   (*pskb)->nfmark = nfmark ^ diff;
9184 +                   (*pskb)->nfcache |= NFC_ALTERED;
9185 +               }
9186 +               break;
9187 +           }
9188 +       }
9189 +
9190 +       return IPT_CONTINUE;
9191 +}
9192 +
9193 +static int
9194 +checkentry(const char *tablename,
9195 +          const struct ipt_entry *e,
9196 +          void *targinfo,
9197 +          unsigned int targinfosize,
9198 +          unsigned int hook_mask)
9199 +{
9200 +       struct ipt_connmark_target_info *matchinfo = targinfo;
9201 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
9202 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
9203 +                      targinfosize,
9204 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
9205 +               return 0;
9206 +       }
9207 +
9208 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
9209 +           if (strcmp(tablename, "mangle") != 0) {
9210 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9211 +                   return 0;
9212 +           }
9213 +       }
9214 +
9215 +       return 1;
9216 +}
9217 +
9218 +static struct ipt_target ipt_connmark_reg = {
9219 +       .name = "CONNMARK",
9220 +       .target = &target,
9221 +       .checkentry = &checkentry,
9222 +       .me = THIS_MODULE
9223 +};
9224 +
9225 +static int __init init(void)
9226 +{
9227 +       return ipt_register_target(&ipt_connmark_reg);
9228 +}
9229 +
9230 +static void __exit fini(void)
9231 +{
9232 +       ipt_unregister_target(&ipt_connmark_reg);
9233 +}
9234 +
9235 +module_init(init);
9236 +module_exit(fini);
9237 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6/net/ipv4/netfilter/ipt_IPMARK.c
9238 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_IPMARK.c     1970-01-01 01:00:00.000000000 +0100
9239 +++ linux-2.6.6/net/ipv4/netfilter/ipt_IPMARK.c 2004-05-18 12:38:15.000000000 +0200
9240 @@ -0,0 +1,81 @@
9241 +/* This is a module which is used for setting the NFMARK field of an skb. */
9242 +#include <linux/module.h>
9243 +#include <linux/skbuff.h>
9244 +#include <linux/ip.h>
9245 +#include <net/checksum.h>
9246 +
9247 +#include <linux/netfilter_ipv4/ip_tables.h>
9248 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
9249 +
9250 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
9251 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
9252 +MODULE_LICENSE("GPL");
9253 +
9254 +static unsigned int
9255 +target(struct sk_buff **pskb,
9256 +       const struct net_device *in,
9257 +       const struct net_device *out,
9258 +       unsigned int hooknum,
9259 +       const void *targinfo,
9260 +       void *userinfo)
9261 +{
9262 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
9263 +       struct iphdr *iph = (*pskb)->nh.iph;
9264 +       unsigned long mark;
9265 +
9266 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
9267 +               mark = (unsigned long) ntohl(iph->saddr);
9268 +       else
9269 +               mark = (unsigned long) ntohl(iph->daddr);
9270 +
9271 +       mark &= ipmarkinfo->andmask;
9272 +       mark |= ipmarkinfo->ormask;
9273 +       
9274 +       if ((*pskb)->nfmark != mark) {
9275 +               (*pskb)->nfmark = mark;
9276 +               (*pskb)->nfcache |= NFC_ALTERED;
9277 +       }
9278 +       return IPT_CONTINUE;
9279 +}
9280 +
9281 +static int
9282 +checkentry(const char *tablename,
9283 +          const struct ipt_entry *e,
9284 +           void *targinfo,
9285 +           unsigned int targinfosize,
9286 +           unsigned int hook_mask)
9287 +{
9288 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
9289 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
9290 +                      targinfosize,
9291 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
9292 +               return 0;
9293 +       }
9294 +
9295 +       if (strcmp(tablename, "mangle") != 0) {
9296 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9297 +               return 0;
9298 +       }
9299 +
9300 +       return 1;
9301 +}
9302 +
9303 +static struct ipt_target ipt_ipmark_reg = { 
9304 +       .name = "IPMARK",
9305 +       .target = target,
9306 +       .checkentry = checkentry,
9307 +       .me = THIS_MODULE
9308 +};
9309 +
9310 +static int __init init(void)
9311 +{
9312 +       return ipt_register_target(&ipt_ipmark_reg);
9313 +}
9314 +
9315 +static void __exit fini(void)
9316 +{
9317 +       ipt_unregister_target(&ipt_ipmark_reg);
9318 +}
9319 +
9320 +module_init(init);
9321 +module_exit(fini);
9322 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.6/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
9323 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      1970-01-01 01:00:00.000000000 +0100
9324 +++ linux-2.6.6/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  2004-05-18 12:36:01.000000000 +0200
9325 @@ -0,0 +1,89 @@
9326 +/**
9327 + * Strip all IP options in the IP packet header.
9328 + *
9329 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
9330 + * This software is distributed under GNU GPL v2, 1991
9331 + */
9332 +
9333 +#include <linux/module.h>
9334 +#include <linux/skbuff.h>
9335 +#include <linux/ip.h>
9336 +#include <net/checksum.h>
9337 +
9338 +#include <linux/netfilter_ipv4/ip_tables.h>
9339 +
9340 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
9341 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
9342 +MODULE_LICENSE("GPL");
9343 +
9344 +static unsigned int
9345 +target(struct sk_buff **pskb,
9346 +       const struct net_device *in,
9347 +       const struct net_device *out,
9348 +       unsigned int hooknum,
9349 +       const void *targinfo,
9350 +       void *userinfo)
9351 +{
9352 +       struct iphdr *iph;
9353 +       struct sk_buff *skb;
9354 +       struct ip_options *opt;
9355 +       unsigned char *optiph;
9356 +       int l;
9357 +       
9358 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
9359 +               return NF_DROP;
9360
9361 +       skb = (*pskb);
9362 +       iph = (*pskb)->nh.iph;
9363 +       optiph = skb->nh.raw;
9364 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
9365 +
9366 +       /* if no options in packet then nothing to clear. */
9367 +       if (iph->ihl * 4 == sizeof(struct iphdr))
9368 +               return IPT_CONTINUE;
9369 +
9370 +       /* else clear all options */
9371 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
9372 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
9373 +       opt = &(IPCB(skb)->opt);
9374 +       opt->is_data = 0;
9375 +       opt->optlen = l;
9376 +
9377 +       skb->nfcache |= NFC_ALTERED;
9378 +
9379 +        return IPT_CONTINUE;
9380 +}
9381 +
9382 +static int
9383 +checkentry(const char *tablename,
9384 +          const struct ipt_entry *e,
9385 +           void *targinfo,
9386 +           unsigned int targinfosize,
9387 +           unsigned int hook_mask)
9388 +{
9389 +       if (strcmp(tablename, "mangle")) {
9390 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9391 +               return 0;
9392 +       }
9393 +       /* nothing else to check because no parameters */
9394 +       return 1;
9395 +}
9396 +
9397 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
9398 +       .name = "IPV4OPTSSTRIP",
9399 +       .target = target,
9400 +       .checkentry = checkentry,
9401 +       .me = THIS_MODULE };
9402 +
9403 +static int __init init(void)
9404 +{
9405 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
9406 +}
9407 +
9408 +static void __exit fini(void)
9409 +{
9410 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9411 +}
9412 +
9413 +module_init(init);
9414 +module_exit(fini);
9415 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_MARK.c linux-2.6.6/net/ipv4/netfilter/ipt_MARK.c
9416 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_MARK.c       2004-05-10 04:32:37.000000000 +0200
9417 +++ linux-2.6.6/net/ipv4/netfilter/ipt_MARK.c   2004-05-18 12:38:18.000000000 +0200
9418 @@ -29,10 +29,20 @@
9419  {
9420         const struct ipt_mark_target_info *markinfo = targinfo;
9421  
9422 -       if((*pskb)->nfmark != markinfo->mark) {
9423 +       switch (markinfo->mode) {
9424 +       case IPT_MARK_SET:
9425                 (*pskb)->nfmark = markinfo->mark;
9426 -               (*pskb)->nfcache |= NFC_ALTERED;
9427 +               break;
9428 +               
9429 +       case IPT_MARK_AND:
9430 +               (*pskb)->nfmark &= markinfo->mark;
9431 +               break;
9432 +               
9433 +       case IPT_MARK_OR:
9434 +               (*pskb)->nfmark |= markinfo->mark;
9435 +               break;
9436         }
9437 +        (*pskb)->nfcache |= NFC_ALTERED;
9438         return IPT_CONTINUE;
9439  }
9440  
9441 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.6/net/ipv4/netfilter/ipt_NETLINK.c
9442 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_NETLINK.c    1970-01-01 01:00:00.000000000 +0100
9443 +++ linux-2.6.6/net/ipv4/netfilter/ipt_NETLINK.c        2004-05-18 12:36:02.000000000 +0200
9444 @@ -0,0 +1,119 @@
9445 +#include <linux/module.h>
9446 +#include <linux/version.h>
9447 +#include <linux/config.h>
9448 +#include <linux/socket.h>
9449 +#include <linux/skbuff.h>
9450 +#include <linux/kernel.h>
9451 +#include <linux/netlink.h>
9452 +#include <linux/netdevice.h>
9453 +#include <linux/mm.h>
9454 +#include <linux/socket.h>
9455 +#include <linux/netfilter_ipv4/ip_tables.h>
9456 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9457 +#include <net/sock.h>
9458 +
9459 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9460 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9461 +MODULE_LICENSE("GPL");
9462 +
9463 +#if 0
9464 +#define DEBUGP printk
9465 +#else
9466 +#define DEBUGP(format, args...)
9467 +#endif
9468 +
9469 +static struct sock *ipfwsk;
9470 +
9471 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9472 +                                   unsigned int hooknum,
9473 +                                   const struct net_device *in,
9474 +                                   const struct net_device *out,
9475 +                                   const void *targinfo, void *userinfo)
9476 +{
9477 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9478 +       struct iphdr *ip = (*pskb)->nh.iph;
9479 +       struct sk_buff *outskb;
9480 +       struct netlink_t nlhdr;
9481 +       size_t len=0;
9482 +
9483 +       /* Allocate a socket buffer */
9484 +       if ( MASK(nld->flags, USE_SIZE) )
9485 +               len = nld->size+sizeof(nlhdr);
9486 +       else
9487 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
9488 +
9489 +       outskb=alloc_skb(len, GFP_ATOMIC);
9490 +
9491 +       if (outskb) {
9492 +               nlhdr.len=len;
9493 +               
9494 +               if ( MASK(nld->flags, USE_MARK) )
9495 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
9496 +               else
9497 +                       nlhdr.mark=(*pskb)->nfmark;
9498 +               
9499 +               if ( in && in->name ) {
9500 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9501 +               }else if ( out && out->name ){
9502 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9503 +               }
9504 +
9505 +               skb_put(outskb, len);
9506 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9507 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9508 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9509 +       }else{
9510 +               if (net_ratelimit())
9511 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9512 +       }
9513 +
9514 +       if ( MASK(nld->flags, USE_DROP) )
9515 +               return NF_DROP;
9516 +
9517 +       return IPT_CONTINUE;
9518 +}
9519 +
9520 +static int ipt_netlink_checkentry(const char *tablename,
9521 +                              const struct ipt_entry *e,
9522 +                              void *targinfo,
9523 +                              unsigned int targinfosize,
9524 +                              unsigned int hookmask)
9525 +{
9526 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9527 +
9528 +       return 1;
9529 +}
9530 +
9531 +static struct ipt_target ipt_netlink_reg = { 
9532 +       {NULL, NULL},
9533 +       "NETLINK",
9534 +       ipt_netlink_target,
9535 +       ipt_netlink_checkentry,
9536 +       NULL,
9537 +       THIS_MODULE
9538 +};
9539 +
9540 +static int __init init(void)
9541 +{
9542 +       DEBUGP("ipt_NETLINK: init module\n");   
9543 +
9544 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
9545 +               return -EINVAL;
9546 +       }
9547 +
9548 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9549 +               return -EINVAL;
9550 +       }
9551 +
9552 +       return 0;
9553 +}
9554 +
9555 +static void __exit fini(void)
9556 +{
9557 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
9558 +       ipt_unregister_target(&ipt_netlink_reg);
9559 +       if(ipfwsk->sk_socket) sock_release(ipfwsk->sk_socket);
9560 +}
9561 +
9562 +module_init(init);
9563 +module_exit(fini);
9564 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.6/net/ipv4/netfilter/ipt_POOL.c
9565 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_POOL.c       1970-01-01 01:00:00.000000000 +0100
9566 +++ linux-2.6.6/net/ipv4/netfilter/ipt_POOL.c   2004-05-18 12:36:48.000000000 +0200
9567 @@ -0,0 +1,116 @@
9568 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9569 + *
9570 + * This target can be used almost everywhere. It acts on some specified
9571 + * IP pool, adding or deleting some IP address in the pool. The address
9572 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9573 + * of the packet under inspection.
9574 + *
9575 + * The target normally returns IPT_CONTINUE.
9576 + */
9577 +
9578 +#include <linux/types.h>
9579 +#include <linux/ip.h>
9580 +#include <linux/timer.h>
9581 +#include <linux/module.h>
9582 +#include <linux/netfilter.h>
9583 +#include <linux/netdevice.h>
9584 +#include <linux/if.h>
9585 +#include <linux/inetdevice.h>
9586 +#include <net/protocol.h>
9587 +#include <net/checksum.h>
9588 +#include <linux/netfilter_ipv4.h>
9589 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9590 +#include <linux/netfilter_ipv4/ipt_pool.h>
9591 +
9592 +#if 0
9593 +#define DEBUGP printk
9594 +#else
9595 +#define DEBUGP(format, args...)
9596 +#endif
9597 +
9598 +/*** NOTE NOTE NOTE NOTE ***
9599 +**
9600 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9601 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9602 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9603 +** is modified for the source IP address of the packet under inspection.
9604 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9605 +**
9606 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9607 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9608 +**
9609 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9610 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9611 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9612 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9613 +*/
9614 +
9615 +static int
9616 +do_check(const char *tablename,
9617 +              const struct ipt_entry *e,
9618 +              void *targinfo,
9619 +              unsigned int targinfosize,
9620 +              unsigned int hook_mask)
9621 +{
9622 +       const struct ipt_pool_info *ipi = targinfo;
9623 +
9624 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9625 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
9626 +               return 0;
9627 +       }
9628 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9629 +       return 1;
9630 +}
9631 +
9632 +static unsigned int
9633 +do_target(struct sk_buff **pskb,
9634 +               unsigned int hooknum,
9635 +               const struct net_device *in,
9636 +               const struct net_device *out,
9637 +               const void *targinfo,
9638 +               void *userinfo)
9639 +{
9640 +       const struct ipt_pool_info *ipi = targinfo;
9641 +       int modified;
9642 +       unsigned int verdict = IPT_CONTINUE;
9643 +
9644 +       if (ipi->src != IP_POOL_NONE) {
9645 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9646 +                                       ipi->flags & IPT_POOL_DEL_SRC);
9647 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9648 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9649 +                               verdict = NF_ACCEPT;
9650 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9651 +                               verdict = NF_DROP;
9652 +               }
9653 +       }
9654 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9655 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9656 +                                       ipi->flags & IPT_POOL_DEL_DST);
9657 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9658 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9659 +                               verdict = NF_ACCEPT;
9660 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9661 +                               verdict = NF_DROP;
9662 +               }
9663 +       }
9664 +       return verdict;
9665 +}
9666 +
9667 +static struct ipt_target pool_reg
9668 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9669 +
9670 +static int __init init(void)
9671 +{
9672 +       DEBUGP("init ipt_POOL\n");
9673 +       return ipt_register_target(&pool_reg);
9674 +}
9675 +
9676 +static void __exit fini(void)
9677 +{
9678 +       DEBUGP("fini ipt_POOL\n");
9679 +       ipt_unregister_target(&pool_reg);
9680 +}
9681 +
9682 +module_init(init);
9683 +module_exit(fini);
9684 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.6/net/ipv4/netfilter/ipt_ROUTE.c
9685 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_ROUTE.c      1970-01-01 01:00:00.000000000 +0100
9686 +++ linux-2.6.6/net/ipv4/netfilter/ipt_ROUTE.c  2004-05-18 12:38:20.000000000 +0200
9687 @@ -0,0 +1,393 @@
9688 +/*
9689 + * This implements the ROUTE target, which enables you to setup unusual
9690 + * routes not supported by the standard kernel routing table.
9691 + *
9692 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
9693 + *
9694 + * v 1.9 2004/05/14
9695 + *
9696 + * This software is distributed under GNU GPL v2, 1991
9697 + */
9698 +
9699 +#include <linux/module.h>
9700 +#include <linux/skbuff.h>
9701 +#include <linux/ip.h>
9702 +#include <linux/netfilter_ipv4/ip_tables.h>
9703 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
9704 +#include <linux/netdevice.h>
9705 +#include <linux/route.h>
9706 +#include <net/ip.h>
9707 +#include <net/route.h>
9708 +#include <net/icmp.h>
9709 +#include <net/checksum.h>
9710 +
9711 +#if 0
9712 +#define DEBUGP printk
9713 +#else
9714 +#define DEBUGP(format, args...)
9715 +#endif
9716 +
9717 +MODULE_LICENSE("GPL");
9718 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
9719 +MODULE_DESCRIPTION("iptables ROUTE target module");
9720 +
9721 +/* Try to route the packet according to the routing keys specified in
9722 + * route_info. Keys are :
9723 + *  - ifindex : 
9724 + *      0 if no oif preferred, 
9725 + *      otherwise set to the index of the desired oif
9726 + *  - route_info->gw :
9727 + *      0 if no gateway specified,
9728 + *      otherwise set to the next host to which the pkt must be routed
9729 + * If success, skb->dev is the output device to which the packet must 
9730 + * be sent and skb->dst is not NULL
9731 + *
9732 + * RETURN: -1 if an error occured
9733 + *          1 if the packet was succesfully routed to the 
9734 + *            destination desired
9735 + *          0 if the kernel routing table could not route the packet
9736 + *            according to the keys specified
9737 + */
9738 +static int route(struct sk_buff *skb,
9739 +                unsigned int ifindex,
9740 +                const struct ipt_route_target_info *route_info)
9741 +{
9742 +       int err;
9743 +       struct rtable *rt;
9744 +       struct iphdr *iph = skb->nh.iph;
9745 +       struct flowi fl = {
9746 +               .oif = ifindex,
9747 +               .nl_u = {
9748 +                       .ip4_u = {
9749 +                               .daddr = iph->daddr,
9750 +                               .saddr = 0,
9751 +                               .tos = RT_TOS(iph->tos),
9752 +                               .scope = RT_SCOPE_UNIVERSE,
9753 +                       }
9754 +               } 
9755 +       };
9756 +       
9757 +       /* The destination address may be overloaded by the target */
9758 +       if (route_info->gw)
9759 +               fl.fld_dst = route_info->gw;
9760 +       
9761 +       /* Trying to route the packet using the standard routing table. */
9762 +       if ((err = ip_route_output_key(&rt, &fl))) {
9763 +               if (net_ratelimit()) 
9764 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
9765 +               return -1;
9766 +       }
9767 +       
9768 +       /* Drop old route. */
9769 +       dst_release(skb->dst);
9770 +       skb->dst = NULL;
9771 +
9772 +       /* Success if no oif specified or if the oif correspond to the 
9773 +        * one desired */
9774 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
9775 +               skb->dst = &rt->u.dst;
9776 +               skb->dev = skb->dst->dev;
9777 +               return 1;
9778 +       }
9779 +       
9780 +       /* The interface selected by the routing table is not the one
9781 +        * specified by the user. This may happen because the dst address
9782 +        * is one of our own addresses.
9783 +        */
9784 +       if (net_ratelimit()) 
9785 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
9786 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
9787 +       
9788 +       return 0;
9789 +}
9790 +
9791 +
9792 +/* Stolen from ip_finish_output2
9793 + * PRE : skb->dev is set to the device we are leaving by
9794 + *       skb->dst is not NULL
9795 + * POST: the packet is sent with the link layer header pushed
9796 + *       the packet is destroyed
9797 + */
9798 +static void ip_direct_send(struct sk_buff *skb)
9799 +{
9800 +       struct dst_entry *dst = skb->dst;
9801 +       struct hh_cache *hh = dst->hh;
9802 +
9803 +       if (hh) {
9804 +               read_lock_bh(&hh->hh_lock);
9805 +               memcpy(skb->data - 16, hh->hh_data, 16);
9806 +               read_unlock_bh(&hh->hh_lock);
9807 +               skb_push(skb, hh->hh_len);
9808 +               hh->hh_output(skb);
9809 +       } else if (dst->neighbour)
9810 +               dst->neighbour->output(skb);
9811 +       else {
9812 +               if (net_ratelimit())
9813 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
9814 +               kfree_skb(skb);
9815 +       }
9816 +}
9817 +
9818 +
9819 +/* PRE : skb->dev is set to the device we are leaving by
9820 + * POST: - the packet is directly sent to the skb->dev device, without 
9821 + *         pushing the link layer header.
9822 + *       - the packet is destroyed
9823 + */
9824 +static inline int dev_direct_send(struct sk_buff *skb)
9825 +{
9826 +       return dev_queue_xmit(skb);
9827 +}
9828 +
9829 +
9830 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
9831 +                             struct sk_buff *skb) 
9832 +{
9833 +       unsigned int ifindex = 0;
9834 +       struct net_device *dev_out = NULL;
9835 +
9836 +       /* The user set the interface name to use.
9837 +        * Getting the current interface index.
9838 +        */
9839 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
9840 +               ifindex = dev_out->ifindex;
9841 +       } else {
9842 +               /* Unknown interface name : packet dropped */
9843 +               if (net_ratelimit()) 
9844 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
9845 +               return NF_DROP;
9846 +       }
9847 +
9848 +       /* Trying the standard way of routing packets */
9849 +       switch (route(skb, ifindex, route_info)) {
9850 +       case 1:
9851 +               dev_put(dev_out);
9852 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
9853 +                       return IPT_CONTINUE;
9854 +
9855 +               ip_direct_send(skb);
9856 +               return NF_STOLEN;
9857 +
9858 +       case 0:
9859 +               /* Failed to send to oif. Trying the hard way */
9860 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
9861 +                       return NF_DROP;
9862 +
9863 +               if (net_ratelimit()) 
9864 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
9865 +                              ifindex);
9866 +
9867 +               /* We have to force the use of an interface.
9868 +                * This interface must be a tunnel interface since
9869 +                * otherwise we can't guess the hw address for
9870 +                * the packet. For a tunnel interface, no hw address
9871 +                * is needed.
9872 +                */
9873 +               if ((dev_out->type != ARPHRD_TUNNEL)
9874 +                   && (dev_out->type != ARPHRD_IPGRE)) {
9875 +                       if (net_ratelimit()) 
9876 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
9877 +                       dev_put(dev_out);
9878 +                       return NF_DROP;
9879 +               }
9880 +       
9881 +               /* Send the packet. This will also free skb
9882 +                * Do not go through the POST_ROUTING hook because 
9883 +                * skb->dst is not set and because it will probably
9884 +                * get confused by the destination IP address.
9885 +                */
9886 +               skb->dev = dev_out;
9887 +               dev_direct_send(skb);
9888 +               dev_put(dev_out);
9889 +               return NF_STOLEN;
9890 +               
9891 +       default:
9892 +               /* Unexpected error */
9893 +               dev_put(dev_out);
9894 +               return NF_DROP;
9895 +       }
9896 +}
9897 +
9898 +
9899 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
9900 +                             struct sk_buff *skb) 
9901 +{
9902 +       struct net_device *dev_in = NULL;
9903 +
9904 +       /* Getting the current interface index. */
9905 +       if (!(dev_in = dev_get_by_name(route_info->iif))) {
9906 +               if (net_ratelimit()) 
9907 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
9908 +               return NF_DROP;
9909 +       }
9910 +
9911 +       skb->dev = dev_in;
9912 +       dst_release(skb->dst);
9913 +       skb->dst = NULL;
9914 +
9915 +       netif_rx(skb);
9916 +       dev_put(dev_in);
9917 +       return NF_STOLEN;
9918 +}
9919 +
9920 +
9921 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
9922 +                            struct sk_buff *skb) 
9923 +{
9924 +       if (route(skb, 0, route_info)!=1)
9925 +               return NF_DROP;
9926 +
9927 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
9928 +               return IPT_CONTINUE;
9929 +
9930 +       ip_direct_send(skb);
9931 +       return NF_STOLEN;
9932 +}
9933 +
9934 +
9935 +static unsigned int ipt_route_target(struct sk_buff **pskb,
9936 +                                    const struct net_device *in,
9937 +                                    const struct net_device *out,
9938 +                                    unsigned int hooknum,
9939 +                                    const void *targinfo,
9940 +                                    void *userinfo)
9941 +{
9942 +       const struct ipt_route_target_info *route_info = targinfo;
9943 +       struct sk_buff *skb = *pskb;
9944 +
9945 +       /* If we are at PREROUTING or INPUT hook
9946 +        * the TTL isn't decreased by the IP stack
9947 +        */
9948 +       if (hooknum == NF_IP_PRE_ROUTING ||
9949 +           hooknum == NF_IP_LOCAL_IN) {
9950 +
9951 +               struct iphdr *iph = skb->nh.iph;
9952 +
9953 +               if (iph->ttl <= 1) {
9954 +                       struct rtable *rt;
9955 +                       struct flowi fl = {
9956 +                               .oif = 0,
9957 +                               .nl_u = {
9958 +                                       .ip4_u = {
9959 +                                               .daddr = iph->daddr,
9960 +                                               .saddr = iph->saddr,
9961 +                                               .tos = RT_TOS(iph->tos),
9962 +                                               .scope = ((iph->tos & RTO_ONLINK) ?
9963 +                                                         RT_SCOPE_LINK :
9964 +                                                         RT_SCOPE_UNIVERSE)
9965 +                                       }
9966 +                               } 
9967 +                       };
9968 +
9969 +                       if (ip_route_output_key(&rt, &fl)) {
9970 +                               return NF_DROP;
9971 +                       }
9972 +
9973 +                       if (skb->dev == rt->u.dst.dev) {
9974 +                               /* Drop old route. */
9975 +                               dst_release(skb->dst);
9976 +                               skb->dst = &rt->u.dst;
9977 +
9978 +                               /* this will traverse normal stack, and 
9979 +                                * thus call conntrack on the icmp packet */
9980 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
9981 +                                         ICMP_EXC_TTL, 0);
9982 +                       }
9983 +
9984 +                       return NF_DROP;
9985 +               }
9986 +
9987 +               /*
9988 +                * If we are at INPUT the checksum must be recalculated since
9989 +                * the length could change as the result of a defragmentation.
9990 +                */
9991 +               if(hooknum == NF_IP_LOCAL_IN) {
9992 +                       iph->ttl = iph->ttl - 1;
9993 +                       iph->check = 0;
9994 +                       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
9995 +               } else {
9996 +                       ip_decrease_ttl(iph);
9997 +               }
9998 +       }
9999 +
10000 +       /* Tell conntrack to forget this packet since it may get confused 
10001 +        * when a packet is leaving with dst address == our address.
10002 +        * Good idea ? Dunno. Need advice.
10003 +        */
10004 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
10005 +               nf_conntrack_put(skb->nfct);
10006 +               skb->nfct = NULL;
10007 +               skb->nfcache = 0;
10008 +#ifdef CONFIG_NETFILTER_DEBUG
10009 +               skb->nf_debug = 0;
10010 +#endif
10011 +       }
10012 +
10013 +       if (route_info->oif[0] != '\0') 
10014 +               return route_oif(route_info, *pskb);
10015 +       
10016 +       if (route_info->iif[0] != '\0') 
10017 +               return route_iif(route_info, *pskb);
10018 +
10019 +       if (route_info->gw) 
10020 +               return route_gw(route_info, *pskb);
10021 +
10022 +       if (net_ratelimit()) 
10023 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
10024 +
10025 +       return IPT_CONTINUE;
10026 +}
10027 +
10028 +
10029 +static int ipt_route_checkentry(const char *tablename,
10030 +                               const struct ipt_entry *e,
10031 +                               void *targinfo,
10032 +                               unsigned int targinfosize,
10033 +                               unsigned int hook_mask)
10034 +{
10035 +       if (strcmp(tablename, "mangle") != 0) {
10036 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
10037 +                      tablename);
10038 +               return 0;
10039 +       }
10040 +
10041 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
10042 +                           | (1 << NF_IP_LOCAL_IN)
10043 +                           | (1 << NF_IP_FORWARD)
10044 +                           | (1 << NF_IP_LOCAL_OUT)
10045 +                           | (1 << NF_IP_POST_ROUTING))) {
10046 +               printk("ipt_ROUTE: bad hook\n");
10047 +               return 0;
10048 +       }
10049 +
10050 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
10051 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
10052 +                      targinfosize,
10053 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
10054 +               return 0;
10055 +       }
10056 +
10057 +       return 1;
10058 +}
10059 +
10060 +
10061 +static struct ipt_target ipt_route_reg = { 
10062 +       .name = "ROUTE",
10063 +       .target = ipt_route_target,
10064 +       .checkentry = ipt_route_checkentry,
10065 +       .me = THIS_MODULE,
10066 +};
10067 +
10068 +static int __init init(void)
10069 +{
10070 +       return ipt_register_target(&ipt_route_reg);
10071 +}
10072 +
10073 +
10074 +static void __exit fini(void)
10075 +{
10076 +       ipt_unregister_target(&ipt_route_reg);
10077 +}
10078 +
10079 +module_init(init);
10080 +module_exit(fini);
10081 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6/net/ipv4/netfilter/ipt_TARPIT.c
10082 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TARPIT.c     1970-01-01 01:00:00.000000000 +0100
10083 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TARPIT.c 2004-05-18 12:38:28.000000000 +0200
10084 @@ -0,0 +1,290 @@
10085 +/* 
10086 + * Kernel module to capture and hold incoming TCP connections using 
10087 + * no local per-connection resources.
10088 + * 
10089 + * Based on ipt_REJECT.c and offering functionality similar to 
10090 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
10091 + * 
10092 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
10093 + * 
10094 + * This program is free software; you can redistribute it and/or modify
10095 + * it under the terms of the GNU General Public License as published by
10096 + * the Free Software Foundation; either version 2 of the License, or
10097 + * (at your option) any later version.
10098 + *
10099 + * This program is distributed in the hope that it will be useful,
10100 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10101 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10102 + * GNU General Public License for more details.
10103 + *
10104 + * You should have received a copy of the GNU General Public License
10105 + * along with this program; if not, write to the Free Software
10106 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10107 + * 
10108 + * Goal:
10109 + * - Allow incoming TCP connections to be established.
10110 + * - Passing data should result in the connection being switched to the 
10111 + *   persist state (0 byte window), in which the remote side stops sending 
10112 + *   data and asks to continue every 60 seconds.
10113 + * - Attempts to shut down the connection should be ignored completely, so 
10114 + *   the remote side ends up having to time it out.
10115 + *
10116 + * This means:
10117 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
10118 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
10119 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
10120 + */
10121 +
10122 +#include <linux/config.h>
10123 +#include <linux/module.h>
10124 +#include <linux/skbuff.h>
10125 +#include <linux/ip.h>
10126 +#include <net/ip.h>
10127 +#include <net/tcp.h>
10128 +#include <net/icmp.h>
10129 +struct in_device;
10130 +#include <net/route.h>
10131 +#include <linux/random.h>
10132 +#include <linux/netfilter_ipv4/ip_tables.h>
10133 +
10134 +#if 0
10135 +#define DEBUGP printk
10136 +#else
10137 +#define DEBUGP(format, args...)
10138 +#endif
10139 +
10140 +MODULE_LICENSE("GPL");
10141 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
10142 +
10143 +/* Stolen from ip_finish_output2 */
10144 +static int ip_direct_send(struct sk_buff *skb)
10145 +{
10146 +       struct dst_entry *dst = skb->dst;
10147 +       struct hh_cache *hh = dst->hh;
10148 +
10149 +       if (hh) {    
10150 +               read_lock_bh(&hh->hh_lock);
10151 +               memcpy(skb->data - 16, hh->hh_data, 16);
10152 +                read_unlock_bh(&hh->hh_lock);
10153 +                skb_push(skb, hh->hh_len);
10154 +                return hh->hh_output(skb);
10155 +        } else if (dst->neighbour)
10156 +                return dst->neighbour->output(skb);
10157 +
10158 +       if (net_ratelimit())
10159 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
10160 +        kfree_skb(skb);
10161 +        return -EINVAL;
10162 +}
10163 +
10164 +
10165 +/* Send reply */
10166 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
10167 +{
10168 +       struct sk_buff *nskb;
10169 +       struct rtable *nrt;
10170 +       struct tcphdr *otcph, *ntcph;
10171 +       struct flowi fl = {};
10172 +       unsigned int otcplen;
10173 +       u_int16_t tmp;
10174 +
10175 +       /* A truncated TCP header isn't going to be useful */
10176 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
10177 +               return;
10178 +
10179 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
10180 +                                  + oskb->nh.iph->ihl);
10181 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
10182 +
10183 +       /* No replies for RST or FIN */
10184 +       if (otcph->rst || otcph->fin)
10185 +               return;
10186 +
10187 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
10188 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
10189 +               return;
10190 +
10191 +       /* Check checksum. */
10192 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
10193 +                        oskb->nh.iph->daddr,
10194 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
10195 +               return;
10196 +
10197 +       /* Copy skb (even if skb is about to be dropped, we can't just
10198 +           clone it because there may be other things, such as tcpdump,
10199 +           interested in it) */
10200 +       nskb = skb_copy(oskb, GFP_ATOMIC);
10201 +       if (!nskb)
10202 +               return;
10203 +
10204 +       /* This packet will not be the same as the other: clear nf fields */
10205 +       nf_conntrack_put(nskb->nfct);
10206 +       nskb->nfct = NULL;
10207 +       nskb->nfcache = 0;
10208 +#ifdef CONFIG_NETFILTER_DEBUG
10209 +       nskb->nf_debug = 0;
10210 +#endif
10211 +
10212 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
10213 +
10214 +       /* Truncate to length (no data) */
10215 +       ntcph->doff = sizeof(struct tcphdr)/4;
10216 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
10217 +       nskb->nh.iph->tot_len = htons(nskb->len);
10218 +
10219 +       /* Swap source and dest */
10220 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
10221 +       tmp = ntcph->source;
10222 +       ntcph->source = ntcph->dest;
10223 +       ntcph->dest = tmp;
10224 +
10225 +       /* Use supplied sequence number or make a new one */
10226 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
10227 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
10228 +                                                       nskb->nh.iph->daddr, 
10229 +                                                       ntcph->source, 
10230 +                                                       ntcph->dest));
10231 +
10232 +       /* Our SYN-ACKs must have a >0 window */
10233 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
10234 +
10235 +       ntcph->urg_ptr = 0;
10236 +
10237 +       /* Reset flags */
10238 +       ((u_int8_t *)ntcph)[13] = 0;
10239 +
10240 +       if (otcph->syn && otcph->ack) {
10241 +               ntcph->rst = 1;
10242 +               ntcph->ack_seq = 0;
10243 +       } else {
10244 +               ntcph->syn = otcph->syn;
10245 +               ntcph->ack = 1;
10246 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
10247 +       }
10248 +
10249 +       /* Adjust TCP checksum */
10250 +       ntcph->check = 0;
10251 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
10252 +                                  nskb->nh.iph->saddr,
10253 +                                  nskb->nh.iph->daddr,
10254 +                                  csum_partial((char *)ntcph,
10255 +                                               sizeof(struct tcphdr), 0));
10256 +
10257 +       /* Adjust IP TTL */
10258 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
10259 +
10260 +       /* Set DF, id = 0 */
10261 +       nskb->nh.iph->frag_off = htons(IP_DF);
10262 +       nskb->nh.iph->id = 0;
10263 +
10264 +       /* Adjust IP checksum */
10265 +       nskb->nh.iph->check = 0;
10266 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
10267 +                                          nskb->nh.iph->ihl);
10268 +
10269 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
10270 +       fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
10271 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
10272 +       fl.oif = 0;
10273 +
10274 +       if (ip_route_output_key(&nrt, &fl))
10275 +               goto free_nskb;
10276 +
10277 +       dst_release(nskb->dst);
10278 +       nskb->dst = &nrt->u.dst;
10279 +
10280 +       /* "Never happens" */
10281 +       if (nskb->len > dst_pmtu(nskb->dst))
10282 +               goto free_nskb;
10283 +
10284 +       ip_direct_send (nskb);
10285 +
10286 +       return;
10287 +
10288 + free_nskb:
10289 +       kfree_skb(nskb);
10290 +}
10291 +
10292 +
10293 +static unsigned int tarpit(struct sk_buff **pskb,
10294 +                          const struct net_device *in,
10295 +                          const struct net_device *out,
10296 +                          unsigned int hooknum,
10297 +                          const void *targinfo,
10298 +                          void *userinfo)
10299 +{
10300 +       struct sk_buff *skb = *pskb;
10301 +       struct rtable *rt = (struct rtable*)skb->dst;
10302 +
10303 +       /* Do we have an input route cache entry? */
10304 +       if (!rt)
10305 +               return NF_DROP;
10306 +
10307 +        /* No replies to physical multicast/broadcast */
10308 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
10309 +               return NF_DROP;
10310 +
10311 +        /* Now check at the protocol level */
10312 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
10313 +                return NF_DROP;
10314 +
10315 +       /* Our naive response construction doesn't deal with IP
10316 +           options, and probably shouldn't try. */
10317 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
10318 +               return NF_DROP;
10319 +
10320 +        /* We aren't interested in fragments */
10321 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
10322 +                return NF_DROP;
10323 +
10324 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
10325 +
10326 +       return NF_DROP;
10327 +}
10328 +
10329 +
10330 +static int check(const char *tablename,
10331 +                const struct ipt_entry *e,
10332 +                void *targinfo,
10333 +                unsigned int targinfosize,
10334 +                unsigned int hook_mask)
10335 +{
10336 +       /* Only allow these for input/forward packet filtering. */
10337 +       if (strcmp(tablename, "filter") != 0) {
10338 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
10339 +               return 0;
10340 +       }
10341 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
10342 +                           | (1 << NF_IP_FORWARD))) != 0) {
10343 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
10344 +               return 0;
10345 +       }
10346 +
10347 +       /* Must specify that it's a TCP packet */
10348 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
10349 +               DEBUGP("TARPIT: not valid for non-tcp\n");
10350 +               return 0;
10351 +       }
10352 +
10353 +       return 1;
10354 +}
10355 +
10356 +static struct ipt_target ipt_tarpit_reg = { 
10357 +       .name = "TARPIT",
10358 +       .target = tarpit,
10359 +       .checkentry = check,
10360 +       .me = THIS_MODULE
10361 +};
10362 +
10363 +static int __init init(void)
10364 +{
10365 +       return ipt_register_target(&ipt_tarpit_reg);
10366 +}
10367 +
10368 +static void __exit fini(void)
10369 +{
10370 +       ipt_unregister_target(&ipt_tarpit_reg);
10371 +}
10372 +
10373 +module_init(init);
10374 +module_exit(fini);
10375 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.6/net/ipv4/netfilter/ipt_TCPLAG.c
10376 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TCPLAG.c     1970-01-01 01:00:00.000000000 +0100
10377 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TCPLAG.c 2004-05-18 12:38:29.000000000 +0200
10378 @@ -0,0 +1,697 @@
10379 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
10380 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
10381 + *
10382 + * This program is free software; you can redistribute it and/or modify
10383 + * it under the terms of the GNU General Public License as published by
10384 + * the Free Software Foundation; either version 2 of the License, or
10385 + * (at your option) any later version.
10386 + *
10387 + * This program is distributed in the hope that it will be useful,
10388 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10389 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10390 + * GNU General Public License for more details.
10391 + *
10392 + * You should have received a copy of the GNU General Public License
10393 + * along with this program; if not, write to the Free Software
10394 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10395 + */
10396 +
10397 +/*
10398 + * This collects packets and attempts to make them into pairs
10399 + * based on its own knowledge of how typical network conversations
10400 + * operate. Once it has a pair, it logs the time between them.
10401 + */
10402 +#include <linux/module.h>
10403 +#include <linux/skbuff.h>
10404 +#include <linux/ip.h>
10405 +#include <linux/spinlock.h>
10406 +#include <net/icmp.h>
10407 +#include <net/udp.h>
10408 +#include <net/tcp.h>
10409 +#include <linux/netfilter_ipv4/ip_tables.h>
10410 +
10411 +#include <net/route.h>
10412 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
10413 +
10414 +#if 0
10415 +#define DEBUGP printk
10416 +#else
10417 +#define DEBUGP(format, args...)
10418 +#endif
10419 +
10420 +/*
10421 + * We need one spinlock for the hash table.
10422 + */
10423 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
10424 +
10425 +typedef struct timeval timeval_T;
10426 +
10427 +/*
10428 + * Linked lists of events in the connection,
10429 + * these store the SEQ numbers and the newest is always
10430 + * at the start of the linked list, then they get older
10431 + * down to the end of the linked list (this is not perfect
10432 + * if packets get out of order but we don't worry about fine
10433 + * details like that).
10434 + *
10435 + * Matching any event wipes out that event and also all other
10436 + * events down the chain (i.e. all older events).
10437 + * This keeps the linked list as short as possible.
10438 + */
10439 +typedef struct tcplag_event_S
10440 +{
10441 +       struct tcplag_event_S *next;
10442 +       u16 source_port;
10443 +       u16 dest_port;
10444 +       u32 expected_ACK;
10445 +       struct timeval stamp;
10446 +} tcplag_event_T;
10447 +
10448 +/*
10449 + * This stores the connection statistics
10450 + * We define connections more loosely than TCP/IP does,
10451 + * because we only consider the two hosts, not the ports
10452 + * Also, we list the host-pairs in low,high order which
10453 + * means that we don't care who originated the connection.
10454 + */
10455 +typedef struct tcplag_hash_S
10456 +{
10457 +       u32 low_ip;
10458 +       u32 high_ip;
10459 +       struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
10460 +       struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
10461 +       tcplag_event_T *h_ACK_list;     /* Try to match ACK packets coming from h in this list */
10462 +       tcplag_event_T *l_ACK_list;     /* Try to match ACK packets coming from l in this list */
10463 +       time_t stamp;                   /* When this bucket got added to the table */
10464 +       u16 count_l_SEQ_h_ACK;          /* Increment for each event */
10465 +       u16 count_h_SEQ_l_ACK;          /* Increment for each event */
10466 +} tcplag_hash_T;
10467 +
10468 +static tcplag_hash_T **hashtab = 0;
10469 +static u32 hashsize = 0;
10470 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
10471 +static u32 reaper_ix = 0;
10472 +
10473 +static void divide_down( timeval_T *T, int c )
10474 +{
10475 +       int remainder;
10476 +
10477 +       T->tv_usec /= c;
10478 +       remainder = T->tv_sec % c; /* Only works properly with positive numbers */
10479 +       remainder *= 1000000;
10480 +       T->tv_usec == remainder;
10481 +       T->tv_sec /= c;
10482 +}
10483 +
10484 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
10485 +{
10486 +       register long x;
10487 +
10488 +       x = tv1->tv_sec - tv2->tv_sec;
10489 +       if( x ) return( x );
10490 +       x = tv1->tv_usec - tv2->tv_usec;
10491 +       return( x );
10492 +}
10493 +
10494 +void sprint_timeval( char *buf, timeval_T *tv )
10495 +{
10496 +       if( tv->tv_sec )
10497 +               sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
10498 +       else
10499 +               sprintf( buf, "%lu", tv->tv_usec );
10500 +}
10501 +
10502 +/*
10503 + * This generates the log messages through printk()
10504 + *
10505 + * There is really no particular interest in the port numbers at this stage,
10506 + * they are only useful for matching up the request with the reply.
10507 + * The IP numbers are useful because some sites may be slower than others
10508 + * or may travel different routes, etc (OK, in theory changing the port number
10509 + * could also change the route but I don't like that sort of theory).
10510 + *
10511 + * The tags are:
10512 + *
10513 + * LIP=          The IP number of the side with the lowest lag
10514 + * RIP=          The IP number of the side with the highest lag
10515 + * LLAG=         The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
10516 + * RLAG=         The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
10517 + */
10518 +static void output( tcplag_hash_T *H, int level, const char *prefix )
10519 +{
10520 +       struct timeval ltm, rtm;
10521 +       u32 local_ip, remote_ip;
10522 +       char r_buf[ 20 ], l_buf[ 20 ];
10523 +/*
10524 + * We can't make sense of a connection that only passes data one way,
10525 + * In principle, at least the SYN and FIN should go both ways so we
10526 + * should get a few hits for every connection.
10527 + */
10528 +       if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
10529 +/*
10530 + * Calculate average times by dividing down
10531 + */
10532 +       divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
10533 +       divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
10534 +/*
10535 + * Sort these two by the lag so the the local is always the short lag
10536 + */
10537 +       if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
10538 +       {
10539 +               local_ip    = H->low_ip;
10540 +               remote_ip   = H->high_ip;
10541 +               rtm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
10542 +               rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
10543 +               ltm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
10544 +               ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
10545 +       }
10546 +       else
10547 +       {
10548 +               local_ip    = H->high_ip;
10549 +               remote_ip   = H->low_ip;
10550 +               ltm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
10551 +               ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
10552 +               rtm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
10553 +               rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
10554 +       }
10555 +/*
10556 + * Don't use a spinlock on the output,
10557 + * it is not guaranteed safe because some OTHER printk could
10558 + * split our log message so we want only one single printk.
10559 + *
10560 + * We use sprintf() to partially pre-digest the output
10561 + *
10562 + * Actually, neither this not the main netfilter LOG target is
10563 + * really safe from printk() overlap, basically syslog cannot
10564 + * be regarded as a guaranteed data output channel. It is good
10565 + * enough for most purposes.
10566 + */
10567 +       sprint_timeval( l_buf, &ltm );
10568 +       sprint_timeval( r_buf, &rtm );
10569 +       printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
10570 +                       level & 7, prefix,
10571 +                       NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
10572 +                       l_buf, r_buf );
10573 +}
10574 +
10575 +/*
10576 + * The reaper rolls through the hash table looking for old.
10577 + * Log entries are only generated at the reaping time
10578 + * (which means all log entries are out-of-date)
10579 + */
10580 +static void reaper( time_t now, int level, const char *prefix )
10581 +{
10582 +       int i;
10583 +
10584 +       now -= max_seconds;
10585 +       if( !hashsize ) return;
10586 +       if( !hashtab ) return;
10587 +       for( i = 0; i < 10; i++ )
10588 +       {
10589 +               if( ++reaper_ix >= hashsize ) reaper_ix = 0; 
10590 +
10591 +//             DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
10592 +
10593 +               if( hashtab[ reaper_ix ])
10594 +               {
10595 +                       tcplag_hash_T *found = 0;
10596 +
10597 +                       spin_lock_bh( &hash_lock );
10598 +                       if( hashtab[ reaper_ix ])
10599 +                       {
10600 +                               if( now > hashtab[ reaper_ix ]->stamp )
10601 +                               {
10602 +                                       DEBUGP( KERN_WARNING "reaper found expired entry\n" );
10603 +                                       found = hashtab[ reaper_ix ];
10604 +                                       hashtab[ reaper_ix ] = 0;
10605 +                               }
10606 +                       }
10607 +                       spin_unlock_bh( &hash_lock );
10608 +
10609 +                       if( found )
10610 +                       {
10611 +                               output( found, level, prefix );
10612 +                               kfree( found );
10613 +                       }
10614 +               }
10615 +       }
10616 +}
10617 +
10618 +/*
10619 + * Convert the connection characteristics into a number
10620 + * (not including the timestamp) FIXME: this is a sucky hash function
10621 + */
10622 +static u32 make_hash( tcplag_hash_T *connection )
10623 +{
10624 +       register u32 r;
10625 +
10626 +       r = connection->low_ip;
10627 +       r += connection->high_ip;
10628 +       return( r );
10629 +}
10630 +
10631 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
10632 +{
10633 +       int x;
10634 +
10635 +       x = con1->low_ip - con2->low_ip; if( x ) return( x );
10636 +       x = con1->high_ip - con2->high_ip;
10637 +       return( x );
10638 +}
10639 +
10640 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
10641 +{
10642 +       int x;
10643 +
10644 +       DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
10645 +       x = ev1->expected_ACK - ev2->expected_ACK;
10646 +       if( x ) return( x );
10647 +       DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
10648 +       x = ev1->source_port - ev2->source_port;
10649 +       if( x ) return( x );
10650 +       DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
10651 +       x = ev1->dest_port - ev2->dest_port;
10652 +       return( x );
10653 +}
10654 +
10655 +/*
10656 + * Go to the hash table and either find an existing connection that
10657 + * matches correctly or inject a new connection into the table.
10658 + * Once the connection is OK, chain the event onto the linked list.
10659 + */
10660 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
10661 +{
10662 +       u32 h, i;
10663 +
10664 +       if( !event ) return; /* Just to be safe */
10665 +       if( !hashsize ) return;
10666 +       if( !hashtab ) return;
10667 +
10668 +       h = make_hash( connection );
10669 +       h %= hashsize;
10670 +
10671 +       DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
10672 +
10673 +       spin_lock_bh( &hash_lock );
10674 +       for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
10675 +       {
10676 +               tcplag_hash_T *co_new = 0;
10677 +/*
10678 + * Consider existing entry
10679 + */
10680 +               if( hashtab[ h ])
10681 +               {
10682 +                       if( compare_connections( hashtab[ h ], connection )) continue;
10683 +                       co_new = hashtab[ h ];
10684 +                       DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
10685 +                       goto add_link;
10686 +               }
10687 +/*
10688 + * Use empty slot for new entry
10689 + */
10690 +               if( !hashtab[ h ])
10691 +               {
10692 +                       co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
10693 +                       memset( co_new, 0, sizeof( tcplag_hash_T ));
10694 +                       co_new->low_ip = connection->low_ip;
10695 +                       co_new->high_ip = connection->high_ip;
10696 +                       co_new->stamp = event->stamp.tv_sec;
10697 +                       hashtab[ h ] = co_new;
10698 +                       DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
10699 + add_link:
10700 +                       {
10701 +                               tcplag_event_T *ev_new;
10702 +
10703 +                               ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
10704 +                               memcpy( ev_new, event, sizeof( tcplag_event_T ));
10705 +                               if( direction )
10706 +                               {
10707 +                                       ev_new->next = co_new->h_ACK_list;
10708 +                                       co_new->h_ACK_list = ev_new;
10709 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
10710 +                               }
10711 +                               else
10712 +                               {
10713 +                                       ev_new->next = co_new->l_ACK_list;
10714 +                                       co_new->l_ACK_list = ev_new;
10715 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
10716 +                               }
10717 +                       }
10718 +                       goto done;
10719 +               }
10720 +       }
10721 + done:
10722 +       spin_unlock_bh( &hash_lock );
10723 +}
10724 +
10725 +/*
10726 + * Search the hash table for a matching connection,
10727 + * if we can't find one of those then we are stuffed.
10728 + *
10729 + * Once a connection has been found, scan along the list for
10730 + * a matching SEQ number and if that is found then calculate
10731 + * the lag, update the counters and cut the chain at the
10732 + * point where the matching SEQ is found.
10733 + */
10734 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
10735 +{
10736 +       u32 h, i;
10737 +
10738 +       if( !event ) return( 0 );
10739 +       if( !hashsize ) return( 0 );
10740 +       if( !hashtab ) return( 0 );
10741 +       h = make_hash( connection );
10742 +       h %= hashsize;
10743 +
10744 +       DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
10745 +
10746 +       for( i = 0; i < hashsize; i++ )
10747 +       {
10748 +               tcplag_hash_T *found = 0;
10749 +
10750 +               if( !hashtab[ h ]) return( 0 );
10751 +
10752 +               spin_lock_bh( &hash_lock );
10753 +               if( hashtab[ h ])
10754 +               {
10755 +                       if( !compare_connections( hashtab[ h ], connection ))
10756 +                       {
10757 +                               tcplag_event_T *ev, **evroot;
10758 +                               timeval_T *tv;
10759 +                               u16 *cn;
10760 +
10761 +                               found = hashtab[ h ];
10762 +                               if( direction )
10763 +                               {
10764 +                                       evroot = &found->h_ACK_list;
10765 +                                       tv = &found->lag_l_SEQ_h_ACK;
10766 +                                       cn = &found->count_l_SEQ_h_ACK;
10767 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
10768 +                               }
10769 +                               else
10770 +                               {
10771 +                                       evroot = &found->l_ACK_list;
10772 +                                       tv = &found->lag_h_SEQ_l_ACK;
10773 +                                       cn = &found->count_h_SEQ_l_ACK;
10774 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
10775 +                               }
10776 +                               for( ev = *evroot; ev; ev = ev->next )
10777 +                               {
10778 +                                       if( !compare_events( ev, event ))
10779 +                                       {
10780 +/*
10781 + * Calculate the lag (in two parts) and add that to the collection
10782 + */
10783 +                                               event->stamp.tv_sec -= ev->stamp.tv_sec;
10784 +                                               event->stamp.tv_usec -= ev->stamp.tv_usec;
10785 +                                               if( event->stamp.tv_usec < 0 )
10786 +                                               {
10787 +                                                       event->stamp.tv_usec += 1000000;
10788 +                                                       event->stamp.tv_sec++;
10789 +                                               }
10790 +                                               if( event->stamp.tv_sec < 0 )
10791 +                                               {
10792 +                                                       DEBUGP( KERN_WARNING "Negative lag detected\n" );
10793 +                                               }
10794 +                                               else
10795 +                                               {
10796 +                                                       tv->tv_sec += event->stamp.tv_sec;
10797 +                                                       tv->tv_usec += event->stamp.tv_usec;
10798 +                                                       ++*cn;
10799 +                                                       DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
10800 +                                                                       " (accumulator is up to %lu.%06lu, %u events)\n",
10801 +                                                                       event->stamp.tv_sec,
10802 +                                                                       event->stamp.tv_usec,
10803 +                                                                       tv->tv_sec, tv->tv_usec, *cn );
10804 +                                               }
10805 +/*
10806 + * Truncate the linked list.
10807 + *
10808 + * Visit each event in the list and return the memory to the pool.
10809 + *
10810 + * If a host is making multiple connections to the same remote host
10811 + * then this truncation will result in some requests not being
10812 + * monitored. Statistically we will still get some reasonable number
10813 + * of measurements and multiple simultaneous connections between host
10814 + * pairs don't happen all that often.
10815 + */
10816 +                                               *evroot = 0;
10817 +                                               while( ev )
10818 +                                               {
10819 +                                                       tcplag_event_T *ev_next = ev->next;
10820 +                                                       DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
10821 +                                                       kfree( ev );
10822 +                                                       ev = ev_next;
10823 +                                               }
10824 +/*
10825 + * TODO: overflow limit for *cn, force premature output() if necessary
10826 + * (and drop this connection from the hash table)
10827 + */
10828 +                                               break;
10829 +                                       }
10830 +                               }
10831 +                               goto done;
10832 +                       }
10833 +               }
10834 + done:
10835 +               spin_unlock_bh( &hash_lock );
10836 +
10837 +               if( found ) return( 1 );
10838 +               if( ++h >= hashsize ) h = 0;
10839 +       }       
10840 +       return( 0 );
10841 +}
10842 +
10843 +/*
10844 + * Here is our target data:
10845 + *
10846 + * pskb      --  The packet itself (see linux/skbuff.h for breakdown)
10847 + *
10848 + * hooknum   --
10849 + *
10850 + * in        --  The device that this packet came in on
10851 + *               (depending on the chain this may or may not exist)
10852 + *
10853 + * out       --  The device that this packet is just about to go
10854 + *               out onto (again existance depends on the chain)
10855 + *
10856 + * targinfo  --  Our private data (handed through from iptables command util)
10857 + *
10858 + * userinfo  --  Some more data
10859 + *
10860 + */
10861 +
10862 +static unsigned int target( struct sk_buff **pskb,
10863 +                                                       unsigned int hooknum,
10864 +                                                       const struct net_device *in,
10865 +                                                       const struct net_device *out,
10866 +                                                       const void *targinfo,
10867 +                                                       void *userinfo )
10868 +{
10869 +       struct iphdr *iph = ( *pskb )->nh.iph;
10870 +       const struct ipt_tcplag *el = targinfo;
10871 +       tcplag_hash_T connection;
10872 +       tcplag_event_T event;
10873 +       int direction;
10874 +/*
10875 + * We know we are dealing with IP here
10876 + * Fill in all the obvious fields
10877 + */
10878 +       if( iph->saddr > iph->daddr )
10879 +       {
10880 +               direction = 0;
10881 +               connection.high_ip = iph->saddr;
10882 +               connection.low_ip = iph->daddr;
10883 +       }
10884 +       else
10885 +       {
10886 +               direction = 1;
10887 +               connection.low_ip = iph->saddr;
10888 +               connection.high_ip = iph->daddr;
10889 +       }
10890 +       do_gettimeofday( &event.stamp );
10891 +/*
10892 + * Do a bit of cleaning
10893 + */
10894 +       reaper( event.stamp.tv_sec, el->level, el->prefix );
10895 +
10896 +       DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
10897 +                       event.stamp.tv_sec,
10898 +                       event.stamp.tv_usec,
10899 +                       in ? in->name : "none", out ? out->name : "none" );
10900 +/*
10901 + * Now start looking at the details
10902 + *
10903 + * First step is to identify this packet to see if it is 
10904 + * the sort of packet that we are interested in.
10905 + * Don't hold any locks while we are doing this because often
10906 + * we will just let the packet go without any further consideration.
10907 + */
10908 +       switch( iph->protocol )
10909 +       {
10910 +               case IPPROTO_TCP:
10911 +               {
10912 +                       struct tcphdr *tcp;
10913 +
10914 +                       if( ntohs( iph->frag_off ) & IP_OFFSET )
10915 +                       {
10916 +                               DEBUGP( KERN_WARNING "ignoring fragment\n" );
10917 +                               break;
10918 +                       }
10919 +                       tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
10920 +                       event.source_port = ntohs( tcp->source );
10921 +                       event.dest_port = ntohs( tcp->dest );
10922 +/*
10923 + * Every packet should have a valid SEQ number so use this to
10924 + * generate an ACK number. This works along the formula:
10925 + * -- Start with the SEQ number
10926 + * -- For SYN or FIN add 1 to that number
10927 + * -- For data packet, add the data length to that number
10928 + */
10929 +
10930 +/*
10931 + * Data length requires a bit of fiddling around
10932 + */
10933 +                       {
10934 +                               unsigned int data_len;
10935 +                               if( tcp->syn || tcp->fin )
10936 +                               {
10937 +                                       data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
10938 +                               }
10939 +                               else
10940 +                               {
10941 +                                       data_len = ntohs( iph->tot_len );
10942 +                                       data_len -= 4 * iph->ihl;  /* Subtract away IP header & options */
10943 +                                       data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
10944 +                               }
10945 +                               
10946 +                               DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
10947 +
10948 +                               if( data_len ) /* Only track events that demand an ACK */
10949 +                               {
10950 +                                       event.expected_ACK = ntohl( tcp->seq ) + data_len;
10951 +                                       hash_insert( &connection, &event, direction );
10952 +                               }
10953 +                               else
10954 +                               {
10955 +                                       DEBUGP( "Don't bother to insert this, ACK not required\n" );
10956 +                               }
10957 +                       }
10958 +
10959 +                       if( tcp->ack )
10960 +                       {
10961 +/*
10962 + * Now we consider the matching of an existing event.
10963 + * Reverse the port numbers and change the ACK number to the actual ACK number
10964 + * Note that the direction is reversed because the reply will be going
10965 + * the opposite way to the request.
10966 + */
10967 +                               event.expected_ACK = ntohl( tcp->ack_seq );
10968 +                               event.dest_port = ntohs( tcp->source );
10969 +                               event.source_port = ntohs( tcp->dest );
10970 +                               request_complete( &connection, &event, !direction );
10971 +                       }
10972 +                       else
10973 +                       {
10974 +                               DEBUGP( "Don't bother to check this, ACK not valid\n" );
10975 +                       }
10976 +               }
10977 +       }
10978 +       return( IPT_CONTINUE );
10979 +}
10980 +
10981 +/*
10982 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
10983 + * return( 1 ) if the entry is suitable
10984 + *
10985 + * tablename     --  
10986 + *
10987 + * e             --  
10988 + *
10989 + * targinfo      --  Our private data block (handed to us from iptables plug-in)
10990 + *
10991 + * targinfosize  --  The size of our private data block
10992 + *
10993 + * hook_mask     --  
10994 + *
10995 + *
10996 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
10997 + * all possible flag combos make sense. All we check for is correct data size.
10998 + */
10999 +static int checkentry( const char *tablename,
11000 +                                          const struct ipt_entry *e,
11001 +                                          void *targinfo,
11002 +                                          unsigned int targinfosize,
11003 +                                          unsigned int hook_mask )
11004 +{
11005 +       const struct ipt_tcplag *el = targinfo;
11006 +
11007 +       if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
11008 +       {
11009 +               DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
11010 +                               IPT_ALIGN( sizeof( struct ipt_tcplag )));
11011 +               return( 0 );
11012 +       }
11013 +       if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
11014 +       return( 1 );
11015 +}
11016 +
11017 +static struct ipt_target reg =
11018 +{
11019 +       { 0, 0 },
11020 +       "TCPLAG",
11021 +       &target,
11022 +       &checkentry,
11023 +       0,
11024 +    THIS_MODULE
11025 +};
11026 +
11027 +static int __init init( void )
11028 +{
11029 +       if( ipt_register_target( &reg )) return( -EINVAL );
11030 +       hashsize = 123; /* should be configurable */
11031 +       hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
11032 +       memset( hashtab, 0, sizeof( void * ) * hashsize );
11033 +       return( 0 );
11034 +}
11035 +
11036 +/*
11037 + * This should not need locks (in theory)
11038 + * because it can only get punted after it is no longer
11039 + * chained into any of the netfilter lists.
11040 + */
11041 +static void __exit fini( void )
11042 +{
11043 +       int i;
11044 +
11045 +       ipt_unregister_target( &reg );
11046 +/*
11047 + * Put back kernel memory
11048 + */
11049 +       for( i = 0; i < hashsize; i++ )
11050 +       {
11051 +               tcplag_hash_T *p;
11052 +
11053 +               if(( p = hashtab[ i ]))
11054 +               {
11055 +                       tcplag_event_T *ev, *evn;
11056 +
11057 +                       hashtab[ i ] = 0;
11058 +                       for( ev = p->h_ACK_list; ev; ev = evn )
11059 +                       {
11060 +                               evn = ev->next;
11061 +                               kfree( ev );
11062 +                       }
11063 +                       for( ev = p->l_ACK_list; ev; ev = evn )
11064 +                       {
11065 +                               evn = ev->next;
11066 +                               kfree( ev );
11067 +                       }
11068 +                       kfree( p );
11069 +               }
11070 +       }
11071 +       kfree( hashtab );
11072 +}
11073 +
11074 +module_init(init);
11075 +module_exit(fini);
11076 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6/net/ipv4/netfilter/ipt_TRACE.c
11077 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TRACE.c      1970-01-01 01:00:00.000000000 +0100
11078 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TRACE.c  2004-05-18 12:38:32.000000000 +0200
11079 @@ -0,0 +1,64 @@
11080 +/* This is a module which is used for setting 
11081 + * the NFC_TRACE flag in the nfcache field of an skb. 
11082 + */
11083 +#include <linux/module.h>
11084 +#include <linux/skbuff.h>
11085 +
11086 +#include <linux/netfilter_ipv4/ip_tables.h>
11087 +
11088 +static unsigned int
11089 +target(struct sk_buff **pskb,
11090 +       const struct net_device *in,
11091 +       const struct net_device *out,
11092 +       unsigned int hooknum,
11093 +       const void *targinfo,
11094 +       void *userinfo)
11095 +{
11096 +       (*pskb)->nfcache |= NFC_TRACE;
11097 +       return IPT_CONTINUE;
11098 +}
11099 +
11100 +static int
11101 +checkentry(const char *tablename,
11102 +          const struct ipt_entry *e,
11103 +           void *targinfo,
11104 +           unsigned int targinfosize,
11105 +           unsigned int hook_mask)
11106 +{
11107 +       if (targinfosize != 0) {
11108 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
11109 +                      targinfosize);
11110 +               return 0;
11111 +       }
11112 +
11113 +       if (strcmp(tablename, "raw") != 0) {
11114 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
11115 +               return 0;
11116 +       }
11117 +
11118 +       return 1;
11119 +}
11120 +
11121 +static struct ipt_target ipt_trace_reg = { 
11122 +       .name = "TRACE", 
11123 +       .target = target, 
11124 +       .checkentry = checkentry, 
11125 +       .me = THIS_MODULE
11126 +};
11127 +
11128 +static int __init init(void)
11129 +{
11130 +       if (ipt_register_target(&ipt_trace_reg))
11131 +               return -EINVAL;
11132 +
11133 +       return 0;
11134 +}
11135 +
11136 +static void __exit fini(void)
11137 +{
11138 +       ipt_unregister_target(&ipt_trace_reg);
11139 +}
11140 +
11141 +module_init(init);
11142 +module_exit(fini);
11143 +MODULE_LICENSE("GPL");
11144 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.6/net/ipv4/netfilter/ipt_TTL.c
11145 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_TTL.c        1970-01-01 01:00:00.000000000 +0100
11146 +++ linux-2.6.6/net/ipv4/netfilter/ipt_TTL.c    2004-05-18 12:36:09.000000000 +0200
11147 @@ -0,0 +1,120 @@
11148 +/* TTL modification target for IP tables
11149 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
11150 + *
11151 + * Version: $Revision$
11152 + *
11153 + * This software is distributed under the terms of GNU GPL
11154 + */
11155 +
11156 +#include <linux/module.h>
11157 +#include <linux/skbuff.h>
11158 +#include <linux/ip.h>
11159 +#include <net/checksum.h>
11160 +
11161 +#include <linux/netfilter_ipv4/ip_tables.h>
11162 +#include <linux/netfilter_ipv4/ipt_TTL.h>
11163 +
11164 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
11165 +MODULE_DESCRIPTION("IP tables TTL modification module");
11166 +MODULE_LICENSE("GPL");
11167 +
11168 +static unsigned int 
11169 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 
11170 +               const struct net_device *out, unsigned int hooknum, 
11171 +               const void *targinfo, void *userinfo)
11172 +{
11173 +       struct iphdr *iph;
11174 +       const struct ipt_TTL_info *info = targinfo;
11175 +       u_int16_t diffs[2];
11176 +       int new_ttl;
11177 +
11178 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
11179 +               return NF_DROP;
11180 +
11181 +       iph = (*pskb)->nh.iph;
11182 +                        
11183 +       switch (info->mode) {
11184 +               case IPT_TTL_SET:
11185 +                       new_ttl = info->ttl;
11186 +                       break;
11187 +               case IPT_TTL_INC:
11188 +                       new_ttl = iph->ttl + info->ttl;
11189 +                       if (new_ttl > 255)
11190 +                               new_ttl = 255;
11191 +                       break;
11192 +               case IPT_TTL_DEC:
11193 +                       new_ttl = iph->ttl + info->ttl;
11194 +                       if (new_ttl < 0)
11195 +                               new_ttl = 0;
11196 +                       break;
11197 +               default:
11198 +                       new_ttl = iph->ttl;
11199 +                       break;
11200 +       }
11201 +
11202 +       if (new_ttl != iph->ttl) {
11203 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
11204 +               iph->ttl = new_ttl;
11205 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
11206 +               iph->check = csum_fold(csum_partial((char *)diffs,
11207 +                                                   sizeof(diffs),
11208 +                                                   iph->check^0xFFFF));
11209 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
11210 +       }
11211 +
11212 +       return IPT_CONTINUE;
11213 +}
11214 +
11215 +static int ipt_ttl_checkentry(const char *tablename,
11216 +               const struct ipt_entry *e,
11217 +               void *targinfo,
11218 +               unsigned int targinfosize,
11219 +               unsigned int hook_mask)
11220 +{
11221 +       struct ipt_TTL_info *info = targinfo;
11222 +
11223 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
11224 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
11225 +                               targinfosize,
11226 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
11227 +               return 0;       
11228 +       }       
11229 +
11230 +       if (strcmp(tablename, "mangle")) {
11231 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
11232 +               return 0;
11233 +       }
11234 +
11235 +       if (info->mode > IPT_TTL_MAXMODE) {
11236 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
11237 +                       info->mode);
11238 +               return 0;
11239 +       }
11240 +
11241 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
11242 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
11243 +               return 0;
11244 +       }
11245 +       
11246 +       return 1;
11247 +}
11248 +
11249 +static struct ipt_target ipt_TTL = { 
11250 +       .name = "TTL",
11251 +       .target = ipt_ttl_target, 
11252 +       .checkentry = ipt_ttl_checkentry, 
11253 +       .me = THIS_MODULE 
11254 +};
11255 +
11256 +static int __init init(void)
11257 +{
11258 +       return ipt_register_target(&ipt_TTL);
11259 +}
11260 +
11261 +static void __exit fini(void)
11262 +{
11263 +       ipt_unregister_target(&ipt_TTL);
11264 +}
11265 +
11266 +module_init(init);
11267 +module_exit(fini);
11268 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6/net/ipv4/netfilter/ipt_XOR.c
11269 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_XOR.c        1970-01-01 01:00:00.000000000 +0100
11270 +++ linux-2.6.6/net/ipv4/netfilter/ipt_XOR.c    2004-05-18 12:38:34.000000000 +0200
11271 @@ -0,0 +1,117 @@
11272 +/* XOR target for IP tables
11273 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
11274 + * Based on ipt_TTL.c
11275 + *
11276 + * Version 1.0
11277 + *
11278 + * This software is distributed under the terms of GNU GPL
11279 + */
11280 +
11281 +#include <linux/module.h>
11282 +#include <linux/skbuff.h>
11283 +#include <linux/ip.h>
11284 +#include <linux/tcp.h>
11285 +#include <linux/udp.h>
11286 +
11287 +#include <linux/netfilter_ipv4/ip_tables.h>
11288 +#include <linux/netfilter_ipv4/ipt_XOR.h>
11289 +
11290 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
11291 +MODULE_DESCRIPTION("IP tables XOR module");
11292 +MODULE_LICENSE("GPL");
11293 +
11294 +static unsigned int 
11295 +ipt_xor_target(struct sk_buff **pskb, 
11296 +               const struct net_device *in, const struct net_device *out, 
11297 +               unsigned int hooknum, const void *targinfo, void *userinfo)
11298 +{
11299 +       struct ipt_XOR_info *info = (void *) targinfo;
11300 +       struct iphdr *iph;
11301 +       struct tcphdr *tcph;
11302 +       struct udphdr *udph;
11303 +       int i, j, k;
11304 +
11305 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
11306 +               return NF_DROP;
11307 +
11308 +       iph = (*pskb)->nh.iph;
11309 +  
11310 +       if (iph->protocol == IPPROTO_TCP) {
11311 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
11312 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
11313 +                       for (k=0; k<=info->block_size; k++) {
11314 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
11315 +                                               info->key[j];
11316 +                               i++;
11317 +                       }
11318 +                       j++;
11319 +                       if (info->key[j] == 0x00)
11320 +                               j = 0;
11321 +               }
11322 +       } else if (iph->protocol == IPPROTO_UDP) {
11323 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
11324 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
11325 +                       for (k=0; k<=info->block_size; k++) {
11326 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
11327 +                                               info->key[j];
11328 +                               i++;
11329 +                       }
11330 +                       j++;
11331 +                       if (info->key[j] == 0x00)
11332 +                               j = 0;
11333 +               }
11334 +       }
11335 +  
11336 +       return IPT_CONTINUE;
11337 +}
11338 +
11339 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
11340 +               void *targinfo, unsigned int targinfosize, 
11341 +               unsigned int hook_mask)
11342 +{
11343 +       struct ipt_XOR_info *info = targinfo;
11344 +
11345 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
11346 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
11347 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
11348 +               return 0;
11349 +       }       
11350 +
11351 +       if (strcmp(tablename, "mangle")) {
11352 +               printk(KERN_WARNING "XOR: can only be called from"
11353 +                               "\"mangle\" table, not \"%s\"\n", tablename);
11354 +               return 0; 
11355 +       }
11356 +
11357 +       if (!strcmp(info->key, "")) {
11358 +               printk(KERN_WARNING "XOR: You must specify a key");
11359 +               return 0;
11360 +       }
11361 +
11362 +       if (info->block_size == 0) {
11363 +               printk(KERN_WARNING "XOR: You must specify a block-size");
11364 +               return 0;
11365 +       }
11366 +
11367 +       return 1;
11368 +}
11369 +
11370 +static struct ipt_target ipt_XOR = { 
11371 +       .name = "XOR",
11372 +       .target = ipt_xor_target, 
11373 +       .checkentry = ipt_xor_checkentry,
11374 +       .me = THIS_MODULE,
11375 +};
11376 +
11377 +static int __init init(void)
11378 +{
11379 +       return ipt_register_target(&ipt_XOR);
11380 +}
11381 +
11382 +static void __exit fini(void)
11383 +{
11384 +       ipt_unregister_target(&ipt_XOR);
11385 +}
11386 +
11387 +module_init(init);
11388 +module_exit(fini);
11389 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6/net/ipv4/netfilter/ipt_addrtype.c
11390 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_addrtype.c   1970-01-01 01:00:00.000000000 +0100
11391 +++ linux-2.6.6/net/ipv4/netfilter/ipt_addrtype.c       2004-05-18 12:38:44.000000000 +0200
11392 @@ -0,0 +1,68 @@
11393 +/*
11394 + *  iptables module to match inet_addr_type() of an ip.
11395 + */
11396 +
11397 +#include <linux/module.h>
11398 +#include <linux/skbuff.h>
11399 +#include <linux/netdevice.h>
11400 +#include <net/route.h>
11401 +
11402 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
11403 +#include <linux/netfilter_ipv4/ip_tables.h>
11404 +
11405 +MODULE_LICENSE("GPL");
11406 +
11407 +static inline int match_type(u_int32_t addr, u_int16_t mask)
11408 +{
11409 +       return !!(mask & (1 << inet_addr_type(addr)));
11410 +}
11411 +
11412 +static int match(const struct sk_buff *skb, const struct net_device *in,
11413 +                const struct net_device *out, const void *matchinfo,
11414 +                int offset, int *hotdrop)
11415 +{
11416 +       const struct ipt_addrtype_info *info = matchinfo;
11417 +       const struct iphdr *iph = skb->nh.iph;
11418 +       int ret = 1;
11419 +
11420 +       if (info->source)
11421 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
11422 +       if (info->dest)
11423 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
11424 +       
11425 +       return ret;
11426 +}
11427 +
11428 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
11429 +                     void *matchinfo, unsigned int matchsize,
11430 +                     unsigned int hook_mask)
11431 +{
11432 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
11433 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
11434 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
11435 +               return 0;
11436 +       }
11437 +
11438 +       return 1;
11439 +}
11440 +
11441 +static struct ipt_match addrtype_match = { 
11442 +       .name = "addrtype",
11443 +       .match = match,
11444 +       .checkentry = checkentry,
11445 +       .me = THIS_MODULE
11446 +};
11447 +
11448 +static int __init init(void)
11449 +{
11450 +       return ipt_register_match(&addrtype_match);
11451 +}
11452 +
11453 +static void __exit fini(void)
11454 +{
11455 +       ipt_unregister_match(&addrtype_match);
11456 +
11457 +}
11458 +
11459 +module_init(init);
11460 +module_exit(fini);
11461 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.6/net/ipv4/netfilter/ipt_connlimit.c
11462 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_connlimit.c  1970-01-01 01:00:00.000000000 +0100
11463 +++ linux-2.6.6/net/ipv4/netfilter/ipt_connlimit.c      2004-05-18 12:36:13.000000000 +0200
11464 @@ -0,0 +1,230 @@
11465 +/*
11466 + * netfilter module to limit the number of parallel tcp
11467 + * connections per IP address.
11468 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
11469 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
11470 + *             only ignore TIME_WAIT or gone connections
11471 + *
11472 + * based on ...
11473 + *
11474 + * Kernel module to match connection tracking information.
11475 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
11476 + */
11477 +#include <linux/module.h>
11478 +#include <linux/skbuff.h>
11479 +#include <linux/list.h>
11480 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11481 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
11482 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
11483 +#include <linux/netfilter_ipv4/ip_tables.h>
11484 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
11485 +
11486 +#define DEBUG 0
11487 +
11488 +MODULE_LICENSE("GPL");
11489 +
11490 +/* we'll save the tuples of all connections we care about */
11491 +struct ipt_connlimit_conn
11492 +{
11493 +        struct list_head list;
11494 +       struct ip_conntrack_tuple tuple;
11495 +};
11496 +
11497 +struct ipt_connlimit_data {
11498 +       spinlock_t lock;
11499 +       struct list_head iphash[256];
11500 +};
11501 +
11502 +static int ipt_iphash(u_int32_t addr)
11503 +{
11504 +       int hash;
11505 +
11506 +       hash  =  addr        & 0xff;
11507 +       hash ^= (addr >>  8) & 0xff;
11508 +       hash ^= (addr >> 16) & 0xff;
11509 +       hash ^= (addr >> 24) & 0xff;
11510 +       return hash;
11511 +}
11512 +
11513 +static int count_them(struct ipt_connlimit_data *data,
11514 +                     u_int32_t addr, u_int32_t mask,
11515 +                     struct ip_conntrack *ct)
11516 +{
11517 +#if DEBUG
11518 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
11519 +                                    "fin_wait", "time_wait", "close", "close_wait",
11520 +                                    "last_ack", "listen" };
11521 +#endif
11522 +       int addit = 1, matches = 0;
11523 +       struct ip_conntrack_tuple tuple;
11524 +       struct ip_conntrack_tuple_hash *found;
11525 +       struct ipt_connlimit_conn *conn;
11526 +       struct list_head *hash,*lh;
11527 +
11528 +       spin_lock(&data->lock);
11529 +       tuple = ct->tuplehash[0].tuple;
11530 +       hash = &data->iphash[ipt_iphash(addr & mask)];
11531 +
11532 +       /* check the saved connections */
11533 +       for (lh = hash->next; lh != hash; lh = lh->next) {
11534 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
11535 +               found = ip_conntrack_find_get(&conn->tuple,ct);
11536 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
11537 +                   found != NULL &&
11538 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
11539 +                       /* Just to be sure we have it only once in the list.
11540 +                          We should'nt see tuples twice unless someone hooks this
11541 +                          into a table without "-p tcp --syn" */
11542 +                       addit = 0;
11543 +               }
11544 +#if DEBUG
11545 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
11546 +                      ipt_iphash(addr & mask),
11547 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
11548 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
11549 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
11550 +#endif
11551 +               if (NULL == found) {
11552 +                       /* this one is gone */
11553 +                       lh = lh->prev;
11554 +                       list_del(lh->next);
11555 +                       kfree(conn);
11556 +                       continue;
11557 +               }
11558 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
11559 +                       /* we don't care about connections which are
11560 +                          closed already -> ditch it */
11561 +                       lh = lh->prev;
11562 +                       list_del(lh->next);
11563 +                       kfree(conn);
11564 +                       nf_conntrack_put(&found->ctrack->infos[0]);
11565 +                       continue;
11566 +               }
11567 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
11568 +                       /* same source IP address -> be counted! */
11569 +                       matches++;
11570 +               }
11571 +               nf_conntrack_put(&found->ctrack->infos[0]);
11572 +       }
11573 +       if (addit) {
11574 +               /* save the new connection in our list */
11575 +#if DEBUG
11576 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
11577 +                      ipt_iphash(addr & mask),
11578 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
11579 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
11580 +#endif
11581 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
11582 +               if (NULL == conn)
11583 +                       return -1;
11584 +               memset(conn,0,sizeof(*conn));
11585 +               INIT_LIST_HEAD(&conn->list);
11586 +               conn->tuple = tuple;
11587 +               list_add(&conn->list,hash);
11588 +               matches++;
11589 +       }
11590 +       spin_unlock(&data->lock);
11591 +       return matches;
11592 +}
11593 +
11594 +static int
11595 +match(const struct sk_buff *skb,
11596 +      const struct net_device *in,
11597 +      const struct net_device *out,
11598 +      const void *matchinfo,
11599 +      int offset,
11600 +      int *hotdrop)
11601 +{
11602 +       const struct ipt_connlimit_info *info = matchinfo;
11603 +       int connections, match;
11604 +       struct ip_conntrack *ct;
11605 +       enum ip_conntrack_info ctinfo;
11606 +
11607 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11608 +       if (NULL == ct) {
11609 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
11610 +               *hotdrop = 1;
11611 +               return 0;
11612 +       }
11613 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
11614 +       if (-1 == connections) {
11615 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
11616 +               *hotdrop = 1; /* let's free some memory :-) */
11617 +               return 0;
11618 +       }
11619 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
11620 +#if DEBUG
11621 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
11622 +              "connections=%d limit=%d match=%s\n",
11623 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
11624 +              connections, info->limit, match ? "yes" : "no");
11625 +#endif
11626 +
11627 +       return match;
11628 +}
11629 +
11630 +static int check(const char *tablename,
11631 +                const struct ipt_ip *ip,
11632 +                void *matchinfo,
11633 +                unsigned int matchsize,
11634 +                unsigned int hook_mask)
11635 +{
11636 +       struct ipt_connlimit_info *info = matchinfo;
11637 +       int i;
11638 +
11639 +       /* verify size */
11640 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
11641 +               return 0;
11642 +
11643 +       /* refuse anything but tcp */
11644 +       if (ip->proto != IPPROTO_TCP)
11645 +               return 0;
11646 +
11647 +       /* init private data */
11648 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
11649 +       spin_lock_init(&(info->data->lock));
11650 +       for (i = 0; i < 256; i++)
11651 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
11652 +       
11653 +       return 1;
11654 +}
11655 +
11656 +static void destroy(void *matchinfo, unsigned int matchinfosize)
11657 +{
11658 +       struct ipt_connlimit_info *info = matchinfo;
11659 +       struct ipt_connlimit_conn *conn;
11660 +       struct list_head *hash;
11661 +       int i;
11662 +
11663 +       /* cleanup */
11664 +       for (i = 0; i < 256; i++) {
11665 +               hash = &(info->data->iphash[i]);
11666 +               while (hash != hash->next) {
11667 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
11668 +                       list_del(hash->next);
11669 +                       kfree(conn);
11670 +               }
11671 +       }
11672 +       kfree(info->data);
11673 +}
11674 +
11675 +static struct ipt_match connlimit_match = { 
11676 +       .name = "connlimit",
11677 +       .match = &match,
11678 +       .checkentry = &check,
11679 +       .destroy = &destroy,
11680 +       .me = THIS_MODULE
11681 +};
11682 +
11683 +static int __init init(void)
11684 +{
11685 +       return ipt_register_match(&connlimit_match);
11686 +}
11687 +
11688 +static void __exit fini(void)
11689 +{
11690 +       ipt_unregister_match(&connlimit_match);
11691 +}
11692 +
11693 +module_init(init);
11694 +module_exit(fini);
11695 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6/net/ipv4/netfilter/ipt_connmark.c
11696 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_connmark.c   1970-01-01 01:00:00.000000000 +0100
11697 +++ linux-2.6.6/net/ipv4/netfilter/ipt_connmark.c       2004-05-18 12:38:02.000000000 +0200
11698 @@ -0,0 +1,81 @@
11699 +/* This kernel module matches connection mark values set by the
11700 + * CONNMARK target
11701 + *
11702 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
11703 + * by Henrik Nordstrom <hno@marasystems.com>
11704 + *
11705 + * This program is free software; you can redistribute it and/or modify
11706 + * it under the terms of the GNU General Public License as published by
11707 + * the Free Software Foundation; either version 2 of the License, or
11708 + * (at your option) any later version.
11709 + *
11710 + * This program is distributed in the hope that it will be useful,
11711 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11712 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11713 + * GNU General Public License for more details.
11714 + *
11715 + * You should have received a copy of the GNU General Public License
11716 + * along with this program; if not, write to the Free Software
11717 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
11718 + */
11719 +
11720 +#include <linux/module.h>
11721 +#include <linux/skbuff.h>
11722 +
11723 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
11724 +MODULE_DESCRIPTION("IP tables connmark match module");
11725 +MODULE_LICENSE("GPL");
11726 +
11727 +#include <linux/netfilter_ipv4/ip_tables.h>
11728 +#include <linux/netfilter_ipv4/ipt_connmark.h>
11729 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11730 +
11731 +static int
11732 +match(const struct sk_buff *skb,
11733 +      const struct net_device *in,
11734 +      const struct net_device *out,
11735 +      const void *matchinfo,
11736 +      int offset,
11737 +      int *hotdrop)
11738 +{
11739 +       const struct ipt_connmark_info *info = matchinfo;
11740 +       enum ip_conntrack_info ctinfo;
11741 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11742 +       if (!ct)
11743 +               return 0;
11744 +
11745 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
11746 +}
11747 +
11748 +static int
11749 +checkentry(const char *tablename,
11750 +          const struct ipt_ip *ip,
11751 +          void *matchinfo,
11752 +          unsigned int matchsize,
11753 +          unsigned int hook_mask)
11754 +{
11755 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
11756 +               return 0;
11757 +
11758 +       return 1;
11759 +}
11760 +
11761 +static struct ipt_match connmark_match = {
11762 +       .name = "connmark",
11763 +       .match = &match,
11764 +       .checkentry = &checkentry,
11765 +       .me = THIS_MODULE
11766 +};
11767 +
11768 +static int __init init(void)
11769 +{
11770 +       return ipt_register_match(&connmark_match);
11771 +}
11772 +
11773 +static void __exit fini(void)
11774 +{
11775 +       ipt_unregister_match(&connmark_match);
11776 +}
11777 +
11778 +module_init(init);
11779 +module_exit(fini);
11780 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.6/net/ipv4/netfilter/ipt_dstlimit.c
11781 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_dstlimit.c   1970-01-01 01:00:00.000000000 +0100
11782 +++ linux-2.6.6/net/ipv4/netfilter/ipt_dstlimit.c       2004-05-18 12:36:19.000000000 +0200
11783 @@ -0,0 +1,690 @@
11784 +/* iptables match extension to limit the number of packets per second
11785 + * seperately for each destination.
11786 + *
11787 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
11788 + *
11789 + * $Id$
11790 + *
11791 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
11792 + *
11793 + * based on ipt_limit.c by:
11794 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
11795 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
11796 + * Rusty Russell       <rusty@rustcorp.com.au>
11797 + *
11798 + * The general idea is to create a hash table for every dstip and have a
11799 + * seperate limit counter per tuple.  This way you can do something like 'limit
11800 + * the number of syn packets for each of my internal addresses.
11801 + *
11802 + * Ideally this would just be implemented as a general 'hash' match, which would
11803 + * allow us to attach any iptables target to it's hash buckets.  But this is
11804 + * not possible in the current iptables architecture.  As always, pkttables for
11805 + * 2.7.x will help ;)
11806 + */
11807 +#include <linux/module.h>
11808 +#include <linux/skbuff.h>
11809 +#include <linux/spinlock.h>
11810 +#include <linux/random.h>
11811 +#include <linux/jhash.h>
11812 +#include <linux/slab.h>
11813 +#include <linux/vmalloc.h>
11814 +#include <linux/tcp.h>
11815 +#include <linux/udp.h>
11816 +#include <linux/proc_fs.h>
11817 +#include <linux/seq_file.h>
11818 +
11819 +#define ASSERT_READ_LOCK(x) 
11820 +#define ASSERT_WRITE_LOCK(x) 
11821 +#include <linux/netfilter_ipv4/lockhelp.h>
11822 +#include <linux/netfilter_ipv4/listhelp.h>
11823 +
11824 +#include <linux/netfilter_ipv4/ip_tables.h>
11825 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
11826 +
11827 +/* FIXME: this is just for IP_NF_ASSERRT */
11828 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11829 +
11830 +#define MS2JIFFIES(x) ((x*HZ)/1000)
11831 +
11832 +MODULE_LICENSE("GPL");
11833 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
11834 +MODULE_DESCRIPTION("iptables match for limiting per destination");
11835 +
11836 +/* need to declare this at the top */
11837 +static struct proc_dir_entry *dstlimit_procdir;
11838 +static struct file_operations dl_file_ops;
11839 +
11840 +/* hash table crap */
11841 +
11842 +struct dsthash_dst {
11843 +       u_int32_t src_ip;
11844 +       u_int32_t dst_ip;
11845 +       u_int16_t port;
11846 +};
11847 +
11848 +struct dsthash_ent {
11849 +       /* static / read-only parts in the beginning */
11850 +       struct list_head list;
11851 +       struct dsthash_dst dst;
11852 +
11853 +       /* modified structure members in the end */
11854 +       unsigned long expires;          /* precalculated expiry time */
11855 +       struct {
11856 +               unsigned long prev;     /* last modification */
11857 +               u_int32_t credit;
11858 +               u_int32_t credit_cap, cost;
11859 +       } rateinfo;
11860 +};
11861 +
11862 +struct ipt_dstlimit_htable {
11863 +       struct list_head list;          /* global list of all htables */
11864 +       atomic_t use;
11865 +
11866 +       struct dstlimit_cfg cfg;        /* config */
11867 +
11868 +       /* used internally */
11869 +       spinlock_t lock;                /* lock for list_head */
11870 +       u_int32_t rnd;                  /* random seed for hash */
11871 +       struct timer_list timer;        /* timer for gc */
11872 +       atomic_t count;                 /* number entries in table */
11873 +
11874 +       /* seq_file stuff */
11875 +       struct proc_dir_entry *pde;
11876 +
11877 +       struct list_head hash[0];       /* hashtable itself */
11878 +};
11879 +
11880 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
11881 +static LIST_HEAD(dstlimit_htables);
11882 +static kmem_cache_t *dstlimit_cachep;
11883 +
11884 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
11885 +{
11886 +       return (ent->dst.dst_ip == b->dst_ip 
11887 +               && ent->dst.port == b->port
11888 +               && ent->dst.src_ip == b->src_ip);
11889 +}
11890 +
11891 +static inline u_int32_t
11892 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
11893 +{
11894 +       return (jhash_3words(dst->dst_ip, dst->port, 
11895 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
11896 +}
11897 +
11898 +static inline struct dsthash_ent *
11899 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11900 +{
11901 +       struct dsthash_ent *ent;
11902 +       u_int32_t hash = hash_dst(ht, dst);
11903 +       MUST_BE_LOCKED(&ht->lock);
11904 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
11905 +       return ent;
11906 +}
11907 +
11908 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
11909 +static struct dsthash_ent *
11910 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11911 +{
11912 +       struct dsthash_ent *ent;
11913 +
11914 +       /* initialize hash with random val at the time we allocate
11915 +        * the first hashtable entry */
11916 +       if (!ht->rnd)
11917 +               get_random_bytes(&ht->rnd, 4);
11918 +
11919 +       if (ht->cfg.max &&
11920 +           atomic_read(&ht->count) >= ht->cfg.max) {
11921 +               /* FIXME: do something. question is what.. */
11922 +               if (net_ratelimit())
11923 +                       printk(KERN_WARNING 
11924 +                               "ipt_dstlimit: max count of %u reached\n", 
11925 +                               ht->cfg.max);
11926 +               return NULL;
11927 +       }
11928 +
11929 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
11930 +       if (!ent) {
11931 +               if (net_ratelimit())
11932 +                       printk(KERN_ERR 
11933 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
11934 +               return NULL;
11935 +       }
11936 +
11937 +       atomic_inc(&ht->count);
11938 +
11939 +       ent->dst.dst_ip = dst->dst_ip;
11940 +       ent->dst.port = dst->port;
11941 +       ent->dst.src_ip = dst->src_ip;
11942 +
11943 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
11944 +
11945 +       return ent;
11946 +}
11947 +
11948 +static inline void 
11949 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
11950 +{
11951 +       MUST_BE_LOCKED(&ht->lock);
11952 +
11953 +       list_del(&ent->list);
11954 +       kmem_cache_free(dstlimit_cachep, ent);
11955 +       atomic_dec(&ht->count);
11956 +}
11957 +static void htable_gc(unsigned long htlong);
11958 +
11959 +static int htable_create(struct ipt_dstlimit_info *minfo)
11960 +{
11961 +       int i;
11962 +       unsigned int size;
11963 +       struct ipt_dstlimit_htable *hinfo;
11964 +
11965 +       if (minfo->cfg.size)
11966 +               size = minfo->cfg.size;
11967 +       else {
11968 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
11969 +                        / sizeof(struct list_head));
11970 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
11971 +                       size = 8192;
11972 +               if (size < 16)
11973 +                       size = 16;
11974 +       }
11975 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
11976 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
11977 +                       + (sizeof(struct list_head) * size));
11978 +       if (!hinfo) {
11979 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
11980 +               return -1;
11981 +       }
11982 +       minfo->hinfo = hinfo;
11983 +
11984 +       /* copy match config into hashtable config */
11985 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
11986 +       hinfo->cfg.size = size;
11987 +       if (!hinfo->cfg.max)
11988 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
11989 +       else if (hinfo->cfg.max < hinfo->cfg.size)
11990 +               hinfo->cfg.max = hinfo->cfg.size;
11991 +
11992 +       for (i = 0; i < hinfo->cfg.size; i++)
11993 +               INIT_LIST_HEAD(&hinfo->hash[i]);
11994 +
11995 +       atomic_set(&hinfo->count, 0);
11996 +       atomic_set(&hinfo->use, 1);
11997 +       hinfo->rnd = 0;
11998 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
11999 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
12000 +       if (!hinfo->pde) {
12001 +               vfree(hinfo);
12002 +               return -1;
12003 +       }
12004 +       hinfo->pde->proc_fops = &dl_file_ops;
12005 +       hinfo->pde->data = hinfo;
12006 +
12007 +       init_timer(&hinfo->timer);
12008 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
12009 +       hinfo->timer.data = (unsigned long )hinfo;
12010 +       hinfo->timer.function = htable_gc;
12011 +       add_timer(&hinfo->timer);
12012 +
12013 +       WRITE_LOCK(&dstlimit_lock);
12014 +       list_add(&hinfo->list, &dstlimit_htables);
12015 +       WRITE_UNLOCK(&dstlimit_lock);
12016 +
12017 +       return 0;
12018 +}
12019 +
12020 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12021 +{
12022 +       return 1;
12023 +}
12024 +
12025 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12026 +{
12027 +       return (jiffies >= he->expires);
12028 +}
12029 +
12030 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
12031 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
12032 +                                             struct dsthash_ent *he))
12033 +{
12034 +       int i;
12035 +
12036 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
12037 +
12038 +       /* lock hash table and iterate over it */
12039 +       LOCK_BH(&ht->lock);
12040 +       for (i = 0; i < ht->cfg.size; i++) {
12041 +               struct dsthash_ent *dh, *n;
12042 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
12043 +                       if ((*select)(ht, dh))
12044 +                               __dsthash_free(ht, dh);
12045 +               }
12046 +       }
12047 +       UNLOCK_BH(&ht->lock);
12048 +}
12049 +
12050 +/* hash table garbage collector, run by timer */
12051 +static void htable_gc(unsigned long htlong)
12052 +{
12053 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
12054 +
12055 +       htable_selective_cleanup(ht, select_gc);
12056 +
12057 +       /* re-add the timer accordingly */
12058 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
12059 +       add_timer(&ht->timer);
12060 +}
12061 +
12062 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
12063 +{
12064 +       /* remove timer, if it is pending */
12065 +       if (timer_pending(&hinfo->timer))
12066 +               del_timer(&hinfo->timer);
12067 +
12068 +       /* remove proc entry */
12069 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
12070 +
12071 +       htable_selective_cleanup(hinfo, select_all);
12072 +       vfree(hinfo);
12073 +}
12074 +
12075 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
12076 +{
12077 +       struct ipt_dstlimit_htable *hinfo;
12078 +
12079 +       READ_LOCK(&dstlimit_lock);
12080 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
12081 +               if (!strcmp(name, hinfo->pde->name)) {
12082 +                       atomic_inc(&hinfo->use);
12083 +                       READ_UNLOCK(&dstlimit_lock);
12084 +                       return hinfo;
12085 +               }
12086 +       }
12087 +       READ_UNLOCK(&dstlimit_lock);
12088 +
12089 +       return NULL;
12090 +}
12091 +
12092 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
12093 +{
12094 +       if (atomic_dec_and_test(&hinfo->use)) {
12095 +               WRITE_LOCK(&dstlimit_lock);
12096 +               list_del(&hinfo->list);
12097 +               WRITE_UNLOCK(&dstlimit_lock);
12098 +               htable_destroy(hinfo);
12099 +       }
12100 +}
12101 +
12102 +
12103 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
12104 + * see net/sched/sch_tbf.c in the linux source tree
12105 + */
12106 +
12107 +/* Rusty: This is my (non-mathematically-inclined) understanding of
12108 +   this algorithm.  The `average rate' in jiffies becomes your initial
12109 +   amount of credit `credit' and the most credit you can ever have
12110 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
12111 +   test, `cost'.
12112 +
12113 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
12114 +   If you get credit balance more than this, the extra credit is
12115 +   discarded.  Every time the match passes, you lose `cost' credits;
12116 +   if you don't have that many, the test fails.
12117 +
12118 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
12119 +
12120 +   To get the maximum range, we multiply by this factor (ie. you get N
12121 +   credits per jiffy).  We want to allow a rate as low as 1 per day
12122 +   (slowest userspace tool allows), which means
12123 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
12124 +*/
12125 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
12126 +
12127 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
12128 + * us the power of 2 below the theoretical max, so GCC simply does a
12129 + * shift. */
12130 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
12131 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
12132 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
12133 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
12134 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
12135 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
12136 +
12137 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
12138 +
12139 +/* Precision saver. */
12140 +static inline u_int32_t
12141 +user2credits(u_int32_t user)
12142 +{
12143 +       /* If multiplying would overflow... */
12144 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
12145 +               /* Divide first. */
12146 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
12147 +
12148 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
12149 +}
12150 +
12151 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
12152 +{
12153 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
12154 +                                       * CREDITS_PER_JIFFY;
12155 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
12156 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
12157 +}
12158 +
12159 +static int
12160 +dstlimit_match(const struct sk_buff *skb,
12161 +               const struct net_device *in,
12162 +               const struct net_device *out,
12163 +               const void *matchinfo,
12164 +               int offset,
12165 +               int *hotdrop)
12166 +{
12167 +       struct ipt_dstlimit_info *r = 
12168 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
12169 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
12170 +       unsigned long now = jiffies;
12171 +       struct dsthash_ent *dh;
12172 +       struct dsthash_dst dst;
12173 +
12174 +       memset(&dst, 0, sizeof(dst));
12175 +
12176 +       /* dest ip is always in hash */
12177 +       dst.dst_ip = skb->nh.iph->daddr;
12178 +
12179 +       /* source ip only if respective hashmode, otherwise set to
12180 +        * zero */
12181 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
12182 +               dst.src_ip = skb->nh.iph->saddr;
12183 +
12184 +       /* dest port only if respective mode */
12185 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
12186 +               u16 ports[2];
12187 +
12188 +               /* Must not be a fragment. */
12189 +               if (offset)
12190 +                       return 0;
12191 +
12192 +               /* Must be big enough to read ports (both UDP and TCP have
12193 +                  them at the start). */
12194 +               if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12195 +                       /* We've been asked to examine this packet, and we
12196 +                          can't.  Hence, no choice but to drop. */
12197 +                       *hotdrop = 1;
12198 +                       return 0;
12199 +               }
12200 +
12201 +               switch (skb->nh.iph->protocol) {
12202 +                       struct tcphdr *th;
12203 +                       struct udphdr *uh;
12204 +               case IPPROTO_TCP:
12205 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12206 +                       dst.port = th->dest;
12207 +                       break;
12208 +               case IPPROTO_UDP:
12209 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12210 +                       dst.port = uh->dest;
12211 +                       break;
12212 +               default:
12213 +                       break;
12214 +               }
12215 +       } 
12216 +
12217 +       LOCK_BH(&hinfo->lock);
12218 +       dh = __dsthash_find(hinfo, &dst);
12219 +       if (!dh) {
12220 +               dh = __dsthash_alloc_init(hinfo, &dst);
12221 +
12222 +               if (!dh) {
12223 +                       /* enomem... don't match == DROP */
12224 +                       if (net_ratelimit())
12225 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
12226 +                       UNLOCK_BH(&hinfo->lock);
12227 +                       return 0;
12228 +               }
12229 +
12230 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
12231 +
12232 +               dh->rateinfo.prev = jiffies;
12233 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
12234 +                                                       hinfo->cfg.burst);
12235 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
12236 +                                                       hinfo->cfg.burst);
12237 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
12238 +
12239 +               UNLOCK_BH(&hinfo->lock);
12240 +               return 1;
12241 +       }
12242 +
12243 +       /* update expiration timeout */
12244 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
12245 +
12246 +       rateinfo_recalc(dh, now);
12247 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
12248 +               /* We're underlimit. */
12249 +               dh->rateinfo.credit -= dh->rateinfo.cost;
12250 +               UNLOCK_BH(&hinfo->lock);
12251 +               return 1;
12252 +       }
12253 +
12254 +               UNLOCK_BH(&hinfo->lock);
12255 +
12256 +       /* default case: we're overlimit, thus don't match */
12257 +       return 0;
12258 +}
12259 +
12260 +static int
12261 +dstlimit_checkentry(const char *tablename,
12262 +                    const struct ipt_ip *ip,
12263 +                    void *matchinfo,
12264 +                    unsigned int matchsize,
12265 +                    unsigned int hook_mask)
12266 +{
12267 +       struct ipt_dstlimit_info *r = matchinfo;
12268 +
12269 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
12270 +               return 0;
12271 +
12272 +       /* Check for overflow. */
12273 +       if (r->cfg.burst == 0
12274 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
12275 +                                       user2credits(r->cfg.avg)) {
12276 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
12277 +                      r->cfg.avg, r->cfg.burst);
12278 +               return 0;
12279 +       }
12280 +
12281 +       if (r->cfg.mode == 0 
12282 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
12283 +                         |IPT_DSTLIMIT_HASH_DIP
12284 +                         |IPT_DSTLIMIT_HASH_SIP))
12285 +               return 0;
12286 +
12287 +       if (!r->cfg.gc_interval)
12288 +               return 0;
12289 +       
12290 +       if (!r->cfg.expire)
12291 +               return 0;
12292 +
12293 +       r->hinfo = htable_find_get(r->name);
12294 +       if (!r->hinfo && (htable_create(r) != 0)) {
12295 +               return 0;
12296 +       }
12297 +
12298 +       /* Ugly hack: For SMP, we only want to use one set */
12299 +       r->u.master = r;
12300 +
12301 +       return 1;
12302 +}
12303 +
12304 +static void
12305 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
12306 +{
12307 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
12308 +
12309 +       htable_put(r->hinfo);
12310 +}
12311 +
12312 +static struct ipt_match ipt_dstlimit = { 
12313 +       .list = { .prev = NULL, .next = NULL }, 
12314 +       .name = "dstlimit", 
12315 +       .match = dstlimit_match, 
12316 +       .checkentry = dstlimit_checkentry, 
12317 +       .destroy = dstlimit_destroy,
12318 +       .me = THIS_MODULE 
12319 +};
12320 +
12321 +/* PROC stuff */
12322 +
12323 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
12324 +{
12325 +       struct proc_dir_entry *pde = s->private;
12326 +       struct ipt_dstlimit_htable *htable = pde->data;
12327 +       unsigned int *bucket;
12328 +
12329 +       LOCK_BH(&htable->lock);
12330 +       if (*pos >= htable->cfg.size)
12331 +               return NULL;
12332 +
12333 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
12334 +       if (!bucket)
12335 +               return ERR_PTR(-ENOMEM);
12336 +
12337 +       *bucket = *pos;
12338 +       return bucket;
12339 +}
12340 +
12341 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
12342 +{
12343 +       struct proc_dir_entry *pde = s->private;
12344 +       struct ipt_dstlimit_htable *htable = pde->data;
12345 +       unsigned int *bucket = (unsigned int *)v;
12346 +
12347 +       *pos = ++(*bucket);
12348 +       if (*pos >= htable->cfg.size) {
12349 +               kfree(v);
12350 +               return NULL;
12351 +       }
12352 +       return bucket;
12353 +}
12354 +
12355 +static void dl_seq_stop(struct seq_file *s, void *v)
12356 +{
12357 +       struct proc_dir_entry *pde = s->private;
12358 +       struct ipt_dstlimit_htable *htable = pde->data;
12359 +       unsigned int *bucket = (unsigned int *)v;
12360 +
12361 +       kfree(bucket);
12362 +
12363 +       UNLOCK_BH(&htable->lock);
12364 +}
12365 +
12366 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
12367 +{
12368 +       /* recalculate to show accurate numbers */
12369 +       rateinfo_recalc(ent, jiffies);
12370 +
12371 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
12372 +                       (ent->expires - jiffies)/HZ,
12373 +                       NIPQUAD(ent->dst.src_ip),
12374 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
12375 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
12376 +                       ent->rateinfo.cost);
12377 +}
12378 +
12379 +static int dl_seq_show(struct seq_file *s, void *v)
12380 +{
12381 +       struct proc_dir_entry *pde = s->private;
12382 +       struct ipt_dstlimit_htable *htable = pde->data;
12383 +       unsigned int *bucket = (unsigned int *)v;
12384 +
12385 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
12386 +                     struct dsthash_ent *, s)) {
12387 +               /* buffer was filled and unable to print that tuple */
12388 +               return 1;
12389 +       }
12390 +       return 0;
12391 +}
12392 +
12393 +static struct seq_operations dl_seq_ops = {
12394 +       .start = dl_seq_start,
12395 +       .next  = dl_seq_next,
12396 +       .stop  = dl_seq_stop,
12397 +       .show  = dl_seq_show
12398 +};
12399 +
12400 +static int dl_proc_open(struct inode *inode, struct file *file)
12401 +{
12402 +       int ret = seq_open(file, &dl_seq_ops);
12403 +
12404 +       if (!ret) {
12405 +               struct seq_file *sf = file->private_data;
12406 +               sf->private = PDE(inode);
12407 +       }
12408 +       return ret;
12409 +}
12410 +
12411 +static struct file_operations dl_file_ops = {
12412 +       .owner   = THIS_MODULE,
12413 +       .open    = dl_proc_open,
12414 +       .read    = seq_read,
12415 +       .llseek  = seq_lseek,
12416 +       .release = seq_release
12417 +};
12418 +
12419 +static int init_or_fini(int fini)
12420 +{
12421 +       int ret = 0;
12422 +
12423 +       if (fini)
12424 +               goto cleanup;
12425 +
12426 +       if (ipt_register_match(&ipt_dstlimit)) {
12427 +               ret = -EINVAL;
12428 +               goto cleanup_nothing;
12429 +       }
12430 +
12431 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
12432 +        * quite small ? */
12433 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
12434 +                                           sizeof(struct dsthash_ent), 0,
12435 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
12436 +       if (!dstlimit_cachep) {
12437 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
12438 +               ret = -ENOMEM;
12439 +               goto cleanup_unreg_match;
12440 +       }
12441 +
12442 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
12443 +       if (!dstlimit_procdir) {
12444 +               printk(KERN_ERR "Unable to create proc dir entry\n");
12445 +               ret = -ENOMEM;
12446 +               goto cleanup_free_slab;
12447 +       }
12448 +
12449 +       return ret;
12450 +
12451 +cleanup:
12452 +       remove_proc_entry("ipt_dstlimit", proc_net);
12453 +cleanup_free_slab:
12454 +       kmem_cache_destroy(dstlimit_cachep);
12455 +cleanup_unreg_match:
12456 +       ipt_unregister_match(&ipt_dstlimit);
12457 +cleanup_nothing:
12458 +       return ret;
12459 +       
12460 +}
12461 +
12462 +static int __init init(void)
12463 +{
12464 +       return init_or_fini(0);
12465 +}
12466 +
12467 +static void __exit fini(void)
12468 +{
12469 +       init_or_fini(1);
12470 +}
12471 +
12472 +module_init(init);
12473 +module_exit(fini);
12474 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.6/net/ipv4/netfilter/ipt_fuzzy.c
12475 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_fuzzy.c      1970-01-01 01:00:00.000000000 +0100
12476 +++ linux-2.6.6/net/ipv4/netfilter/ipt_fuzzy.c  2004-05-18 12:36:22.000000000 +0200
12477 @@ -0,0 +1,185 @@
12478 +/*
12479 + *  This module implements a simple TSK FLC 
12480 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
12481 + * to limit , in an adaptive and flexible way , the packet rate crossing 
12482 + * a given stream . It serves as an initial and very simple (but effective)
12483 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
12484 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
12485 + * into our code in a precise , adaptive and efficient manner. 
12486 + *  The goal is very similar to that of "limit" match , but using techniques of
12487 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
12488 + * avoiding over and undershoots - and stuff like that .
12489 + *
12490 + *
12491 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
12492 + * 2002-08-17  : Changed to eliminate floating point operations .
12493 + * 2002-08-23  : Coding style changes .
12494 +*/
12495 +
12496 +#include <linux/module.h>
12497 +#include <linux/skbuff.h>
12498 +#include <linux/ip.h>
12499 +#include <linux/random.h>
12500 +#include <net/tcp.h>
12501 +#include <linux/spinlock.h>
12502 +#include <linux/netfilter_ipv4/ip_tables.h>
12503 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
12504 +
12505 +/*
12506 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
12507 + Expressed in percentage
12508 +*/
12509 +
12510 +#define PAR_LOW                1/100
12511 +#define PAR_HIGH       1
12512 +
12513 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
12514 +
12515 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
12516 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
12517 +MODULE_LICENSE("GPL");
12518 +
12519 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12520 +{
12521 +       if (tx >= maxi)
12522 +               return 100;
12523 +
12524 +       if (tx <= mini)
12525 +               return 0;
12526 +
12527 +       return ( (100*(tx-mini)) / (maxi-mini) );
12528 +}
12529 +
12530 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12531 +{
12532 +       if (tx <= mini)
12533 +               return 100;
12534 +
12535 +       if (tx >= maxi)
12536 +               return 0;
12537 +
12538 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
12539 +}
12540 +
12541 +static int
12542 +ipt_fuzzy_match(const struct sk_buff *pskb,
12543 +              const struct net_device *in,
12544 +              const struct net_device *out,
12545 +              const void *matchinfo,
12546 +              int offset,
12547 +              int *hotdrop)
12548 +{
12549 +       /* From userspace */
12550 +       
12551 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
12552 +
12553 +       u_int8_t random_number;
12554 +       unsigned long amount;
12555 +       u_int8_t howhigh, howlow;
12556 +       
12557 +
12558 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
12559 +
12560 +       info->bytes_total += pskb->len;
12561 +       info->packets_total++;
12562 +
12563 +       info->present_time = jiffies;
12564 +       
12565 +       if (info->present_time >= info->previous_time)
12566 +               amount = info->present_time - info->previous_time;
12567 +       else { 
12568 +               /* There was a transition : I choose to re-sample 
12569 +                  and keep the old acceptance rate...
12570 +               */
12571 +
12572 +               amount = 0;
12573 +               info->previous_time = info->present_time;
12574 +               info->bytes_total = info->packets_total = 0;
12575 +       };
12576 +       
12577 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
12578 +       {
12579 +
12580 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
12581 +                                       / amount );
12582 +
12583 +               info->previous_time = info->present_time;
12584 +               info->bytes_total = info->packets_total = 0;
12585 +
12586 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
12587 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
12588 +
12589 +               info->acceptance_rate = (u_int8_t) \
12590 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
12591 +
12592 +               /* In fact , the above defuzzification would require a denominator
12593 +                  proportional to (howhigh+howlow) but , in this particular case ,
12594 +                  that expression is constant .
12595 +                  An imediate consequence is that it isn't necessary to call 
12596 +                  both mf_high and mf_low - but to keep things understandable ,
12597 +                  I did so .  */ 
12598 +
12599 +       }
12600 +       
12601 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
12602 +
12603 +
12604 +       if ( info->acceptance_rate < 100 )
12605 +       {                
12606 +               get_random_bytes((void *)(&random_number), 1);
12607 +
12608 +               /*  If within the acceptance , it can pass => don't match */
12609 +               if (random_number <= (255 * info->acceptance_rate) / 100)
12610 +                       return 0;
12611 +               else
12612 +                       return 1; /* It can't pass ( It matches ) */
12613 +       } ;
12614 +
12615 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
12616 +       
12617 +}
12618 +
12619 +static int
12620 +ipt_fuzzy_checkentry(const char *tablename,
12621 +                  const struct ipt_ip *e,
12622 +                  void *matchinfo,
12623 +                  unsigned int matchsize,
12624 +                  unsigned int hook_mask)
12625 +{
12626 +       
12627 +       const struct ipt_fuzzy_info *info = matchinfo;
12628 +
12629 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
12630 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
12631 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
12632 +               return 0;
12633 +       }
12634 +
12635 +       if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
12636 +           || (info->minimum_rate >= info->maximum_rate )) {
12637 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
12638 +               return 0;
12639 +       }
12640 +
12641 +       return 1;
12642 +}
12643 +
12644 +static struct ipt_match ipt_fuzzy_reg = { 
12645 +       .name = "fuzzy",
12646 +       .match = ipt_fuzzy_match,
12647 +       .checkentry = ipt_fuzzy_checkentry,
12648 +       .me = THIS_MODULE
12649 +};
12650 +
12651 +static int __init init(void)
12652 +{
12653 +       return ipt_register_match(&ipt_fuzzy_reg);
12654 +}
12655 +
12656 +static void __exit fini(void)
12657 +{
12658 +       ipt_unregister_match(&ipt_fuzzy_reg);
12659 +}
12660 +
12661 +module_init(init);
12662 +module_exit(fini);
12663 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6/net/ipv4/netfilter/ipt_helper.c
12664 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_helper.c     2004-05-10 04:32:54.000000000 +0200
12665 +++ linux-2.6.6/net/ipv4/netfilter/ipt_helper.c 2004-05-18 12:39:27.000000000 +0200
12666 @@ -41,17 +41,17 @@
12667         struct ip_conntrack_expect *exp;
12668         struct ip_conntrack *ct;
12669         enum ip_conntrack_info ctinfo;
12670 -       int ret = 0;
12671 +       int ret = info->invert;
12672         
12673         ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12674         if (!ct) {
12675                 DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
12676 -               return 0;
12677 +               return ret;
12678         }
12679  
12680         if (!ct->master) {
12681                 DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
12682 -               return 0;
12683 +               return ret;
12684         }
12685  
12686         exp = ct->master;
12687 @@ -71,8 +71,11 @@
12688         DEBUGP("master's name = %s , info->name = %s\n", 
12689                 exp->expectant->helper->name, info->name);
12690  
12691 -       ret = !strncmp(exp->expectant->helper->name, info->name, 
12692 -                      strlen(exp->expectant->helper->name)) ^ info->invert;
12693 +       if (info->name[0] == '\0')
12694 +               ret ^= 1;
12695 +       else
12696 +               ret ^= !strncmp(exp->expectant->helper->name, info->name, 
12697 +                               strlen(exp->expectant->helper->name));
12698  out_unlock:
12699         READ_UNLOCK(&ip_conntrack_lock);
12700         return ret;
12701 @@ -92,10 +95,6 @@
12702         if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
12703                 return 0;
12704  
12705 -       /* verify that we actually should match anything */
12706 -       if ( strlen(info->name) == 0 )
12707 -               return 0;
12708 -       
12709         return 1;
12710  }
12711  
12712 @@ -108,7 +107,6 @@
12713  
12714  static int __init init(void)
12715  {
12716 -       need_ip_conntrack();
12717         return ipt_register_match(&helper_match);
12718  }
12719  
12720 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.6/net/ipv4/netfilter/ipt_ipv4options.c
12721 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_ipv4options.c        1970-01-01 01:00:00.000000000 +0100
12722 +++ linux-2.6.6/net/ipv4/netfilter/ipt_ipv4options.c    2004-05-18 12:36:29.000000000 +0200
12723 @@ -0,0 +1,172 @@
12724 +/*
12725 +  This is a module which is used to match ipv4 options.
12726 +  This file is distributed under the terms of the GNU General Public
12727 +  License (GPL). Copies of the GPL can be obtained from:
12728 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
12729 +
12730 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
12731 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
12732 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
12733 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
12734 +  19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
12735 +*/
12736 +
12737 +#include <linux/module.h>
12738 +#include <linux/skbuff.h>
12739 +#include <net/ip.h>
12740 +
12741 +#include <linux/netfilter_ipv4/ip_tables.h>
12742 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
12743 +
12744 +MODULE_LICENSE("GPL");
12745 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12746 +
12747 +static int
12748 +match(const struct sk_buff *skb,
12749 +      const struct net_device *in,
12750 +      const struct net_device *out,
12751 +      const void *matchinfo,
12752 +      int offset,
12753 +      int *hotdrop)
12754 +{
12755 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
12756 +       const struct iphdr *iph = skb->nh.iph;
12757 +       const struct ip_options *opt;
12758 +
12759 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
12760 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
12761 +
12762 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
12763 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12764 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12765 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12766 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12767 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
12768 +                       return 0;
12769 +               return 1;
12770 +       }
12771 +       else {
12772 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
12773 +                       /* there are options, and we don't need to care which one */
12774 +                       return 1;
12775 +               else {
12776 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
12777 +                               /* there are options but we don't want any ! */
12778 +                               return 0;
12779 +               }
12780 +       }
12781 +
12782 +       opt = &(IPCB(skb)->opt);
12783 +
12784 +       /* source routing */
12785 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
12786 +               if (!((opt->srr) & (opt->is_strictroute)))
12787 +                       return 0;
12788 +       }
12789 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
12790 +               if (!((opt->srr) & (!opt->is_strictroute)))
12791 +                       return 0;
12792 +       }
12793 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
12794 +               if (opt->srr)
12795 +                       return 0;
12796 +       }
12797 +       /* record route */
12798 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
12799 +               if (!opt->rr)
12800 +                       return 0;
12801 +       }
12802 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
12803 +               if (opt->rr)
12804 +                       return 0;
12805 +       }
12806 +       /* timestamp */
12807 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
12808 +               if (!opt->ts)
12809 +                       return 0;
12810 +       }
12811 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
12812 +               if (opt->ts)
12813 +                       return 0;
12814 +       }
12815 +       /* router-alert option  */
12816 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
12817 +               if (!opt->router_alert)
12818 +                       return 0;
12819 +       }
12820 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
12821 +               if (opt->router_alert)
12822 +                       return 0;
12823 +       }
12824 +
12825 +       /* we match ! */
12826 +       return 1;
12827 +}
12828 +
12829 +static int
12830 +checkentry(const char *tablename,
12831 +          const struct ipt_ip *ip,
12832 +          void *matchinfo,
12833 +          unsigned int matchsize,
12834 +          unsigned int hook_mask)
12835 +{
12836 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
12837 +       /* Check the size */
12838 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
12839 +               return 0;
12840 +       /* Now check the coherence of the data ... */
12841 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
12842 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
12843 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
12844 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
12845 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
12846 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
12847 +               return 0; /* opposites */
12848 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
12849 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12850 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12851 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12852 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12853 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
12854 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
12855 +               return 0; /* opposites */
12856 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
12857 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
12858 +               return 0; /* cannot match in the same time loose and strict source routing */
12859 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12860 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
12861 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
12862 +               return 0; /* opposites */
12863 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
12864 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
12865 +               return 0; /* opposites */
12866 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
12867 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
12868 +               return 0; /* opposites */
12869 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
12870 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
12871 +               return 0; /* opposites */
12872 +
12873 +       /* everything looks ok. */
12874 +       return 1;
12875 +}
12876 +
12877 +static struct ipt_match ipv4options_match = { 
12878 +       .name = "ipv4options",
12879 +       .match = match,
12880 +       .checkentry = checkentry,
12881 +       .me = THIS_MODULE
12882 +};
12883 +
12884 +static int __init init(void)
12885 +{
12886 +       return ipt_register_match(&ipv4options_match);
12887 +}
12888 +
12889 +static void __exit fini(void)
12890 +{
12891 +       ipt_unregister_match(&ipv4options_match);
12892 +}
12893 +
12894 +module_init(init);
12895 +module_exit(fini);
12896 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.6/net/ipv4/netfilter/ipt_mport.c
12897 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_mport.c      1970-01-01 01:00:00.000000000 +0100
12898 +++ linux-2.6.6/net/ipv4/netfilter/ipt_mport.c  2004-05-18 12:36:36.000000000 +0200
12899 @@ -0,0 +1,116 @@
12900 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
12901 +   the same place so we can treat them as equal. */
12902 +#include <linux/module.h>
12903 +#include <linux/types.h>
12904 +#include <linux/udp.h>
12905 +#include <linux/skbuff.h>
12906 +
12907 +#include <linux/netfilter_ipv4/ipt_mport.h>
12908 +#include <linux/netfilter_ipv4/ip_tables.h>
12909 +
12910 +MODULE_LICENSE("GPL");
12911 +
12912 +#if 0
12913 +#define duprintf(format, args...) printk(format , ## args)
12914 +#else
12915 +#define duprintf(format, args...)
12916 +#endif
12917 +
12918 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
12919 +static inline int
12920 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
12921 +{
12922 +       unsigned int i;
12923 +        unsigned int m;
12924 +        u_int16_t pflags = minfo->pflags;
12925 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
12926 +                u_int16_t s, e;
12927 +
12928 +                if (pflags & m
12929 +                    && minfo->ports[i] == 65535)
12930 +                        return 0;
12931 +
12932 +                s = minfo->ports[i];
12933 +
12934 +                if (pflags & m) {
12935 +                        e = minfo->ports[++i];
12936 +                        m <<= 1;
12937 +                } else
12938 +                        e = s;
12939 +
12940 +                if (minfo->flags & IPT_MPORT_SOURCE
12941 +                    && src >= s && src <= e)
12942 +                        return 1;
12943 +
12944 +               if (minfo->flags & IPT_MPORT_DESTINATION
12945 +                   && dst >= s && dst <= e)
12946 +                       return 1;
12947 +       }
12948 +
12949 +       return 0;
12950 +}
12951 +
12952 +static int
12953 +match(const struct sk_buff *skb,
12954 +      const struct net_device *in,
12955 +      const struct net_device *out,
12956 +      const void *matchinfo,
12957 +      int offset,
12958 +      int *hotdrop)
12959 +{
12960 +       u16 ports[2];
12961 +       const struct ipt_mport *minfo = matchinfo;
12962 +
12963 +       if (offset)
12964 +               return 0;
12965 +
12966 +       /* Must be big enough to read ports (both UDP and TCP have
12967 +           them at the start). */
12968 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12969 +               /* We've been asked to examine this packet, and we
12970 +                  can't.  Hence, no choice but to drop. */
12971 +                       duprintf("ipt_multiport:"
12972 +                                " Dropping evil offset=0 tinygram.\n");
12973 +                       *hotdrop = 1;
12974 +                       return 0;
12975 +       }
12976 +
12977 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
12978 +}
12979 +
12980 +/* Called when user tries to insert an entry of this type. */
12981 +static int
12982 +checkentry(const char *tablename,
12983 +          const struct ipt_ip *ip,
12984 +          void *matchinfo,
12985 +          unsigned int matchsize,
12986 +          unsigned int hook_mask)
12987 +{
12988 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
12989 +               return 0;
12990 +
12991 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
12992 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
12993 +               && !(ip->invflags & IPT_INV_PROTO)
12994 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
12995 +}
12996 +
12997 +static struct ipt_match mport_match = { 
12998 +       .name = "mport",
12999 +       .match = &match,
13000 +       .checkentry = &checkentry,
13001 +       .me = THIS_MODULE
13002 +};
13003 +
13004 +static int __init init(void)
13005 +{
13006 +       return ipt_register_match(&mport_match);
13007 +}
13008 +
13009 +static void __exit fini(void)
13010 +{
13011 +       ipt_unregister_match(&mport_match);
13012 +}
13013 +
13014 +module_init(init);
13015 +module_exit(fini);
13016 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.6/net/ipv4/netfilter/ipt_nth.c
13017 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_nth.c        1970-01-01 01:00:00.000000000 +0100
13018 +++ linux-2.6.6/net/ipv4/netfilter/ipt_nth.c    2004-05-18 12:36:40.000000000 +0200
13019 @@ -0,0 +1,166 @@
13020 +/*
13021 +  This is a module which is used for match support for every Nth packet
13022 +  This file is distributed under the terms of the GNU General Public
13023 +  License (GPL). Copies of the GPL can be obtained from:
13024 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
13025 +
13026 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
13027 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
13028 +        * added support for multiple counters
13029 +        * added support for matching on individual packets
13030 +          in the counter cycle
13031 +  2004-02-19 Harald Welte <laforge@netfilter.org>
13032 +       * port to 2.6.x
13033 +
13034 +*/
13035 +
13036 +#include <linux/module.h>
13037 +#include <linux/skbuff.h>
13038 +#include <linux/ip.h>
13039 +#include <net/tcp.h>
13040 +#include <linux/spinlock.h>
13041 +#include <linux/netfilter_ipv4/ip_tables.h>
13042 +#include <linux/netfilter_ipv4/ipt_nth.h>
13043 +
13044 +MODULE_LICENSE("GPL");
13045 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
13046 +
13047 +/*
13048 + * State information.
13049 + */
13050 +struct state {
13051 +       spinlock_t lock;
13052 +       u_int16_t number;
13053 +};
13054 +
13055 +static struct state states[IPT_NTH_NUM_COUNTERS];
13056 +
13057 +static int
13058 +ipt_nth_match(const struct sk_buff *pskb,
13059 +             const struct net_device *in,
13060 +             const struct net_device *out,
13061 +             const void *matchinfo,
13062 +             int offset,
13063 +             int *hotdrop)
13064 +{
13065 +       /* Parameters from userspace */
13066 +       const struct ipt_nth_info *info = matchinfo;
13067 +        unsigned counter = info->counter;
13068 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
13069 +       {
13070 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
13071 +               return 0;
13072 +        };
13073 +
13074 +        spin_lock(&states[counter].lock);
13075 +
13076 +        /* Are we matching every nth packet?*/
13077 +        if (info->packet == 0xFF)
13078 +        {
13079 +               /* We're matching every nth packet and only every nth packet*/
13080 +               /* Do we match or invert match? */
13081 +               if (info->not == 0)
13082 +               {
13083 +                       if (states[counter].number == 0)
13084 +                       {
13085 +                               ++states[counter].number;
13086 +                               goto match;
13087 +                       }
13088 +                       if (states[counter].number >= info->every)
13089 +                               states[counter].number = 0; /* reset the counter */
13090 +                       else
13091 +                               ++states[counter].number;
13092 +                       goto dontmatch;
13093 +               }
13094 +               else
13095 +               {
13096 +                       if (states[counter].number == 0)
13097 +                       {
13098 +                               ++states[counter].number;
13099 +                               goto dontmatch;
13100 +                       }
13101 +                       if (states[counter].number >= info->every)
13102 +                               states[counter].number = 0;
13103 +                       else
13104 +                               ++states[counter].number;
13105 +                       goto match;
13106 +               }
13107 +        }
13108 +        else
13109 +        {
13110 +               /* We're using the --packet, so there must be a rule for every value */
13111 +               if (states[counter].number == info->packet)
13112 +               {
13113 +                       /* only increment the counter when a match happens */
13114 +                       if (states[counter].number >= info->every)
13115 +                               states[counter].number = 0; /* reset the counter */
13116 +                       else
13117 +                               ++states[counter].number;
13118 +                       goto match;
13119 +               }
13120 +               else
13121 +                       goto dontmatch;
13122 +       }
13123 +
13124 + dontmatch:
13125 +       /* don't match */
13126 +       spin_unlock(&states[counter].lock);
13127 +       return 0;
13128 +
13129 + match:
13130 +       spin_unlock(&states[counter].lock);
13131 +       return 1;
13132 +}
13133 +
13134 +static int
13135 +ipt_nth_checkentry(const char *tablename,
13136 +                  const struct ipt_ip *e,
13137 +                  void *matchinfo,
13138 +                  unsigned int matchsize,
13139 +                  unsigned int hook_mask)
13140 +{
13141 +       /* Parameters from userspace */
13142 +       const struct ipt_nth_info *info = matchinfo;
13143 +        unsigned counter = info->counter;
13144 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
13145 +       {
13146 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
13147 +                       return 0;
13148 +               };
13149 +
13150 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
13151 +               printk("nth: matchsize %u != %u\n", matchsize,
13152 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
13153 +               return 0;
13154 +       }
13155 +
13156 +       states[counter].number = info->startat;
13157 +
13158 +       return 1;
13159 +}
13160 +
13161 +static struct ipt_match ipt_nth_reg = { 
13162 +       .name = "nth",
13163 +       .match = ipt_nth_match,
13164 +       .checkentry = ipt_nth_checkentry,
13165 +       .me = THIS_MODULE
13166 +};
13167 +
13168 +static int __init init(void)
13169 +{
13170 +       unsigned counter;
13171 +
13172 +       memset(&states, 0, sizeof(states));
13173 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
13174 +               spin_lock_init(&(states[counter].lock));
13175 +
13176 +       return ipt_register_match(&ipt_nth_reg);
13177 +}
13178 +
13179 +static void __exit fini(void)
13180 +{
13181 +       ipt_unregister_match(&ipt_nth_reg);
13182 +}
13183 +
13184 +module_init(init);
13185 +module_exit(fini);
13186 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.6/net/ipv4/netfilter/ipt_osf.c
13187 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_osf.c        1970-01-01 01:00:00.000000000 +0100
13188 +++ linux-2.6.6/net/ipv4/netfilter/ipt_osf.c    2004-05-18 12:36:46.000000000 +0200
13189 @@ -0,0 +1,865 @@
13190 +/*
13191 + * ipt_osf.c
13192 + *
13193 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
13194 + *
13195 + *
13196 + * This program is free software; you can redistribute it and/or modify
13197 + * it under the terms of the GNU General Public License as published by
13198 + * the Free Software Foundation; either version 2 of the License, or
13199 + * (at your option) any later version.
13200 + *
13201 + * This program is distributed in the hope that it will be useful,
13202 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13203 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13204 + * GNU General Public License for more details.
13205 + *
13206 + * You should have received a copy of the GNU General Public License
13207 + * along with this program; if not, write to the Free Software
13208 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13209 + */
13210 +
13211 +/*
13212 + * OS fingerprint matching module.
13213 + * It simply compares various parameters from SYN packet with
13214 + * some hardcoded ones.
13215 + *
13216 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
13217 + * for his p0f.
13218 + */
13219 +
13220 +#include <linux/config.h>
13221 +#include <linux/kernel.h>
13222 +#include <linux/types.h>
13223 +#include <linux/string.h>
13224 +#include <linux/smp.h>
13225 +#include <linux/module.h>
13226 +#include <linux/skbuff.h>
13227 +#include <linux/file.h>
13228 +#include <linux/ip.h>
13229 +#include <linux/proc_fs.h>
13230 +#include <linux/fs.h>
13231 +#include <linux/slab.h>
13232 +#include <linux/spinlock.h>
13233 +#include <linux/ctype.h>
13234 +#include <linux/list.h>
13235 +#include <linux/if.h>
13236 +
13237 +#include <net/sock.h>
13238 +#include <net/ip.h>
13239 +
13240 +#include <linux/netfilter_ipv4/ip_tables.h>
13241 +
13242 +#include <linux/netfilter_ipv4/ipt_osf.h>
13243 +
13244 +#define OSF_DEBUG
13245 +
13246 +#ifdef OSF_DEBUG
13247 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
13248 +#define loga(x...)             printk(x)
13249 +#else
13250 +#define log(x...)              do {} while(0)
13251 +#define loga(x...)             do {} while(0)
13252 +#endif
13253 +
13254 +#define FMATCH_WRONG           0
13255 +#define FMATCH_OK              1
13256 +#define FMATCH_OPT_WRONG       2
13257 +
13258 +#define OPTDEL                 ','
13259 +#define OSFPDEL                ':'
13260 +#define MAXOPTSTRLEN           128
13261 +#define OSFFLUSH               "FLUSH"
13262 +
13263 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
13264 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
13265 +static struct list_head        finger_list;    
13266 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
13267 +                     const void *, int, 
13268 +                     const void *, u_int16_t, 
13269 +                     int *);
13270 +static int checkentry(const char *, const struct ipt_ip *, void *,
13271 +                          unsigned int, unsigned int);
13272 +
13273 +static unsigned long seq, ipt_osf_groups = 1;
13274 +static struct sock *nts;
13275 +
13276 +static struct ipt_match osf_match = 
13277 +{ 
13278 +       { NULL, NULL }, 
13279 +       "osf", 
13280 +       &match, 
13281 +       &checkentry, 
13282 +       NULL, 
13283 +       THIS_MODULE 
13284 +};
13285 +
13286 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
13287 +{
13288 +       unsigned int size;
13289 +       struct sk_buff *skb;
13290 +       struct ipt_osf_nlmsg *data;
13291 +       struct nlmsghdr *nlh;
13292 +
13293 +       size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
13294 +
13295 +       skb = alloc_skb(size, GFP_ATOMIC);
13296 +       if (!skb)
13297 +       {
13298 +               log("skb_alloc() failed.\n");
13299 +               return;
13300 +       }
13301 +       
13302 +       nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
13303 +       
13304 +       data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
13305 +
13306 +       memcpy(&data->f, f, sizeof(struct osf_finger));
13307 +       memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
13308 +       memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
13309 +
13310 +       NETLINK_CB(skb).dst_groups = ipt_osf_groups;
13311 +       netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
13312 +
13313 +nlmsg_failure:
13314 +       return;
13315 +}
13316 +
13317 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
13318 +{
13319 +       struct iphdr *ip = skb->nh.iph;
13320 +
13321 +       if (flags & IPT_OSF_SMART)
13322 +       {
13323 +               struct in_device *in_dev = in_dev_get(skb->dev);
13324 +
13325 +               for_ifa(in_dev)
13326 +               {
13327 +                       if (inet_ifa_match(ip->saddr, ifa))
13328 +                       {
13329 +                               in_dev_put(in_dev);
13330 +                               return (ip->ttl == f_ttl);
13331 +                       }
13332 +               }
13333 +               endfor_ifa(in_dev);
13334 +               
13335 +               in_dev_put(in_dev);
13336 +               return (ip->ttl <= f_ttl);
13337 +       }
13338 +       else
13339 +               return (ip->ttl == f_ttl);
13340 +}
13341 +
13342 +static int
13343 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
13344 +      const void *matchinfo, int offset,
13345 +      const void *hdr, u_int16_t datalen,
13346 +      int *hotdrop)
13347 +{
13348 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
13349 +       struct iphdr *ip = skb->nh.iph;
13350 +       struct tcphdr *tcp;
13351 +       int fmatch = FMATCH_WRONG, fcount = 0;
13352 +       unsigned long totlen, optsize = 0, window;
13353 +       unsigned char df, *optp = NULL, *_optp = NULL;
13354 +       char check_WSS = 0;
13355 +       struct list_head *ent;
13356 +       struct osf_finger *f;
13357 +
13358 +       if (!ip || !info)
13359 +               return 0;
13360 +                               
13361 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
13362 +
13363 +       if (!tcp->syn)
13364 +               return 0;
13365 +       
13366 +       totlen = ntohs(ip->tot_len);
13367 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
13368 +       window = ntohs(tcp->window);
13369 +       
13370 +       if (tcp->doff*4 > sizeof(struct tcphdr))
13371 +       {
13372 +               _optp = optp = (char *)(tcp+1);
13373 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
13374 +       }
13375 +
13376 +       
13377 +       /* Actually we can create hash/table of all genres and search
13378 +        * only in appropriate part, but here is initial variant,
13379 +        * so will use slow path.
13380 +        */
13381 +       read_lock(&osf_lock);
13382 +       list_for_each(ent, &finger_list)
13383 +       {
13384 +               f = list_entry(ent, struct osf_finger, flist);
13385 +       
13386 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
13387 +                       continue;
13388 +
13389 +               optp = _optp;
13390 +               fmatch = FMATCH_WRONG;
13391 +
13392 +               if (totlen == f->ss && df == f->df && 
13393 +                       smart_dec(skb, info->flags, f->ttl))
13394 +               {
13395 +                       unsigned long foptsize;
13396 +                       int optnum;
13397 +                       unsigned short mss = 0;
13398 +
13399 +                       check_WSS = 0;
13400 +
13401 +                       switch (f->wss.wc)
13402 +                       {
13403 +                               case 0:   check_WSS = 0; break;
13404 +                               case 'S': check_WSS = 1; break;
13405 +                               case 'T': check_WSS = 2; break;
13406 +                               case '%': check_WSS = 3; break;
13407 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
13408 +                                                        f->wss.wc, f->genre, f->details);
13409 +                                        check_WSS = 4;
13410 +                                        break;
13411 +                       }
13412 +                       if (check_WSS == 4)
13413 +                               continue;
13414 +
13415 +                       /* Check options */
13416 +
13417 +                       foptsize = 0;
13418 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
13419 +                               foptsize += f->opt[optnum].length;
13420 +
13421 +                               
13422 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
13423 +                               continue;
13424 +
13425 +                       if (!optp)
13426 +                       {
13427 +                               fmatch = FMATCH_OK;
13428 +                               loga("\tYEP : matching without options.\n");
13429 +                               if ((info->flags & IPT_OSF_LOG) && 
13430 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13431 +                                       break;
13432 +                               else
13433 +                                       continue;
13434 +                       }
13435 +                       
13436 +
13437 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
13438 +                       {
13439 +                               if (f->opt[optnum].kind == (*optp)) 
13440 +                               {
13441 +                                       unsigned char len = f->opt[optnum].length;
13442 +                                       unsigned char *optend = optp + len;
13443 +                                       int loop_cont = 0;
13444 +
13445 +                                       fmatch = FMATCH_OK;
13446 +
13447 +
13448 +                                       switch (*optp)
13449 +                                       {
13450 +                                               case OSFOPT_MSS:
13451 +                                                       mss = ntohs(*(unsigned short *)(optp+2));
13452 +                                                       break;
13453 +                                               case OSFOPT_TS:
13454 +                                                       loop_cont = 1;
13455 +                                                       break;
13456 +                                       }
13457 +                                       
13458 +                                       if (loop_cont)
13459 +                                       {
13460 +                                               optp = optend;
13461 +                                               continue;
13462 +                                       }
13463 +                                       
13464 +                                       if (len != 1)
13465 +                                       {
13466 +                                               /* Skip kind and length fields*/
13467 +                                               optp += 2; 
13468 +
13469 +                                               if (f->opt[optnum].wc.val != 0)
13470 +                                               {
13471 +                                                       unsigned long tmp = 0;
13472 +                                                       
13473 +                                                       /* Hmmm... It looks a bit ugly. :) */
13474 +                                                       memcpy(&tmp, optp, 
13475 +                                                               (len > sizeof(unsigned long)?
13476 +                                                                       sizeof(unsigned long):len));
13477 +                                                       /* 2 + 2: optlen(2 bytes) + 
13478 +                                                        *      kind(1 byte) + length(1 byte) */
13479 +                                                       if (len == 4) 
13480 +                                                               tmp = ntohs(tmp);
13481 +                                                       else
13482 +                                                               tmp = ntohl(tmp);
13483 +
13484 +                                                       if (f->opt[optnum].wc.wc == '%')
13485 +                                                       {
13486 +                                                               if ((tmp % f->opt[optnum].wc.val) != 0)
13487 +                                                                       fmatch = FMATCH_OPT_WRONG;
13488 +                                                       }
13489 +                                                       else if (tmp != f->opt[optnum].wc.val)
13490 +                                                               fmatch = FMATCH_OPT_WRONG;
13491 +                                               }
13492 +                                       }
13493 +
13494 +                                       optp = optend;
13495 +                               }
13496 +                               else
13497 +                                       fmatch = FMATCH_OPT_WRONG;
13498 +
13499 +                               if (fmatch != FMATCH_OK)
13500 +                                       break;
13501 +                       }
13502 +
13503 +                       if (fmatch != FMATCH_OPT_WRONG)
13504 +                       {
13505 +                               fmatch = FMATCH_WRONG;
13506 +
13507 +                               switch (check_WSS)
13508 +                               {
13509 +                                       case 0:
13510 +                                               if (f->wss.val == 0 || window == f->wss.val)
13511 +                                                       fmatch = FMATCH_OK;
13512 +                                               break;
13513 +                                       case 1: /* MSS */
13514 +/* Lurked in OpenBSD */
13515 +#define SMART_MSS      1460
13516 +                                               if (window == f->wss.val*mss || 
13517 +                                                       window == f->wss.val*SMART_MSS)
13518 +                                                       fmatch = FMATCH_OK;
13519 +                                               break;
13520 +                                       case 2: /* MTU */
13521 +                                               if (window == f->wss.val*(mss+40) ||
13522 +                                                       window == f->wss.val*(SMART_MSS+40))
13523 +                                                       fmatch = FMATCH_OK;
13524 +                                               break;
13525 +                                       case 3: /* MOD */
13526 +                                               if ((window % f->wss.val) == 0)
13527 +                                                       fmatch = FMATCH_OK;
13528 +                                               break;
13529 +                               }
13530 +                       }
13531 +                                       
13532 +
13533 +                       if (fmatch == FMATCH_OK)
13534 +                       {
13535 +                               fcount++;
13536 +                               log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n", 
13537 +                                       f->genre, f->version,
13538 +                                       f->subtype, f->details,
13539 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
13540 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest),
13541 +                                       f->ttl - ip->ttl);
13542 +                               if (info->flags & IPT_OSF_NETLINK)
13543 +                               {
13544 +                                       spin_lock_bh(&ipt_osf_netlink_lock);
13545 +                                       ipt_osf_nlsend(f, skb);
13546 +                                       spin_unlock_bh(&ipt_osf_netlink_lock);
13547 +                               }
13548 +                               if ((info->flags & IPT_OSF_LOG) && 
13549 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13550 +                                       break;
13551 +                       }
13552 +               }
13553 +       }
13554 +       if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
13555 +       {
13556 +               unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
13557 +               unsigned int i, optsize;
13558 +               struct osf_finger fg;
13559 +
13560 +               memset(&fg, 0, sizeof(fg));
13561 +
13562 +               if ((info->flags & IPT_OSF_LOG))
13563 +                       log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
13564 +               if (optp)
13565 +               {
13566 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
13567 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
13568 +                                         opt, optsize) < 0)
13569 +                       {
13570 +                               if (info->flags & IPT_OSF_LOG)
13571 +                                       loga("TRUNCATED");
13572 +                               if (info->flags & IPT_OSF_NETLINK)
13573 +                                       strcpy(fg.details, "TRUNCATED");
13574 +                       }
13575 +                       else
13576 +                       {
13577 +                               for (i = 0; i < optsize; i++)
13578 +                               {
13579 +                                       if (info->flags & IPT_OSF_LOG)
13580 +                                               loga("%02X", opt[i]);
13581 +                               }
13582 +                               if (info->flags & IPT_OSF_NETLINK)
13583 +                                       memcpy(fg.details, opt, MAXDETLEN);
13584 +                       }
13585 +               }
13586 +               if ((info->flags & IPT_OSF_LOG))
13587 +                       loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
13588 +                               NIPQUAD(ip->saddr), ntohs(tcp->source),
13589 +                               NIPQUAD(ip->daddr), ntohs(tcp->dest));
13590 +               
13591 +               if (info->flags & IPT_OSF_NETLINK)
13592 +               {
13593 +                       fg.wss.val      = window;
13594 +                       fg.ttl          = ip->ttl;
13595 +                       fg.df           = df;
13596 +                       fg.ss           = totlen;
13597 +                       strncpy(fg.genre, "Unknown", MAXGENRELEN);
13598 +
13599 +                       spin_lock_bh(&ipt_osf_netlink_lock);
13600 +                       ipt_osf_nlsend(&fg, skb);
13601 +                       spin_unlock_bh(&ipt_osf_netlink_lock);
13602 +               }
13603 +       }
13604 +
13605 +       read_unlock(&osf_lock);
13606 +
13607 +       return (fmatch == FMATCH_OK)?1:0;
13608 +}
13609 +
13610 +static int
13611 +checkentry(const char *tablename,
13612 +           const struct ipt_ip *ip,
13613 +           void *matchinfo,
13614 +           unsigned int matchsize,
13615 +           unsigned int hook_mask)
13616 +{
13617 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
13618 +               return 0;
13619 +       if (ip->proto != IPPROTO_TCP)
13620 +              return 0;
13621 +
13622 +       return 1;
13623 +}
13624 +
13625 +static char * osf_strchr(char *ptr, char c)
13626 +{
13627 +       char *tmp;
13628 +
13629 +       tmp = strchr(ptr, c);
13630 +
13631 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
13632 +               tmp++;
13633 +
13634 +       return tmp;
13635 +}
13636 +
13637 +static struct osf_finger * finger_alloc(void)
13638 +{
13639 +       struct osf_finger *f;
13640 +
13641 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
13642 +       if (f)
13643 +               memset(f, 0, sizeof(struct osf_finger));
13644 +       
13645 +       return f;
13646 +}
13647 +
13648 +static void finger_free(struct osf_finger *f)
13649 +{
13650 +       memset(f, 0, sizeof(struct osf_finger));
13651 +       kfree(f);
13652 +}
13653 +
13654 +
13655 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
13656 +{
13657 +       int i, op;
13658 +       char *ptr, wc;
13659 +       unsigned long val;
13660 +
13661 +       ptr = &obuf[0];
13662 +       i = 0;
13663 +       while (ptr != NULL && i < olen)
13664 +       {
13665 +               val = 0;
13666 +               op = 0;
13667 +               wc = 0;
13668 +               switch (obuf[i])
13669 +               {
13670 +                       case 'N': 
13671 +                               op = OSFOPT_NOP;
13672 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13673 +                               if (ptr)
13674 +                               {
13675 +                                       *ptr = '\0';
13676 +                                       ptr++;
13677 +                                       i += (int)(ptr-&obuf[i]);
13678 +
13679 +                               }
13680 +                               else
13681 +                                       i++;
13682 +                               break;
13683 +                       case 'S': 
13684 +                               op = OSFOPT_SACKP;
13685 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13686 +                               if (ptr)
13687 +                               {
13688 +                                       *ptr = '\0';
13689 +                                       ptr++;
13690 +                                       i += (int)(ptr-&obuf[i]);
13691 +
13692 +                               }
13693 +                               else
13694 +                                       i++;
13695 +                               break;
13696 +                       case 'T': 
13697 +                               op = OSFOPT_TS;
13698 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13699 +                               if (ptr)
13700 +                               {
13701 +                                       *ptr = '\0';
13702 +                                       ptr++;
13703 +                                       i += (int)(ptr-&obuf[i]);
13704 +
13705 +                               }
13706 +                               else
13707 +                                       i++;
13708 +                               break;
13709 +                       case 'W': 
13710 +                               op = OSFOPT_WSO;
13711 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13712 +                               if (ptr)
13713 +                               {
13714 +                                       switch (obuf[i+1])
13715 +                                       {
13716 +                                               case '%':       wc = '%'; break;
13717 +                                               case 'S':       wc = 'S'; break;
13718 +                                               case 'T':       wc = 'T'; break;
13719 +                                               default:        wc = 0; break;
13720 +                                       }
13721 +                                       
13722 +                                       *ptr = '\0';
13723 +                                       ptr++;
13724 +                                       if (wc)
13725 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
13726 +                                       else
13727 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
13728 +                                       i += (int)(ptr-&obuf[i]);
13729 +
13730 +                               }
13731 +                               else
13732 +                                       i++;
13733 +                               break;
13734 +                       case 'M': 
13735 +                               op = OSFOPT_MSS;
13736 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13737 +                               if (ptr)
13738 +                               {
13739 +                                       if (obuf[i+1] == '%')
13740 +                                               wc = '%';
13741 +                                       *ptr = '\0';
13742 +                                       ptr++;
13743 +                                       if (wc)
13744 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
13745 +                                       else
13746 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
13747 +                                       i += (int)(ptr-&obuf[i]);
13748 +
13749 +                               }
13750 +                               else
13751 +                                       i++;
13752 +                               break;
13753 +                       case 'E': 
13754 +                               op = OSFOPT_EOL;
13755 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13756 +                               if (ptr)
13757 +                               {
13758 +                                       *ptr = '\0';
13759 +                                       ptr++;
13760 +                                       i += (int)(ptr-&obuf[i]);
13761 +
13762 +                               }
13763 +                               else
13764 +                                       i++;
13765 +                               break;
13766 +                       default:
13767 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13768 +                               if (ptr)
13769 +                               {
13770 +                                       ptr++;
13771 +                                       i += (int)(ptr-&obuf[i]);
13772 +
13773 +                               }
13774 +                               else
13775 +                                       i++;
13776 +                               break;
13777 +               }
13778 +
13779 +               opt[*optnum].kind       = IANA_opts[op].kind;
13780 +               opt[*optnum].length     = IANA_opts[op].length;
13781 +               opt[*optnum].wc.wc      = wc;
13782 +               opt[*optnum].wc.val     = val;
13783 +
13784 +               (*optnum)++;
13785 +       }
13786 +}
13787 +
13788 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
13789 +{
13790 +       struct list_head *ent;
13791 +       struct osf_finger *f = NULL;
13792 +       int i;
13793 +       
13794 +       *eof = 1;
13795 +       count = 0;
13796 +
13797 +       read_lock_bh(&osf_lock);
13798 +       list_for_each(ent, &finger_list)
13799 +       {
13800 +               f = list_entry(ent, struct osf_finger, flist);
13801 +
13802 +               log("%s [%s]", f->genre, f->details);
13803 +               
13804 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
13805 +                                       f->genre, f->version,
13806 +                                       f->subtype, f->details);
13807 +               
13808 +               if (f->opt_num)
13809 +               {
13810 +                       loga(" OPT: ");
13811 +                       //count += sprintf(buf+count, " OPT: ");
13812 +                       for (i=0; i<f->opt_num; ++i)
13813 +                       {
13814 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
13815 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13816 +                               loga("%d.%c%lu; ", 
13817 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13818 +                       }
13819 +               }
13820 +               loga("\n");
13821 +               count += sprintf(buf+count, "\n");
13822 +       }
13823 +       read_unlock_bh(&osf_lock);
13824 +
13825 +       return count;
13826 +}
13827 +
13828 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
13829 +{
13830 +       int cnt;
13831 +       unsigned long i;
13832 +       char obuf[MAXOPTSTRLEN];
13833 +       struct osf_finger *finger;
13834 +       struct list_head *ent, *n;
13835 +
13836 +       char *pbeg, *pend;
13837 +
13838 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
13839 +       {
13840 +               int i = 0;
13841 +               write_lock_bh(&osf_lock);
13842 +               list_for_each_safe(ent, n, &finger_list)
13843 +               {
13844 +                       i++;
13845 +                       finger = list_entry(ent, struct osf_finger, flist);
13846 +                       list_del(&finger->flist);
13847 +                       finger_free(finger);
13848 +               }
13849 +               write_unlock_bh(&osf_lock);
13850 +       
13851 +               log("Flushed %d entries.\n", i);
13852 +               
13853 +               return count;
13854 +       }
13855 +
13856 +       
13857 +       cnt = 0;
13858 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
13859 +               if (buffer[i] == ':')
13860 +                       cnt++;
13861 +
13862 +       if (cnt != 8 || i != count)
13863 +       {
13864 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
13865 +                       cnt, i, count);
13866 +               return count;
13867 +       }
13868 +
13869 +       memset(obuf, 0, sizeof(obuf));
13870 +       
13871 +       finger = finger_alloc();
13872 +       if (!finger)
13873 +       {
13874 +               log("Failed to allocate new fingerprint entry.\n");
13875 +               return -ENOMEM;
13876 +       }
13877 +
13878 +       pbeg = (char *)buffer;
13879 +       pend = osf_strchr(pbeg, OSFPDEL);
13880 +       if (pend)
13881 +       {
13882 +               *pend = '\0';
13883 +               if (pbeg[0] == 'S')
13884 +               {
13885 +                       finger->wss.wc = 'S';
13886 +                       if (pbeg[1] == '%')
13887 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13888 +                       else if (pbeg[1] == '*')
13889 +                               finger->wss.val = 0;
13890 +                       else 
13891 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13892 +               }
13893 +               else if (pbeg[0] == 'T')
13894 +               {
13895 +                       finger->wss.wc = 'T';
13896 +                       if (pbeg[1] == '%')
13897 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13898 +                       else if (pbeg[1] == '*')
13899 +                               finger->wss.val = 0;
13900 +                       else 
13901 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13902 +               }
13903 +               else if (pbeg[0] == '%')
13904 +               {
13905 +                       finger->wss.wc = '%';
13906 +                       finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13907 +               }
13908 +               else if (isdigit(pbeg[0]))
13909 +               {
13910 +                       finger->wss.wc = 0;
13911 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
13912 +               }
13913 +
13914 +               pbeg = pend+1;
13915 +       }
13916 +       pend = osf_strchr(pbeg, OSFPDEL);
13917 +       if (pend)
13918 +       {
13919 +               *pend = '\0';
13920 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
13921 +               pbeg = pend+1;
13922 +       }
13923 +       pend = osf_strchr(pbeg, OSFPDEL);
13924 +       if (pend)
13925 +       {
13926 +               *pend = '\0';
13927 +               finger->df = simple_strtoul(pbeg, NULL, 10);
13928 +               pbeg = pend+1;
13929 +       }
13930 +       pend = osf_strchr(pbeg, OSFPDEL);
13931 +       if (pend)
13932 +       {
13933 +               *pend = '\0';
13934 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
13935 +               pbeg = pend+1;
13936 +       }
13937 +
13938 +       pend = osf_strchr(pbeg, OSFPDEL);
13939 +       if (pend)
13940 +       {
13941 +               *pend = '\0';
13942 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
13943 +               pbeg = pend+1;
13944 +       }
13945 +
13946 +       pend = osf_strchr(pbeg, OSFPDEL);
13947 +       if (pend)
13948 +       {
13949 +               *pend = '\0';
13950 +               if (pbeg[0] == '@' || pbeg[0] == '*')
13951 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
13952 +               else
13953 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
13954 +               pbeg = pend+1;
13955 +       }
13956 +       
13957 +       pend = osf_strchr(pbeg, OSFPDEL);
13958 +       if (pend)
13959 +       {
13960 +               *pend = '\0';
13961 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
13962 +               pbeg = pend+1;
13963 +       }
13964 +       
13965 +       pend = osf_strchr(pbeg, OSFPDEL);
13966 +       if (pend)
13967 +       {
13968 +               *pend = '\0';
13969 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
13970 +               pbeg = pend+1;
13971 +       }
13972 +
13973 +       cnt = snprintf(finger->details, 
13974 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
13975 +                       "%s", pbeg);
13976 +       
13977 +       log("%s - %s[%s] : %s\n", 
13978 +               finger->genre, finger->version,
13979 +               finger->subtype, finger->details);
13980 +       
13981 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
13982 +       
13983 +
13984 +       write_lock_bh(&osf_lock);
13985 +       list_add_tail(&finger->flist, &finger_list);
13986 +       write_unlock_bh(&osf_lock);
13987 +
13988 +       return count;
13989 +}
13990 +
13991 +static int __init osf_init(void)
13992 +{
13993 +       int err;
13994 +       struct proc_dir_entry *p;
13995 +
13996 +       log("Startng OS fingerprint matching module.\n");
13997 +
13998 +       INIT_LIST_HEAD(&finger_list);
13999 +       
14000 +       err = ipt_register_match(&osf_match);
14001 +       if (err)
14002 +       {
14003 +               log("Failed to register OS fingerprint matching module.\n");
14004 +               return -ENXIO;
14005 +       }
14006 +
14007 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
14008 +       if (!p)
14009 +       {
14010 +               ipt_unregister_match(&osf_match);
14011 +               return -ENXIO;
14012 +       }
14013 +
14014 +       p->write_proc = osf_proc_write;
14015 +       p->read_proc  = osf_proc_read;
14016 +       
14017 +       nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
14018 +       if (!nts)
14019 +       {
14020 +               log("netlink_kernel_create() failed\n");
14021 +               remove_proc_entry("sys/net/ipv4/osf", NULL);
14022 +               ipt_unregister_match(&osf_match);
14023 +               return -ENOMEM;
14024 +       }
14025 +
14026 +       return 0;
14027 +}
14028 +
14029 +static void __exit osf_fini(void)
14030 +{
14031 +       struct list_head *ent, *n;
14032 +       struct osf_finger *f;
14033 +       
14034 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
14035 +       ipt_unregister_match(&osf_match);
14036 +       if (nts && nts->sk_socket)
14037 +               sock_release(nts->sk_socket);
14038 +
14039 +       list_for_each_safe(ent, n, &finger_list)
14040 +       {
14041 +               f = list_entry(ent, struct osf_finger, flist);
14042 +               list_del(&f->flist);
14043 +               finger_free(f);
14044 +       }
14045 +       
14046 +       log("OS fingerprint matching module finished.\n");
14047 +}
14048 +
14049 +module_init(osf_init);
14050 +module_exit(osf_fini);
14051 +
14052 +MODULE_LICENSE("GPL");
14053 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
14054 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
14055 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6/net/ipv4/netfilter/ipt_owner.c
14056 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_owner.c      2004-05-10 04:33:20.000000000 +0200
14057 +++ linux-2.6.6/net/ipv4/netfilter/ipt_owner.c  2004-05-18 12:39:47.000000000 +0200
14058 @@ -6,12 +6,19 @@
14059   * This program is free software; you can redistribute it and/or modify
14060   * it under the terms of the GNU General Public License version 2 as
14061   * published by the Free Software Foundation.
14062 + *
14063 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
14064   */
14065  
14066  #include <linux/module.h>
14067  #include <linux/skbuff.h>
14068  #include <linux/file.h>
14069 +#include <linux/ip.h>
14070 +#include <linux/tcp.h>
14071 +#include <linux/udp.h>
14072  #include <net/sock.h>
14073 +#include <net/tcp.h>
14074 +#include <net/udp.h>
14075  
14076  #include <linux/netfilter_ipv4/ipt_owner.h>
14077  #include <linux/netfilter_ipv4/ip_tables.h>
14078 @@ -21,7 +28,7 @@
14079  MODULE_DESCRIPTION("iptables owner match");
14080  
14081  static int
14082 -match_comm(const struct sk_buff *skb, const char *comm)
14083 +match_comm(const struct sock *sk, const char *comm)
14084  {
14085         struct task_struct *g, *p;
14086         struct files_struct *files;
14087 @@ -38,7 +45,7 @@
14088                         spin_lock(&files->file_lock);
14089                         for (i=0; i < files->max_fds; i++) {
14090                                 if (fcheck_files(files, i) ==
14091 -                                   skb->sk->sk_socket->file) {
14092 +                                   sk->sk_socket->file) {
14093                                         spin_unlock(&files->file_lock);
14094                                         task_unlock(p);
14095                                         read_unlock(&tasklist_lock);
14096 @@ -54,7 +61,7 @@
14097  }
14098  
14099  static int
14100 -match_pid(const struct sk_buff *skb, pid_t pid)
14101 +match_pid(const struct sock *sk, pid_t pid)
14102  {
14103         struct task_struct *p;
14104         struct files_struct *files;
14105 @@ -70,7 +77,7 @@
14106                 spin_lock(&files->file_lock);
14107                 for (i=0; i < files->max_fds; i++) {
14108                         if (fcheck_files(files, i) ==
14109 -                           skb->sk->sk_socket->file) {
14110 +                           sk->sk_socket->file) {
14111                                 spin_unlock(&files->file_lock);
14112                                 task_unlock(p);
14113                                 read_unlock(&tasklist_lock);
14114 @@ -86,10 +93,10 @@
14115  }
14116  
14117  static int
14118 -match_sid(const struct sk_buff *skb, pid_t sid)
14119 +match_sid(const struct sock *sk, pid_t sid)
14120  {
14121         struct task_struct *g, *p;
14122 -       struct file *file = skb->sk->sk_socket->file;
14123 +       struct file *file = sk->sk_socket->file;
14124         int i, found=0;
14125  
14126         read_lock(&tasklist_lock);
14127 @@ -129,41 +136,71 @@
14128        int *hotdrop)
14129  {
14130         const struct ipt_owner_info *info = matchinfo;
14131 +       struct iphdr *iph = skb->nh.iph;
14132 +       struct sock *sk = NULL;
14133 +       int ret = 0;
14134 +
14135 +       if (out) {
14136 +               sk = skb->sk;
14137 +       } else {
14138 +               if (iph->protocol == IPPROTO_TCP) {
14139 +                       struct tcphdr *tcph =
14140 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
14141 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
14142 +                                          iph->daddr, tcph->dest,
14143 +                                          skb->dev->ifindex);
14144 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
14145 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
14146 +                               return ret;
14147 +                       }
14148 +               } else if (iph->protocol == IPPROTO_UDP) {
14149 +                       struct udphdr *udph =
14150 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
14151 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
14152 +                                          udph->dest, skb->dev->ifindex);
14153 +               }
14154 +       }
14155  
14156 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
14157 -               return 0;
14158 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
14159 +               goto out;
14160  
14161         if(info->match & IPT_OWNER_UID) {
14162 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
14163 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
14164                     !!(info->invert & IPT_OWNER_UID))
14165 -                       return 0;
14166 +                       goto out;
14167         }
14168  
14169         if(info->match & IPT_OWNER_GID) {
14170 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
14171 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
14172                     !!(info->invert & IPT_OWNER_GID))
14173 -                       return 0;
14174 +                       goto out;
14175         }
14176  
14177         if(info->match & IPT_OWNER_PID) {
14178 -               if (!match_pid(skb, info->pid) ^
14179 +               if (!match_pid(sk, info->pid) ^
14180                     !!(info->invert & IPT_OWNER_PID))
14181 -                       return 0;
14182 +                       goto out;
14183         }
14184  
14185         if(info->match & IPT_OWNER_SID) {
14186 -               if (!match_sid(skb, info->sid) ^
14187 +               if (!match_sid(sk, info->sid) ^
14188                     !!(info->invert & IPT_OWNER_SID))
14189 -                       return 0;
14190 +                       goto out;
14191         }
14192  
14193         if(info->match & IPT_OWNER_COMM) {
14194 -               if (!match_comm(skb, info->comm) ^
14195 +               if (!match_comm(sk, info->comm) ^
14196                     !!(info->invert & IPT_OWNER_COMM))
14197 -                       return 0;
14198 +                       goto out;
14199         }
14200  
14201 -       return 1;
14202 +       ret = 1;
14203 +
14204 +out:
14205 +       if (in && sk)
14206 +               sock_put(sk);
14207 +
14208 +       return ret;
14209  }
14210  
14211  static int
14212 @@ -173,11 +210,19 @@
14213             unsigned int matchsize,
14214             unsigned int hook_mask)
14215  {
14216 -        if (hook_mask
14217 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
14218 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
14219 -                return 0;
14220 -        }
14221 +       if (hook_mask
14222 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
14223 +           (1 << NF_IP_LOCAL_IN))) {
14224 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
14225 +                      "or POST_ROUTING.\n");
14226 +               return 0;
14227 +       }
14228 +
14229 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
14230 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
14231 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
14232 +               return 0;
14233 +       }
14234  
14235         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
14236                 printk("Matchsize %u != %Zu\n", matchsize,
14237 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6/net/ipv4/netfilter/ipt_policy.c
14238 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_policy.c     1970-01-01 01:00:00.000000000 +0100
14239 +++ linux-2.6.6/net/ipv4/netfilter/ipt_policy.c 2004-05-18 12:39:55.000000000 +0200
14240 @@ -0,0 +1,176 @@
14241 +/* IP tables module for matching IPsec policy
14242 + *
14243 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
14244 + *
14245 + * This program is free software; you can redistribute it and/or modify
14246 + * it under the terms of the GNU General Public License version 2 as
14247 + * published by the Free Software Foundation.
14248 + */
14249 +
14250 +#include <linux/kernel.h>
14251 +#include <linux/config.h>
14252 +#include <linux/module.h>
14253 +#include <linux/skbuff.h>
14254 +#include <linux/init.h>
14255 +#include <net/xfrm.h>
14256 +
14257 +#include <linux/netfilter_ipv4.h>
14258 +#include <linux/netfilter_ipv4/ipt_policy.h>
14259 +#include <linux/netfilter_ipv4/ip_tables.h>
14260 +
14261 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
14262 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
14263 +MODULE_LICENSE("GPL");
14264 +
14265 +
14266 +static inline int
14267 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
14268 +{
14269 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
14270 +
14271 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
14272 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
14273 +           MISMATCH(proto, x->id.proto) ||
14274 +           MISMATCH(mode, x->props.mode) ||
14275 +           MISMATCH(spi, x->id.spi) ||
14276 +           MISMATCH(reqid, x->props.reqid))
14277 +               return 0;
14278 +       return 1;
14279 +}
14280 +
14281 +static int
14282 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
14283 +{
14284 +       const struct ipt_policy_elem *e;
14285 +       struct sec_path *sp = skb->sp;
14286 +       int strict = info->flags & POLICY_MATCH_STRICT;
14287 +       int i, pos;
14288 +
14289 +       if (sp == NULL)
14290 +               return -1;
14291 +       if (strict && info->len != sp->len)
14292 +               return 0;
14293 +
14294 +       for (i = sp->len - 1; i >= 0; i--) {
14295 +               pos = strict ? i - sp->len + 1 : 0;
14296 +               if (pos >= info->len)
14297 +                       return 0;
14298 +               e = &info->pol[pos];
14299 +
14300 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
14301 +                       if (!strict)
14302 +                               return 1;
14303 +               } else if (strict)
14304 +                       return 0;
14305 +       }
14306 +
14307 +       return strict ? 1 : 0;
14308 +}
14309 +
14310 +static int
14311 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
14312 +{
14313 +       const struct ipt_policy_elem *e;
14314 +       struct dst_entry *dst = skb->dst;
14315 +       int strict = info->flags & POLICY_MATCH_STRICT;
14316 +       int i, pos;
14317 +
14318 +       if (dst->xfrm == NULL)
14319 +               return -1;
14320 +
14321 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
14322 +               pos = strict ? i : 0;
14323 +               if (pos >= info->len)
14324 +                       return 0;
14325 +               e = &info->pol[pos];
14326 +
14327 +               if (match_xfrm_state(dst->xfrm, e)) {
14328 +                       if (!strict)
14329 +                               return 1;
14330 +               } else if (strict)
14331 +                       return 0;
14332 +       }
14333 +
14334 +       return strict ? 1 : 0;
14335 +}
14336 +
14337 +static int match(const struct sk_buff *skb,
14338 +                 const struct net_device *in,
14339 +                 const struct net_device *out,
14340 +                 const void *matchinfo, int offset, int *hotdrop)
14341 +{
14342 +       const struct ipt_policy_info *info = matchinfo;
14343 +       int ret;
14344 +
14345 +       if (info->flags & POLICY_MATCH_IN)
14346 +               ret = match_policy_in(skb, info);
14347 +       else
14348 +               ret = match_policy_out(skb, info);
14349 +
14350 +       if (ret < 0) {
14351 +               if (info->flags & POLICY_MATCH_NONE)
14352 +                       ret = 1;
14353 +               else
14354 +                       ret = 0;
14355 +       } else if (info->flags & POLICY_MATCH_NONE)
14356 +               ret = 0;
14357 +
14358 +       return ret;
14359 +}
14360 +
14361 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
14362 +                      void *matchinfo, unsigned int matchsize,
14363 +                      unsigned int hook_mask)
14364 +{
14365 +       struct ipt_policy_info *info = matchinfo;
14366 +
14367 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
14368 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
14369 +                      matchsize, IPT_ALIGN(sizeof(*info)));
14370 +               return 0;
14371 +       }
14372 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
14373 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
14374 +                               "outgoing policy selected\n");
14375 +               return 0;
14376 +       }
14377 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
14378 +           && info->flags & POLICY_MATCH_OUT) {
14379 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
14380 +                               "PRE_ROUTING and INPUT\n");
14381 +               return 0;
14382 +       }
14383 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
14384 +           && info->flags & POLICY_MATCH_IN) {
14385 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
14386 +                               "POST_ROUTING and OUTPUT\n");
14387 +               return 0;
14388 +       }
14389 +       if (info->len > POLICY_MAX_ELEM) {
14390 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
14391 +               return 0;
14392 +       }
14393 +
14394 +       return 1;
14395 +}
14396 +
14397 +static struct ipt_match policy_match =
14398 +{
14399 +       .name           = "policy",
14400 +       .match          = match,
14401 +       .checkentry     = checkentry,
14402 +       .me             = THIS_MODULE,
14403 +};
14404 +
14405 +static int __init init(void)
14406 +{
14407 +       return ipt_register_match(&policy_match);
14408 +}
14409 +
14410 +static void __exit fini(void)
14411 +{
14412 +       ipt_unregister_match(&policy_match);
14413 +}
14414 +
14415 +module_init(init);
14416 +module_exit(fini);
14417 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.6/net/ipv4/netfilter/ipt_pool.c
14418 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_pool.c       1970-01-01 01:00:00.000000000 +0100
14419 +++ linux-2.6.6/net/ipv4/netfilter/ipt_pool.c   2004-05-18 12:36:48.000000000 +0200
14420 @@ -0,0 +1,71 @@
14421 +/* Kernel module to match an IP address pool. */
14422 +
14423 +#include <linux/module.h>
14424 +#include <linux/ip.h>
14425 +#include <linux/skbuff.h>
14426 +
14427 +#include <linux/netfilter_ipv4/ip_tables.h>
14428 +#include <linux/netfilter_ipv4/ip_pool.h>
14429 +#include <linux/netfilter_ipv4/ipt_pool.h>
14430 +
14431 +static inline int match_pool(
14432 +       ip_pool_t index,
14433 +       __u32 addr,
14434 +       int inv
14435 +) {
14436 +       if (ip_pool_match(index, ntohl(addr)))
14437 +               inv = !inv;
14438 +       return inv;
14439 +}
14440 +
14441 +static int match(
14442 +       const struct sk_buff *skb,
14443 +       const struct net_device *in,
14444 +       const struct net_device *out,
14445 +       const void *matchinfo,
14446 +       int offset,
14447 +       const void *hdr,
14448 +       u_int16_t datalen,
14449 +       int *hotdrop
14450 +) {
14451 +       const struct ipt_pool_info *info = matchinfo;
14452 +       const struct iphdr *iph = skb->nh.iph;
14453 +
14454 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
14455 +                                               info->flags&IPT_POOL_INV_SRC))
14456 +               return 0;
14457 +
14458 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
14459 +                                               info->flags&IPT_POOL_INV_DST))
14460 +               return 0;
14461 +
14462 +       return 1;
14463 +}
14464 +
14465 +static int checkentry(
14466 +       const char *tablename,
14467 +       const struct ipt_ip *ip,
14468 +       void *matchinfo,
14469 +       unsigned int matchsize,
14470 +       unsigned int hook_mask
14471 +) {
14472 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
14473 +               return 0;
14474 +       return 1;
14475 +}
14476 +
14477 +static struct ipt_match pool_match
14478 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
14479 +
14480 +static int __init init(void)
14481 +{
14482 +       return ipt_register_match(&pool_match);
14483 +}
14484 +
14485 +static void __exit fini(void)
14486 +{
14487 +       ipt_unregister_match(&pool_match);
14488 +}
14489 +
14490 +module_init(init);
14491 +module_exit(fini);
14492 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.6/net/ipv4/netfilter/ipt_psd.c
14493 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_psd.c        1970-01-01 01:00:00.000000000 +0100
14494 +++ linux-2.6.6/net/ipv4/netfilter/ipt_psd.c    2004-05-18 12:36:55.000000000 +0200
14495 @@ -0,0 +1,358 @@
14496 +/*
14497 +  This is a module which is used for PSD (portscan detection)
14498 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
14499 +  and LOG target module.
14500 +
14501 +  Copyright (C) 2000,2001 astaro AG
14502 +
14503 +  This file is distributed under the terms of the GNU General Public
14504 +  License (GPL). Copies of the GPL can be obtained from:
14505 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
14506 +
14507 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
14508 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
14509 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
14510 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
14511 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
14512 +  2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
14513 +*/
14514 +
14515 +#include <linux/module.h>
14516 +#include <linux/skbuff.h>
14517 +#include <linux/ip.h>
14518 +#include <net/tcp.h>
14519 +#include <linux/spinlock.h>
14520 +#include <linux/netfilter_ipv4/ip_tables.h>
14521 +#include <linux/netfilter_ipv4/ipt_psd.h>
14522 +
14523 +#if 0
14524 +#define DEBUGP printk
14525 +#else
14526 +#define DEBUGP(format, args...)
14527 +#endif
14528 +
14529 +MODULE_LICENSE("GPL");
14530 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
14531 +
14532 +#define HF_DADDR_CHANGING   0x01
14533 +#define HF_SPORT_CHANGING   0x02
14534 +#define HF_TOS_CHANGING            0x04
14535 +#define HF_TTL_CHANGING            0x08
14536 +
14537 +/*
14538 + * Information we keep per each target port
14539 + */
14540 +struct port {
14541 +       u_int16_t number;      /* port number */
14542 +       u_int8_t proto;        /* protocol number */
14543 +       u_int8_t and_flags;    /* tcp ANDed flags */
14544 +       u_int8_t or_flags;     /* tcp ORed flags */
14545 +};
14546 +
14547 +/*
14548 + * Information we keep per each source address.
14549 + */
14550 +struct host {
14551 +       struct host *next;              /* Next entry with the same hash */
14552 +       clock_t timestamp;              /* Last update time */
14553 +       struct in_addr src_addr;        /* Source address */
14554 +       struct in_addr dest_addr;       /* Destination address */
14555 +       unsigned short src_port;        /* Source port */
14556 +       int count;                      /* Number of ports in the list */
14557 +       int weight;                     /* Total weight of ports in the list */
14558 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
14559 +       unsigned char tos;              /* TOS */
14560 +       unsigned char ttl;              /* TTL */
14561 +       unsigned char flags;            /* HF_ flags bitmask */
14562 +};
14563 +
14564 +/*
14565 + * State information.
14566 + */
14567 +static struct {
14568 +       spinlock_t lock;
14569 +       struct host list[LIST_SIZE];    /* List of source addresses */
14570 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
14571 +       int index;                      /* Oldest entry to be replaced */
14572 +} state;
14573 +
14574 +/*
14575 + * Convert an IP address into a hash table index.
14576 + */
14577 +static inline int hashfunc(struct in_addr addr)
14578 +{
14579 +       unsigned int value;
14580 +       int hash;
14581 +
14582 +       value = addr.s_addr;
14583 +       hash = 0;
14584 +       do {
14585 +               hash ^= value;
14586 +       } while ((value >>= HASH_LOG));
14587 +
14588 +       return hash & (HASH_SIZE - 1);
14589 +}
14590 +
14591 +static int
14592 +ipt_psd_match(const struct sk_buff *pskb,
14593 +             const struct net_device *in,
14594 +             const struct net_device *out,
14595 +             const void *matchinfo,
14596 +             int offset,
14597 +             int *hotdrop)
14598 +{
14599 +       struct iphdr *ip_hdr;
14600 +       struct tcphdr *tcp_hdr;
14601 +       struct in_addr addr;
14602 +       u_int16_t src_port,dest_port;
14603 +       u_int8_t tcp_flags, proto;
14604 +       clock_t now;
14605 +       struct host *curr, *last, **head;
14606 +       int hash, index, count;
14607 +
14608 +       /* Parameters from userspace */
14609 +       const struct ipt_psd_info *psdinfo = matchinfo;
14610 +
14611 +       /* IP header */
14612 +       ip_hdr = pskb->nh.iph;
14613 +
14614 +       /* Sanity check */
14615 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
14616 +               DEBUGP("PSD: sanity check failed\n");
14617 +               return 0;
14618 +       }
14619 +
14620 +       /* TCP or UDP ? */
14621 +       proto = ip_hdr->protocol;
14622 +
14623 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
14624 +               DEBUGP("PSD: protocol not supported\n");
14625 +               return 0;
14626 +       }
14627 +
14628 +       /* Get the source address, source & destination ports, and TCP flags */
14629 +
14630 +       addr.s_addr = ip_hdr->saddr;
14631 +
14632 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
14633 +
14634 +       /* Yep, it´s dirty */
14635 +       src_port = tcp_hdr->source;
14636 +       dest_port = tcp_hdr->dest;
14637 +
14638 +       if (proto == IPPROTO_TCP) {
14639 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
14640 +       }
14641 +       else {
14642 +               tcp_flags = 0x00;
14643 +       }
14644 +
14645 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
14646 +        * them spoof us. [DHCP needs this feature - HW] */
14647 +       if (!addr.s_addr) {
14648 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
14649 +               return 0;
14650 +       }
14651 +
14652 +       /* Use jiffies here not to depend on someone setting the time while we're
14653 +        * running; we need to be careful with possible return value overflows. */
14654 +       now = jiffies;
14655 +
14656 +       spin_lock(&state.lock);
14657 +
14658 +       /* Do we know this source address already? */
14659 +       count = 0;
14660 +       last = NULL;
14661 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
14662 +               do {
14663 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
14664 +                       count++;
14665 +                       if (curr->next) last = curr;
14666 +               } while ((curr = curr->next));
14667 +
14668 +       if (curr) {
14669 +
14670 +               /* We know this address, and the entry isn't too old. Update it. */
14671 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
14672 +                   time_after_eq(now, curr->timestamp)) {
14673 +
14674 +                       /* Just update the appropriate list entry if we've seen this port already */
14675 +                       for (index = 0; index < curr->count; index++) {
14676 +                               if (curr->ports[index].number == dest_port) {
14677 +                                       curr->ports[index].proto = proto;
14678 +                                       curr->ports[index].and_flags &= tcp_flags;
14679 +                                       curr->ports[index].or_flags |= tcp_flags;
14680 +                                       goto out_no_match;
14681 +                               }
14682 +                       }
14683 +
14684 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
14685 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
14686 +                               goto out_no_match;
14687 +
14688 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
14689 +                       curr->timestamp = now;
14690 +
14691 +                       /* Logged this scan already? Then drop the packet. */
14692 +                       if (curr->weight >= psdinfo->weight_threshold)
14693 +                               goto out_match;
14694 +
14695 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
14696 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
14697 +                               curr->flags |= HF_DADDR_CHANGING;
14698 +                       if (curr->src_port != src_port)
14699 +                               curr->flags |= HF_SPORT_CHANGING;
14700 +                       if (curr->tos != ip_hdr->tos)
14701 +                               curr->flags |= HF_TOS_CHANGING;
14702 +                       if (curr->ttl != ip_hdr->ttl)
14703 +                               curr->flags |= HF_TTL_CHANGING;
14704 +
14705 +                       /* Update the total weight */
14706 +                       curr->weight += (ntohs(dest_port) < 1024) ?
14707 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14708 +
14709 +                       /* Got enough destination ports to decide that this is a scan? */
14710 +                       /* Then log it and drop the packet. */
14711 +                       if (curr->weight >= psdinfo->weight_threshold)
14712 +                               goto out_match;
14713 +
14714 +                       /* Remember the new port */
14715 +                       if (curr->count < SCAN_MAX_COUNT) {
14716 +                               curr->ports[curr->count].number = dest_port;
14717 +                               curr->ports[curr->count].proto = proto;
14718 +                               curr->ports[curr->count].and_flags = tcp_flags;
14719 +                               curr->ports[curr->count].or_flags = tcp_flags;
14720 +                               curr->count++;
14721 +                       }
14722 +
14723 +                       goto out_no_match;
14724 +               }
14725 +
14726 +               /* We know this address, but the entry is outdated. Mark it unused, and
14727 +                * remove from the hash table. We'll allocate a new entry instead since
14728 +                * this one might get re-used too soon. */
14729 +               curr->src_addr.s_addr = 0;
14730 +               if (last)
14731 +                       last->next = last->next->next;
14732 +               else if (*head)
14733 +                       *head = (*head)->next;
14734 +               last = NULL;
14735 +       }
14736 +
14737 +       /* We don't need an ACK from a new source address */
14738 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
14739 +               goto out_no_match;
14740 +
14741 +       /* Got too many source addresses with the same hash value? Then remove the
14742 +        * oldest one from the hash table, so that they can't take too much of our
14743 +        * CPU time even with carefully chosen spoofed IP addresses. */
14744 +       if (count >= HASH_MAX && last) last->next = NULL;
14745 +
14746 +       /* We're going to re-use the oldest list entry, so remove it from the hash
14747 +        * table first (if it is really already in use, and isn't removed from the
14748 +        * hash table already because of the HASH_MAX check above). */
14749 +
14750 +       /* First, find it */
14751 +       if (state.list[state.index].src_addr.s_addr)
14752 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
14753 +       else
14754 +               head = &last;
14755 +       last = NULL;
14756 +       if ((curr = *head))
14757 +       do {
14758 +               if (curr == &state.list[state.index]) break;
14759 +               last = curr;
14760 +       } while ((curr = curr->next));
14761 +
14762 +       /* Then, remove it */
14763 +       if (curr) {
14764 +               if (last)
14765 +                       last->next = last->next->next;
14766 +               else if (*head)
14767 +                       *head = (*head)->next;
14768 +       }
14769 +
14770 +       /* Get our list entry */
14771 +       curr = &state.list[state.index++];
14772 +       if (state.index >= LIST_SIZE) state.index = 0;
14773 +
14774 +       /* Link it into the hash table */
14775 +       head = &state.hash[hash];
14776 +       curr->next = *head;
14777 +       *head = curr;
14778 +
14779 +       /* And fill in the fields */
14780 +       curr->timestamp = now;
14781 +       curr->src_addr = addr;
14782 +       curr->dest_addr.s_addr = ip_hdr->daddr;
14783 +       curr->src_port = src_port;
14784 +       curr->count = 1;
14785 +       curr->weight = (ntohs(dest_port) < 1024) ?
14786 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14787 +       curr->ports[0].number = dest_port;
14788 +       curr->ports[0].proto = proto;
14789 +       curr->ports[0].and_flags = tcp_flags;
14790 +       curr->ports[0].or_flags = tcp_flags;
14791 +       curr->tos = ip_hdr->tos;
14792 +       curr->ttl = ip_hdr->ttl;
14793 +
14794 +out_no_match:
14795 +       spin_unlock(&state.lock);
14796 +       return 0;
14797 +
14798 +out_match:
14799 +       spin_unlock(&state.lock);
14800 +       return 1;
14801 +}
14802 +
14803 +static int ipt_psd_checkentry(const char *tablename,
14804 +                             const struct ipt_ip *e,
14805 +                             void *matchinfo,
14806 +                             unsigned int matchsize,
14807 +                             unsigned int hook_mask)
14808 +{
14809 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
14810 +
14811 +       /* we accept TCP only */
14812 +/*     if (e->ip.proto != IPPROTO_TCP) { */
14813 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
14814 +/*             return 0; */
14815 +/*     } */
14816 +
14817 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
14818 +               DEBUGP("PSD: matchsize %u != %u\n",
14819 +                      matchsize,
14820 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
14821 +               return 0;
14822 +       }
14823 +
14824 +       return 1;
14825 +}
14826 +
14827 +static struct ipt_match ipt_psd_reg = {
14828 +       .name = "psd",
14829 +       .match = ipt_psd_match,
14830 +       .checkentry = ipt_psd_checkentry,
14831 +       .me = THIS_MODULE };
14832 +
14833 +static int __init init(void)
14834 +{
14835 +       if (ipt_register_match(&ipt_psd_reg))
14836 +               return -EINVAL;
14837 +
14838 +       memset(&state, 0, sizeof(state));
14839 +
14840 +       spin_lock_init(&(state.lock));
14841 +
14842 +       printk("netfilter PSD loaded - (c) astaro AG\n");
14843 +       return 0;
14844 +}
14845 +
14846 +static void __exit fini(void)
14847 +{
14848 +       ipt_unregister_match(&ipt_psd_reg);
14849 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
14850 +}
14851 +
14852 +module_init(init);
14853 +module_exit(fini);
14854 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.6/net/ipv4/netfilter/ipt_quota.c
14855 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_quota.c      1970-01-01 01:00:00.000000000 +0100
14856 +++ linux-2.6.6/net/ipv4/netfilter/ipt_quota.c  2004-05-18 12:36:56.000000000 +0200
14857 @@ -0,0 +1,91 @@
14858 +/* 
14859 + * netfilter module to enforce network quotas
14860 + *
14861 + * Sam Johnston <samj@samj.net>
14862 + */
14863 +#include <linux/module.h>
14864 +#include <linux/skbuff.h>
14865 +#include <linux/spinlock.h>
14866 +#include <linux/interrupt.h>
14867 +
14868 +#include <linux/netfilter_ipv4/ip_tables.h>
14869 +#include <linux/netfilter_ipv4/ipt_quota.h>
14870 +
14871 +MODULE_LICENSE("GPL");
14872 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
14873 +
14874 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
14875 +
14876 +static int
14877 +match(const struct sk_buff *skb,
14878 +      const struct net_device *in,
14879 +      const struct net_device *out,
14880 +      const void *matchinfo,
14881 +      int offset, int *hotdrop)
14882 +{
14883 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
14884 +       unsigned int datalen;
14885 +
14886 +       if (skb->len < sizeof(struct iphdr))
14887 +               return NF_ACCEPT;
14888 +       
14889 +       datalen = skb->len - skb->nh.iph->ihl*4;
14890 +
14891 +        spin_lock_bh(&quota_lock);
14892 +
14893 +        if (q->quota >= datalen) {
14894 +                /* we can afford this one */
14895 +                q->quota -= datalen;
14896 +                spin_unlock_bh(&quota_lock);
14897 +
14898 +#ifdef DEBUG_IPT_QUOTA
14899 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
14900 +#endif
14901 +                return 1;
14902 +        }
14903 +
14904 +        /* so we do not allow even small packets from now on */
14905 +        q->quota = 0;
14906 +
14907 +#ifdef DEBUG_IPT_QUOTA
14908 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
14909 +#endif
14910 +
14911 +        spin_unlock_bh(&quota_lock);
14912 +        return 0;
14913 +}
14914 +
14915 +static int
14916 +checkentry(const char *tablename,
14917 +           const struct ipt_ip *ip,
14918 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
14919 +{
14920 +        /* TODO: spinlocks? sanity checks? */
14921 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
14922 +                return 0;
14923 +
14924 +        return 1;
14925 +}
14926 +
14927 +static struct ipt_match quota_match = {
14928 +       .name = "quota",
14929 +       .match = match,
14930 +       .checkentry = checkentry,
14931 +       .me = THIS_MODULE
14932 +};
14933 +
14934 +static int __init
14935 +init(void)
14936 +{
14937 +        return ipt_register_match(&quota_match);
14938 +}
14939 +
14940 +static void __exit
14941 +fini(void)
14942 +{
14943 +        ipt_unregister_match(&quota_match);
14944 +}
14945 +
14946 +module_init(init);
14947 +module_exit(fini);
14948 +
14949 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_random.c linux-2.6.6/net/ipv4/netfilter/ipt_random.c
14950 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_random.c     1970-01-01 01:00:00.000000000 +0100
14951 +++ linux-2.6.6/net/ipv4/netfilter/ipt_random.c 2004-05-18 12:36:59.000000000 +0200
14952 @@ -0,0 +1,96 @@
14953 +/*
14954 +  This is a module which is used for a "random" match support.
14955 +  This file is distributed under the terms of the GNU General Public
14956 +  License (GPL). Copies of the GPL can be obtained from:
14957 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
14958 +
14959 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14960 +*/
14961 +
14962 +#include <linux/module.h>
14963 +#include <linux/skbuff.h>
14964 +#include <linux/ip.h>
14965 +#include <linux/random.h>
14966 +#include <net/tcp.h>
14967 +#include <linux/spinlock.h>
14968 +#include <linux/netfilter_ipv4/ip_tables.h>
14969 +#include <linux/netfilter_ipv4/ipt_random.h>
14970 +
14971 +MODULE_LICENSE("GPL");
14972 +
14973 +static int
14974 +ipt_rand_match(const struct sk_buff *pskb,
14975 +              const struct net_device *in,
14976 +              const struct net_device *out,
14977 +              const void *matchinfo,
14978 +              int offset,
14979 +              const void *hdr,
14980 +              u_int16_t datalen,
14981 +              int *hotdrop)
14982 +{
14983 +       /* Parameters from userspace */
14984 +       const struct ipt_rand_info *info = matchinfo;
14985 +       u_int8_t random_number;
14986 +
14987 +       /* get 1 random number from the kernel random number generation routine */
14988 +       get_random_bytes((void *)(&random_number), 1);
14989 +
14990 +       /* Do we match ? */
14991 +       if (random_number <= info->average)
14992 +               return 1;
14993 +       else
14994 +               return 0;
14995 +}
14996 +
14997 +static int
14998 +ipt_rand_checkentry(const char *tablename,
14999 +                  const struct ipt_ip *e,
15000 +                  void *matchinfo,
15001 +                  unsigned int matchsize,
15002 +                  unsigned int hook_mask)
15003 +{
15004 +       /* Parameters from userspace */
15005 +       const struct ipt_rand_info *info = matchinfo;
15006 +
15007 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
15008 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
15009 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
15010 +               return 0;
15011 +       }
15012 +
15013 +       /* must be  1 <= average % <= 99 */
15014 +       /* 1  x 2.55 = 2   */
15015 +       /* 99 x 2.55 = 252 */
15016 +       if ((info->average < 2) || (info->average > 252)) {
15017 +               printk("ipt_random:  invalid average %u\n", info->average);
15018 +               return 0;
15019 +       }
15020 +
15021 +       return 1;
15022 +}
15023 +
15024 +static struct ipt_match ipt_rand_reg = { 
15025 +       {NULL, NULL},
15026 +       "random",
15027 +       ipt_rand_match,
15028 +       ipt_rand_checkentry,
15029 +       NULL,
15030 +       THIS_MODULE };
15031 +
15032 +static int __init init(void)
15033 +{
15034 +       if (ipt_register_match(&ipt_rand_reg))
15035 +               return -EINVAL;
15036 +
15037 +       printk("ipt_random match loaded\n");
15038 +       return 0;
15039 +}
15040 +
15041 +static void __exit fini(void)
15042 +{
15043 +       ipt_unregister_match(&ipt_rand_reg);
15044 +       printk("ipt_random match unloaded\n");
15045 +}
15046 +
15047 +module_init(init);
15048 +module_exit(fini);
15049 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.6/net/ipv4/netfilter/ipt_realm.c
15050 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_realm.c      1970-01-01 01:00:00.000000000 +0100
15051 +++ linux-2.6.6/net/ipv4/netfilter/ipt_realm.c  2004-05-18 12:37:05.000000000 +0200
15052 @@ -0,0 +1,78 @@
15053 +/* IP tables module for matching the routing realm
15054 + *
15055 + * $Id$
15056 + *
15057 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
15058 + *
15059 + * This program is free software; you can redistribute it and/or modify
15060 + * it under the terms of the GNU General Public License version 2 as
15061 + * published by the Free Software Foundation.
15062 + */
15063 +
15064 +#include <linux/module.h>
15065 +#include <linux/skbuff.h>
15066 +#include <linux/netdevice.h>
15067 +#include <net/route.h>
15068 +
15069 +#include <linux/netfilter_ipv4/ipt_realm.h>
15070 +#include <linux/netfilter_ipv4/ip_tables.h>
15071 +
15072 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
15073 +MODULE_LICENSE("GPL");
15074 +
15075 +static int
15076 +match(const struct sk_buff *skb,
15077 +      const struct net_device *in,
15078 +      const struct net_device *out,
15079 +      const void *matchinfo,
15080 +      int offset,
15081 +      int *hotdrop)
15082 +{
15083 +       const struct ipt_realm_info *info = matchinfo;
15084 +       struct dst_entry *dst = skb->dst;
15085 +    
15086 +       if (!dst)
15087 +               return 0;
15088 +
15089 +       return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
15090 +}
15091 +
15092 +static int check(const char *tablename,
15093 +                 const struct ipt_ip *ip,
15094 +                 void *matchinfo,
15095 +                 unsigned int matchsize,
15096 +                 unsigned int hook_mask)
15097 +{
15098 +       if (hook_mask
15099 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
15100 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
15101 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
15102 +                      "LOCAL_IN or FORWARD.\n");
15103 +               return 0;
15104 +       }
15105 +
15106 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
15107 +               return 0;
15108 +
15109 +       return 1;
15110 +}
15111 +
15112 +static struct ipt_match realm_match = {
15113 +       .name = "realm",
15114 +       .match = match, 
15115 +       .checkentry = check,
15116 +       .me = THIS_MODULE
15117 +};
15118 +
15119 +static int __init init(void)
15120 +{
15121 +       return ipt_register_match(&realm_match);
15122 +}
15123 +
15124 +static void __exit fini(void)
15125 +{
15126 +       ipt_unregister_match(&realm_match);
15127 +}
15128 +
15129 +module_init(init);
15130 +module_exit(fini);
15131 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.6/net/ipv4/netfilter/ipt_sctp.c
15132 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_sctp.c       1970-01-01 01:00:00.000000000 +0100
15133 +++ linux-2.6.6/net/ipv4/netfilter/ipt_sctp.c   2004-05-18 12:37:09.000000000 +0200
15134 @@ -0,0 +1,199 @@
15135 +#include <linux/module.h>
15136 +#include <linux/skbuff.h>
15137 +#include <net/ip.h>
15138 +#include <linux/sctp.h>
15139 +
15140 +#include <linux/netfilter_ipv4/ip_tables.h>
15141 +#include <linux/netfilter_ipv4/ipt_sctp.h>
15142 +
15143 +#if 0
15144 +#define duprintf(format, args...) printk(format , ## args)
15145 +#else
15146 +#define duprintf(format, args...)
15147 +#endif
15148 +
15149 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
15150 +                                             || (!!((invflag) & (option)) ^ (cond)))
15151 +
15152 +static int
15153 +match_flags(const struct ipt_sctp_flag_info *flag_info,
15154 +           const int flag_count,
15155 +           u_int8_t chunktype,
15156 +           u_int8_t chunkflags)
15157 +{
15158 +       int i;
15159 +
15160 +       for (i = 0; i < flag_count; i++) {
15161 +               if (flag_info[i].chunktype == chunktype) {
15162 +                       return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
15163 +               }
15164 +       }
15165 +
15166 +       return 1;
15167 +}
15168 +
15169 +static int
15170 +match_packet(const struct sk_buff *skb,
15171 +            const u_int32_t *chunkmap,
15172 +            int chunk_match_type,
15173 +            const struct ipt_sctp_flag_info *flag_info,
15174 +            const int flag_count,
15175 +            int *hotdrop)
15176 +{
15177 +       int offset;
15178 +       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
15179 +       sctp_chunkhdr_t sch;
15180 +
15181 +       int i = 0;
15182 +
15183 +       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
15184 +               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
15185 +       }
15186 +
15187 +       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
15188 +       do {
15189 +               if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
15190 +                       duprintf("Dropping invalid SCTP packet.\n");
15191 +                       *hotdrop = 1;
15192 +                       return 0;
15193 +               }
15194 +
15195 +               duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
15196 +                               ++i, offset, sch.type, htons(sch.length), sch.flags);
15197 +
15198 +               offset += (htons(sch.length) + 3) & ~3;
15199 +
15200 +               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
15201 +
15202 +               if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
15203 +                       switch (chunk_match_type) {
15204 +                       case SCTP_CHUNK_MATCH_ANY:
15205 +                               if (match_flags(flag_info, flag_count, 
15206 +                                       sch.type, sch.flags)) {
15207 +                                       return 1;
15208 +                               }
15209 +                               break;
15210 +
15211 +                       case SCTP_CHUNK_MATCH_ALL:
15212 +                               if (match_flags(flag_info, flag_count, 
15213 +                                       sch.type, sch.flags)) {
15214 +                                       SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
15215 +                               }
15216 +                               break;
15217 +
15218 +                       case SCTP_CHUNK_MATCH_ONLY:
15219 +                               if (!match_flags(flag_info, flag_count, 
15220 +                                       sch.type, sch.flags)) {
15221 +                                       return 0;
15222 +                               }
15223 +                               break;
15224 +                       }
15225 +               } else {
15226 +                       switch (chunk_match_type) {
15227 +                       case SCTP_CHUNK_MATCH_ONLY:
15228 +                               return 0;
15229 +                       }
15230 +               }
15231 +       } while (offset < skb->len);
15232 +
15233 +       switch (chunk_match_type) {
15234 +       case SCTP_CHUNK_MATCH_ALL:
15235 +               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
15236 +       case SCTP_CHUNK_MATCH_ANY:
15237 +               return 0;
15238 +       case SCTP_CHUNK_MATCH_ONLY:
15239 +               return 1;
15240 +       }
15241 +
15242 +       /* This will never be reached, but required to stop compiler whine */
15243 +       return 0;
15244 +}
15245 +
15246 +static int
15247 +match(const struct sk_buff *skb,
15248 +      const struct net_device *in,
15249 +      const struct net_device *out,
15250 +      const void *matchinfo,
15251 +      int offset,
15252 +      int *hotdrop)
15253 +{
15254 +       const struct ipt_sctp_info *info;
15255 +       sctp_sctphdr_t sh;
15256 +
15257 +       info = (const struct ipt_sctp_info *)matchinfo;
15258 +
15259 +       if (offset) {
15260 +               duprintf("Dropping non-first fragment.. FIXME\n");
15261 +               return 0;
15262 +       }
15263 +       
15264 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
15265 +               duprintf("Dropping evil TCP offset=0 tinygram.\n");
15266 +               *hotdrop = 1;
15267 +               return 0;
15268 +               }
15269 +       duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
15270 +
15271 +       return  SCCHECK(((ntohs(sh.source) >= info->spts[0]) 
15272 +                       && (ntohs(sh.source) <= info->spts[1])), 
15273 +                       IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
15274 +               && SCCHECK(((ntohs(sh.dest) >= info->dpts[0]) 
15275 +                       && (ntohs(sh.dest) <= info->dpts[1])), 
15276 +                       IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
15277 +               && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
15278 +                                       info->flag_info, info->flag_count, 
15279 +                                       hotdrop),
15280 +                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
15281 +}
15282 +
15283 +static int
15284 +checkentry(const char *tablename,
15285 +          const struct ipt_ip *ip,
15286 +          void *matchinfo,
15287 +          unsigned int matchsize,
15288 +          unsigned int hook_mask)
15289 +{
15290 +       const struct ipt_sctp_info *info;
15291 +
15292 +       info = (const struct ipt_sctp_info *)matchinfo;
15293 +
15294 +       return ip->proto == IPPROTO_SCTP
15295 +               && !(ip->invflags & IPT_INV_PROTO)
15296 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
15297 +               && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
15298 +               && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
15299 +               && !(info->invflags & ~info->flags)
15300 +               && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
15301 +                       (info->chunk_match_type &
15302 +                               (SCTP_CHUNK_MATCH_ALL 
15303 +                               | SCTP_CHUNK_MATCH_ANY
15304 +                               | SCTP_CHUNK_MATCH_ONLY)));
15305 +}
15306 +
15307 +static struct ipt_match sctp_match = 
15308 +{ 
15309 +       .list = { NULL, NULL},
15310 +       .name = "sctp",
15311 +       .match = &match,
15312 +       .checkentry = &checkentry,
15313 +       .destroy = NULL,
15314 +       .me = THIS_MODULE
15315 +};
15316 +
15317 +static int __init init(void)
15318 +{
15319 +       return ipt_register_match(&sctp_match);
15320 +}
15321 +
15322 +static void __exit fini(void)
15323 +{
15324 +       ipt_unregister_match(&sctp_match);
15325 +}
15326 +
15327 +module_init(init);
15328 +module_exit(fini);
15329 +
15330 +MODULE_LICENSE("GPL");
15331 +MODULE_AUTHOR("Kiran Kumar Immidi");
15332 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
15333 +
15334 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6/net/ipv4/netfilter/ipt_string.c
15335 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_string.c     1970-01-01 01:00:00.000000000 +0100
15336 +++ linux-2.6.6/net/ipv4/netfilter/ipt_string.c 2004-05-18 12:40:41.000000000 +0200
15337 @@ -0,0 +1,218 @@
15338 +/* Kernel module to match a string into a packet.
15339 + *
15340 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
15341 + * 
15342 + * ChangeLog
15343 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
15344 + *             Fixed SMP re-entrancy problem using per-cpu data areas
15345 + *             for the skip/shift tables.
15346 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
15347 + *             Fixed kernel panic, due to overrunning boyer moore string
15348 + *             tables. Also slightly tweaked heuristic for deciding what
15349 + *             search algo to use.
15350 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
15351 + *             Implemented Boyer Moore Sublinear search algorithm
15352 + *             alongside the existing linear search based on memcmp().
15353 + *             Also a quick check to decide which method to use on a per
15354 + *             packet basis.
15355 + */
15356 +
15357 +#include <linux/smp.h>
15358 +#include <linux/module.h>
15359 +#include <linux/skbuff.h>
15360 +#include <linux/file.h>
15361 +#include <net/sock.h>
15362 +
15363 +#include <linux/netfilter_ipv4/ip_tables.h>
15364 +#include <linux/netfilter_ipv4/ipt_string.h>
15365 +
15366 +MODULE_LICENSE("GPL");
15367 +
15368 +struct string_per_cpu {
15369 +       int *skip;
15370 +       int *shift;
15371 +       int *len;
15372 +};
15373 +
15374 +struct string_per_cpu *bm_string_data=NULL;
15375 +
15376 +/* Boyer Moore Sublinear string search - VERY FAST */
15377 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
15378 +{
15379 +       int M1, right_end, sk, sh;  
15380 +       int ended, j, i;
15381 +
15382 +       int *skip, *shift, *len;
15383 +       
15384 +       /* use data suitable for this CPU */
15385 +       shift=bm_string_data[smp_processor_id()].shift;
15386 +       skip=bm_string_data[smp_processor_id()].skip;
15387 +       len=bm_string_data[smp_processor_id()].len;
15388 +       
15389 +       /* Setup skip/shift tables */
15390 +       M1 = right_end = needle_len-1;
15391 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
15392 +       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
15393 +
15394 +       for (i = 1; i < needle_len; i++) {   
15395 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
15396 +               len[i] = j;  
15397 +       }  
15398 +
15399 +       shift[0] = 1;  
15400 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
15401 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
15402 +       ended = 0;  
15403 +       
15404 +       for (i = 0; i < needle_len; i++) {  
15405 +               if (len[i] == M1 - i) ended = i;  
15406 +               if (ended) shift[i] = ended;  
15407 +       }  
15408 +
15409 +       /* Do the search*/  
15410 +       while (right_end < haystack_len)
15411 +       {
15412 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
15413 +               if (i == needle_len) {
15414 +                       return haystack+(right_end - M1);
15415 +               }
15416 +               
15417 +               sk = skip[haystack[right_end - i]];  
15418 +               sh = shift[i];
15419 +               right_end = max(right_end - i + sk, right_end + sh);  
15420 +       }
15421 +
15422 +       return NULL;
15423 +}  
15424 +
15425 +/* Linear string search based on memcmp() */
15426 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
15427 +{
15428 +       char *k = haystack + (haystack_len-needle_len);
15429 +       char *t = haystack;
15430 +       
15431 +       while ( t <= k ) {
15432 +               if (memcmp(t, needle, needle_len) == 0)
15433 +                       return t;
15434 +               t++;
15435 +       }
15436 +
15437 +       return NULL;
15438 +}
15439 +
15440 +
15441 +static int
15442 +match(const struct sk_buff *skb,
15443 +      const struct net_device *in,
15444 +      const struct net_device *out,
15445 +      const void *matchinfo,
15446 +      int offset,
15447 +      const void *hdr,
15448 +      u_int16_t datalen,
15449 +      int *hotdrop)
15450 +{
15451 +       const struct ipt_string_info *info = matchinfo;
15452 +       struct iphdr *ip = skb->nh.iph;
15453 +       int hlen, nlen;
15454 +       char *needle, *haystack;
15455 +       proc_ipt_search search=search_linear;
15456 +
15457 +       if ( !ip ) return 0;
15458 +
15459 +       /* get lenghts, and validate them */
15460 +       nlen=info->len;
15461 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
15462 +       if ( nlen > hlen ) return 0;
15463 +
15464 +       needle=(char *)&info->string;
15465 +       haystack=(char *)ip+(ip->ihl*4);
15466 +
15467 +       /* The sublinear search comes in to its own
15468 +        * on the larger packets */
15469 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
15470 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
15471 +               if ( hlen < BM_MAX_HLEN ) {
15472 +                       search=search_sublinear;
15473 +               }else{
15474 +                       if (net_ratelimit())
15475 +                               printk(KERN_INFO "ipt_string: Packet too big "
15476 +                                       "to attempt sublinear string search "
15477 +                                       "(%d bytes)\n", hlen );
15478 +               }
15479 +       }
15480 +       
15481 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
15482 +}
15483 +
15484 +static int
15485 +checkentry(const char *tablename,
15486 +           const struct ipt_ip *ip,
15487 +           void *matchinfo,
15488 +           unsigned int matchsize,
15489 +           unsigned int hook_mask)
15490 +{
15491 +
15492 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
15493 +               return 0;
15494 +
15495 +       return 1;
15496 +}
15497 +
15498 +void string_freeup_data(void)
15499 +{
15500 +       int c;
15501 +       
15502 +       if ( bm_string_data ) {
15503 +               for(c=0; c<smp_num_cpus; c++) {
15504 +                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
15505 +                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
15506 +                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
15507 +               }
15508 +               kfree(bm_string_data);
15509 +       }
15510 +}
15511 +
15512 +static struct ipt_match string_match
15513 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
15514 +
15515 +static int __init init(void)
15516 +{
15517 +       int c;
15518 +       size_t tlen;
15519 +       size_t alen;
15520 +
15521 +       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
15522 +       alen=sizeof(int)*BM_MAX_HLEN;
15523 +       
15524 +       /* allocate array of structures */
15525 +       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
15526 +               return 0;
15527 +       }
15528 +       
15529 +       memset(bm_string_data, 0, tlen);
15530 +       
15531 +       /* allocate our skip/shift tables */
15532 +       for(c=0; c<smp_num_cpus; c++) {
15533 +               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
15534 +                       goto alloc_fail;
15535 +               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
15536 +                       goto alloc_fail;
15537 +               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
15538 +                       goto alloc_fail;
15539 +       }
15540 +       
15541 +       return ipt_register_match(&string_match);
15542 +
15543 +alloc_fail:
15544 +       string_freeup_data();
15545 +       return 0;
15546 +}
15547 +
15548 +static void __exit fini(void)
15549 +{
15550 +       ipt_unregister_match(&string_match);
15551 +       string_freeup_data();
15552 +}
15553 +
15554 +module_init(init);
15555 +module_exit(fini);
15556 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_time.c linux-2.6.6/net/ipv4/netfilter/ipt_time.c
15557 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_time.c       1970-01-01 01:00:00.000000000 +0100
15558 +++ linux-2.6.6/net/ipv4/netfilter/ipt_time.c   2004-05-18 12:37:29.000000000 +0200
15559 @@ -0,0 +1,189 @@
15560 +/*
15561 +  This is a module which is used for time matching
15562 +  It is using some modified code from dietlibc (localtime() function)
15563 +  that you can find at http://www.fefe.de/dietlibc/
15564 +  This file is distributed under the terms of the GNU General Public
15565 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
15566 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
15567 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
15568 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
15569 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
15570 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
15571 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
15572 +  2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
15573 +*/
15574 +
15575 +#include <linux/module.h>
15576 +#include <linux/skbuff.h>
15577 +#include <linux/netfilter_ipv4/ip_tables.h>
15578 +#include <linux/netfilter_ipv4/ipt_time.h>
15579 +#include <linux/time.h>
15580 +
15581 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
15582 +MODULE_DESCRIPTION("Match arrival timestamp/date");
15583 +MODULE_LICENSE("GPL");
15584 +
15585 +struct tm
15586 +{
15587 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
15588 +       int tm_min;                   /* Minutes.     [0-59] */
15589 +       int tm_hour;                  /* Hours.       [0-23] */
15590 +       int tm_mday;                  /* Day.         [1-31] */
15591 +       int tm_mon;                   /* Month.       [0-11] */
15592 +       int tm_year;                  /* Year - 1900.  */
15593 +       int tm_wday;                  /* Day of week. [0-6] */
15594 +       int tm_yday;                  /* Days in year.[0-365] */
15595 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
15596 +
15597 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
15598 +       const char *tm_zone;          /* we don't care, we count from GMT */
15599 +};
15600 +
15601 +void
15602 +localtime(const time_t *timepr, struct tm *r);
15603 +
15604 +static int
15605 +match(const struct sk_buff *skb,
15606 +      const struct net_device *in,
15607 +      const struct net_device *out,
15608 +      const void *matchinfo,
15609 +      int offset,
15610 +      const void *hdr,
15611 +      u_int16_t datalen,
15612 +      int *hotdrop)
15613 +{
15614 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
15615 +       struct tm currenttime;                          /* time human readable */
15616 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
15617 +       u_int16_t packet_time;
15618 +       struct timeval kerneltimeval;
15619 +       time_t packet_local_time;
15620 +
15621 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
15622 +       if (info->kerneltime)
15623 +       {
15624 +               do_gettimeofday(&kerneltimeval);
15625 +               packet_local_time = kerneltimeval.tv_sec;
15626 +       }
15627 +       else
15628 +               packet_local_time = skb->stamp.tv_sec;
15629 +
15630 +       /* First we make sure we are in the date start-stop boundaries */
15631 +       if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
15632 +               return 0; /* We are outside the date boundaries */
15633 +
15634 +       /* Transform the timestamp of the packet, in a human readable form */
15635 +       localtime(&packet_local_time, &currenttime);
15636 +
15637 +       /* check if we match this timestamp, we start by the days... */
15638 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
15639 +               return 0; /* the day doesn't match */
15640 +
15641 +       /* ... check the time now */
15642 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
15643 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
15644 +               return 0;
15645 +
15646 +       /* here we match ! */
15647 +       return 1;
15648 +}
15649 +
15650 +static int
15651 +checkentry(const char *tablename,
15652 +           const struct ipt_ip *ip,
15653 +           void *matchinfo,
15654 +           unsigned int matchsize,
15655 +           unsigned int hook_mask)
15656 +{
15657 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
15658 +
15659 +       /* First, check that we are in the correct hooks */
15660 +       if (hook_mask
15661 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15662 +       {
15663 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
15664 +               return 0;
15665 +       }
15666 +       /* we use the kerneltime if we are in forward or output */
15667 +       info->kerneltime = 1;
15668 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
15669 +               /* we use the skb time */
15670 +               info->kerneltime = 0;
15671 +
15672 +       /* Check the size */
15673 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
15674 +               return 0;
15675 +       /* Now check the coherence of the data ... */
15676 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
15677 +           (info->time_stop  > 1439))
15678 +       {
15679 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
15680 +               return 0;
15681 +       }
15682 +
15683 +       return 1;
15684 +}
15685 +
15686 +static struct ipt_match time_match
15687 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
15688 +
15689 +static int __init init(void)
15690 +{
15691 +       printk("ipt_time loading\n");
15692 +       return ipt_register_match(&time_match);
15693 +}
15694 +
15695 +static void __exit fini(void)
15696 +{
15697 +       ipt_unregister_match(&time_match);
15698 +       printk("ipt_time unloaded\n");
15699 +}
15700 +
15701 +module_init(init);
15702 +module_exit(fini);
15703 +
15704 +
15705 +/* The part below is borowed and modified from dietlibc */
15706 +
15707 +/* seconds per day */
15708 +#define SPD 24*60*60
15709 +
15710 +void
15711 +localtime(const time_t *timepr, struct tm *r) {
15712 +       time_t i;
15713 +       time_t timep;
15714 +       extern struct timezone sys_tz;
15715 +       const unsigned int __spm[12] =
15716 +               { 0,
15717 +                 (31),
15718 +                 (31+28),
15719 +                 (31+28+31),
15720 +                 (31+28+31+30),
15721 +                 (31+28+31+30+31),
15722 +                 (31+28+31+30+31+30),
15723 +                 (31+28+31+30+31+30+31),
15724 +                 (31+28+31+30+31+30+31+31),
15725 +                 (31+28+31+30+31+30+31+31+30),
15726 +                 (31+28+31+30+31+30+31+31+30+31),
15727 +                 (31+28+31+30+31+30+31+31+30+31+30),
15728 +               };
15729 +       register time_t work;
15730 +
15731 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
15732 +       work=timep%(SPD);
15733 +       r->tm_sec=work%60; work/=60;
15734 +       r->tm_min=work%60; r->tm_hour=work/60;
15735 +       work=timep/(SPD);
15736 +       r->tm_wday=(4+work)%7;
15737 +       for (i=1970; ; ++i) {
15738 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
15739 +               if (work>k)
15740 +                       work-=k;
15741 +               else
15742 +                       break;
15743 +       }
15744 +       r->tm_year=i-1900;
15745 +       for (i=11; i && __spm[i]>work; --i) ;
15746 +       r->tm_mon=i;
15747 +       r->tm_mday=work-__spm[i]+1;
15748 +}
15749 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.6/net/ipv4/netfilter/ipt_u32.c
15750 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_u32.c        1970-01-01 01:00:00.000000000 +0100
15751 +++ linux-2.6.6/net/ipv4/netfilter/ipt_u32.c    2004-05-18 12:37:31.000000000 +0200
15752 @@ -0,0 +1,211 @@
15753 +/* Kernel module to match u32 packet content. */
15754 +
15755 +/* 
15756 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
15757 +have specified values.  The specification of what to extract is general 
15758 +enough to find data at given offsets from tcp headers or payloads.
15759 +
15760 + --u32 tests
15761 + The argument amounts to a program in a small language described below.
15762 + tests := location = value |  tests && location = value
15763 + value := range | value , range
15764 + range := number | number : number
15765 +  a single number, n, is interpreted the same as n:n
15766 +  n:m is interpreted as the range of numbers >=n and <=m
15767 + location := number | location operator number
15768 + operator := & | << | >> | @
15769 +
15770 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
15771 + membership operator and the value syntax describes a set.  The @ operator
15772 + is what allows moving to the next header and is described further below.
15773 +
15774 + *** Until I can find out how to avoid it, there are some artificial limits
15775 + on the size of the tests:
15776 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
15777 + - no more than 10 ranges (and 9 commas) per value
15778 + - no more than 10 numbers (and 9 operators) per location
15779 +
15780 + To describe the meaning of location, imagine the following machine that
15781 + interprets it.  There are three registers:
15782 +  A is of type char*, initially the address of the IP header
15783 +  B and C are unsigned 32 bit integers, initially zero
15784 +
15785 +  The instructions are:
15786 +   number      B = number;
15787 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
15788 +   &number     C = C&number
15789 +   <<number    C = C<<number
15790 +   >>number    C = C>>number
15791 +   @number     A = A+C; then do the instruction number
15792 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
15793 +  Otherwise the result of the computation is the final value of C.
15794 +
15795 + Whitespace is allowed but not required in the tests.
15796 + However the characters that do occur there are likely to require
15797 + shell quoting, so it's a good idea to enclose the arguments in quotes.
15798 +
15799 +Example:
15800 + match IP packets with total length >= 256
15801 + The IP header contains a total length field in bytes 2-3.
15802 + --u32 "0&0xFFFF=0x100:0xFFFF" 
15803 + read bytes 0-3
15804 + AND that with FFFF (giving bytes 2-3),
15805 + and test whether that's in the range [0x100:0xFFFF]
15806 +
15807 +Example: (more realistic, hence more complicated)
15808 + match icmp packets with icmp type 0
15809 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
15810 + --u32 "6&0xFF=1 && ...
15811 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
15812 + Next test that it's not a fragment.
15813 +  (If so it might be part of such a packet but we can't always tell.)
15814 +  n.b. This test is generally needed if you want to match anything
15815 +  beyond the IP header.
15816 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
15817 + packet (not a fragment).  Alternatively, you can allow first fragments
15818 + by only testing the last 5 bits of byte 6.
15819 + ... 4&0x3FFF=0 && ...
15820 + Last test: the first byte past the IP header (the type) is 0
15821 + This is where we have to use the @syntax.  The length of the IP header
15822 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
15823 + IP header itself.
15824 + ... 0>>22&0x3C@0>>24=0"
15825 + The first 0 means read bytes 0-3,
15826 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
15827 +   the first byte, so only 22 bits is four times that plus a few more bits.
15828 + &3C then eliminates the two extra bits on the right and the first four 
15829 + bits of the first byte.
15830 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
15831 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
15832 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
15833 + @ means to use this number as a new offset into the packet, and read
15834 + four bytes starting from there.  This is the first 4 bytes of the icmp
15835 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
15836 + the value 24 to the right to throw out all but the first byte and compare
15837 + the result with 0.
15838 +
15839 +Example: 
15840 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
15841 + First we test that the packet is a tcp packet (similar to icmp).
15842 + --u32 "6&0xFF=6 && ...
15843 + Next, test that it's not a fragment (same as above).
15844 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
15845 + 0>>22&3C as above computes the number of bytes in the IP header.
15846 + @ makes this the new offset into the packet, which is the start of the
15847 + tcp header.  The length of the tcp header (again in 32 bit words) is
15848 + the left half of byte 12 of the tcp header.  The 12>>26&3C
15849 + computes this length in bytes (similar to the IP header before).
15850 + @ makes this the new offset, which is the start of the tcp payload.
15851 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
15852 + result is any of 1, 2, 5 or 8
15853 +*/
15854 +
15855 +#include <linux/module.h>
15856 +#include <linux/skbuff.h>
15857 +
15858 +#include <linux/netfilter_ipv4/ipt_u32.h>
15859 +#include <linux/netfilter_ipv4/ip_tables.h>
15860 +
15861 +/* #include <asm-i386/timex.h> for timing */
15862 +
15863 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
15864 +MODULE_DESCRIPTION("IP tables u32 matching module");
15865 +MODULE_LICENSE("GPL");
15866 +
15867 +static int
15868 +match(const struct sk_buff *skb,
15869 +      const struct net_device *in,
15870 +      const struct net_device *out,
15871 +      const void *matchinfo,
15872 +      int offset,
15873 +      const void *hdr,
15874 +      u_int16_t datalen,
15875 +      int *hotdrop)
15876 +{
15877 +       const struct ipt_u32 *data = matchinfo;
15878 +       int testind, i;
15879 +       unsigned char* origbase = (char*)skb->nh.iph;
15880 +       unsigned char* base = origbase;
15881 +       unsigned char* head = skb->head;
15882 +       unsigned char* end = skb->end;
15883 +       int nnums, nvals;
15884 +       u_int32_t pos, val;
15885 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
15886 +          cycles1 = get_cycles(); */
15887 +
15888 +       for (testind=0; testind < data->ntests; testind++) {
15889 +               base = origbase; /* reset for each test */
15890 +               pos = data->tests[testind].location[0].number;
15891 +               if (base+pos+3 > end || base+pos < head) 
15892 +                       return 0;
15893 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
15894 +                       (base[pos+2]<<8) + base[pos+3];
15895 +               nnums = data->tests[testind].nnums;
15896 +               for (i=1; i < nnums; i++) {
15897 +                       u_int32_t number = data->tests[testind].location[i].number;
15898 +                       switch (data->tests[testind].location[i].nextop) {
15899 +                       case IPT_U32_AND: 
15900 +                               val = val & number; 
15901 +                               break;
15902 +                       case IPT_U32_LEFTSH: 
15903 +                               val = val << number;
15904 +                               break;
15905 +                       case IPT_U32_RIGHTSH: 
15906 +                               val = val >> number; 
15907 +                               break;
15908 +                       case IPT_U32_AT:
15909 +                               base = base + val;
15910 +                               pos = number;
15911 +                               if (base+pos+3 > end || base+pos < head) 
15912 +                                       return 0;
15913 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
15914 +                                       (base[pos+2]<<8) + base[pos+3];
15915 +                               break;
15916 +                       }
15917 +               }
15918 +               nvals = data->tests[testind].nvalues;
15919 +               for (i=0; i < nvals; i++) {
15920 +                       if ((data->tests[testind].value[i].min <= val) &&
15921 +                           (val <= data->tests[testind].value[i].max)) {
15922 +                               break;
15923 +                       }
15924 +               }
15925 +               if (i >= data->tests[testind].nvalues) {
15926 +                       /* cycles2 = get_cycles(); 
15927 +                          printk("failed %d in %d cycles\n", testind, 
15928 +                                 cycles2-cycles1); */
15929 +                       return 0;
15930 +               }
15931 +       }
15932 +       /* cycles2 = get_cycles();
15933 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
15934 +       return 1;
15935 +}
15936 +
15937 +static int
15938 +checkentry(const char *tablename,
15939 +           const struct ipt_ip *ip,
15940 +           void *matchinfo,
15941 +           unsigned int matchsize,
15942 +           unsigned int hook_mask)
15943 +{
15944 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
15945 +               return 0;
15946 +       return 1;
15947 +}
15948 +
15949 +static struct ipt_match u32_match
15950 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
15951 +
15952 +static int __init init(void)
15953 +{
15954 +       return ipt_register_match(&u32_match);
15955 +}
15956 +
15957 +static void __exit fini(void)
15958 +{
15959 +       ipt_unregister_match(&u32_match);
15960 +}
15961 +
15962 +module_init(init);
15963 +module_exit(fini);
15964 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6/net/ipv4/netfilter/ipt_unclean.c
15965 --- linux-2.6.6.org/net/ipv4/netfilter/ipt_unclean.c    1970-01-01 01:00:00.000000000 +0100
15966 +++ linux-2.6.6/net/ipv4/netfilter/ipt_unclean.c        2004-05-18 12:40:37.000000000 +0200
15967 @@ -0,0 +1,604 @@
15968 +/* Kernel module to match suspect packets. */
15969 +#include <linux/module.h>
15970 +#include <linux/skbuff.h>
15971 +#include <linux/ip.h>
15972 +#include <linux/udp.h>
15973 +#include <linux/tcp.h>
15974 +#include <linux/icmp.h>
15975 +#include <net/checksum.h>
15976 +
15977 +#include <linux/netfilter_ipv4/ip_tables.h>
15978 +
15979 +#define limpk(format, args...)                                          \
15980 +do {                                                                    \
15981 +       if (net_ratelimit())                                             \
15982 +               printk("ipt_unclean: %s" format,                         \
15983 +                      embedded ? "(embedded packet) " : "" , ## args);  \
15984 +} while(0)
15985 +
15986 +enum icmp_error_status
15987 +{
15988 +       ICMP_MAY_BE_ERROR,
15989 +       ICMP_IS_ERROR,
15990 +       ICMP_NOT_ERROR
15991 +};
15992 +
15993 +struct icmp_info
15994 +{
15995 +       size_t min_len, max_len;
15996 +       enum icmp_error_status err;
15997 +       u_int8_t min_code, max_code;
15998 +};
15999 +
16000 +static int
16001 +check_ip(struct iphdr *iph, size_t length, int embedded);
16002 +
16003 +/* ICMP-specific checks. */
16004 +static int
16005 +check_icmp(const struct icmphdr *icmph,
16006 +          u_int16_t datalen,
16007 +          unsigned int offset,
16008 +          int more_frags,
16009 +          int embedded)
16010 +{
16011 +       static struct icmp_info info[]
16012 +               = { [ICMP_ECHOREPLY]
16013 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
16014 +                   [ICMP_DEST_UNREACH]
16015 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
16016 +                   [ICMP_SOURCE_QUENCH]
16017 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
16018 +                   [ICMP_REDIRECT]
16019 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
16020 +                   [ICMP_ECHO]
16021 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0  },
16022 +                   /* Router advertisement. */
16023 +                   [9]
16024 +                   = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
16025 +                   /* Router solicitation. */
16026 +                   [10]
16027 +                   = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
16028 +                   [ICMP_TIME_EXCEEDED]
16029 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1  },
16030 +                   [ICMP_PARAMETERPROB]
16031 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
16032 +                   [ICMP_TIMESTAMP]
16033 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
16034 +                   [ICMP_TIMESTAMPREPLY]
16035 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
16036 +                   [ICMP_INFO_REQUEST]
16037 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
16038 +                   [ICMP_INFO_REPLY]
16039 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
16040 +                   [ICMP_ADDRESS]
16041 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
16042 +                   [ICMP_ADDRESSREPLY]
16043 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
16044 +
16045 +       /* Can't do anything if it's a fragment. */
16046 +       if (offset)
16047 +               return 1;
16048 +
16049 +       /* Must cover type and code. */
16050 +       if (datalen < 2) {
16051 +               limpk("ICMP len=%u too short\n", datalen);
16052 +               return 0;
16053 +       }
16054 +
16055 +       /* If not embedded. */
16056 +       if (!embedded) {
16057 +               /* Bad checksum?  Don't print, just ignore. */
16058 +               if (!more_frags
16059 +                   && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
16060 +                       return 0;
16061 +
16062 +               /* CHECK: Truncated ICMP (even if first fragment). */
16063 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16064 +                   && info[icmph->type].min_len != 0
16065 +                   && datalen < info[icmph->type].min_len) {
16066 +                       limpk("ICMP type %u len %u too short\n",
16067 +                             icmph->type, datalen);
16068 +                       return 0;
16069 +               }
16070 +
16071 +               /* CHECK: Check within known error ICMPs. */
16072 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16073 +                   && info[icmph->type].err == ICMP_IS_ERROR) {
16074 +                       /* CHECK: Embedded packet must be at least
16075 +                          length of iph + 8 bytes. */
16076 +                       struct iphdr *inner = (void *)icmph + 8;
16077 +
16078 +                       /* datalen > 8 since all ICMP_IS_ERROR types
16079 +                           have min length > 8 */
16080 +                       if (datalen - 8 < sizeof(struct iphdr)) {
16081 +                               limpk("ICMP error internal way too short\n");
16082 +                               return 0;
16083 +                       }
16084 +                       if (datalen - 8 < inner->ihl*4 + 8) {
16085 +                               limpk("ICMP error internal too short\n");
16086 +                               return 0;
16087 +                       }
16088 +                       if (!check_ip(inner, datalen - 8, 1))
16089 +                               return 0;
16090 +               }
16091 +       } else {
16092 +               /* CHECK: Can't embed ICMP unless known non-error. */
16093 +               if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
16094 +                   || info[icmph->type].err != ICMP_NOT_ERROR) {
16095 +                       limpk("ICMP type %u not embeddable\n",
16096 +                             icmph->type);
16097 +                       return 0;
16098 +               }
16099 +       }
16100 +
16101 +       /* CHECK: Invalid ICMP codes. */
16102 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16103 +           && (icmph->code < info[icmph->type].min_code
16104 +               || icmph->code > info[icmph->type].max_code)) {
16105 +               limpk("ICMP type=%u code=%u\n",
16106 +                     icmph->type, icmph->code);
16107 +               return 0;
16108 +       }
16109 +
16110 +       /* CHECK: Above maximum length. */
16111 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
16112 +           && info[icmph->type].max_len != 0
16113 +           && datalen > info[icmph->type].max_len) {
16114 +               limpk("ICMP type=%u too long: %u bytes\n",
16115 +                     icmph->type, datalen);
16116 +               return 0;
16117 +       }
16118 +
16119 +       switch (icmph->type) {
16120 +       case ICMP_PARAMETERPROB: {
16121 +               /* CHECK: Problem param must be within error packet's
16122 +                * IP header. */
16123 +               struct iphdr *iph = (void *)icmph + 8;
16124 +               u_int32_t arg = ntohl(icmph->un.gateway);
16125 +
16126 +               if (icmph->code == 0) {
16127 +                       /* Code 0 means that upper 8 bits is pointer
16128 +                           to problem. */
16129 +                       if ((arg >> 24) >= iph->ihl*4) {
16130 +                               limpk("ICMP PARAMETERPROB ptr = %u\n",
16131 +                                     ntohl(icmph->un.gateway) >> 24);
16132 +                               return 0;
16133 +                       }
16134 +                       arg &= 0x00FFFFFF;
16135 +               }
16136 +
16137 +               /* CHECK: Rest must be zero. */
16138 +               if (arg) {
16139 +                       limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
16140 +                             arg);
16141 +                       return 0;
16142 +               }
16143 +               break;
16144 +       }
16145 +
16146 +       case ICMP_TIME_EXCEEDED:
16147 +       case ICMP_SOURCE_QUENCH:
16148 +               /* CHECK: Unused must be zero. */
16149 +               if (icmph->un.gateway != 0) {
16150 +                       limpk("ICMP type=%u unused = %u\n",
16151 +                             icmph->type, ntohl(icmph->un.gateway));
16152 +                       return 0;
16153 +               }
16154 +               break;
16155 +       }
16156 +
16157 +       return 1;
16158 +}
16159 +
16160 +/* UDP-specific checks. */
16161 +static int
16162 +check_udp(const struct iphdr *iph,
16163 +         const struct udphdr *udph,
16164 +         u_int16_t datalen,
16165 +         unsigned int offset,
16166 +         int more_frags,
16167 +         int embedded)
16168 +{
16169 +       /* Can't do anything if it's a fragment. */
16170 +       if (offset)
16171 +               return 1;
16172 +
16173 +       /* CHECK: Must cover UDP header. */
16174 +       if (datalen < sizeof(struct udphdr)) {
16175 +               limpk("UDP len=%u too short\n", datalen);
16176 +               return 0;
16177 +       }
16178 +
16179 +       /* Bad checksum?  Don't print, just say it's unclean. */
16180 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
16181 +       if (!more_frags && !embedded && udph->check
16182 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
16183 +                                csum_partial((char *)udph, datalen, 0)) != 0)
16184 +               return 0;
16185 +
16186 +       /* CHECK: Destination port can't be zero. */
16187 +       if (!udph->dest) {
16188 +               limpk("UDP zero destination port\n");
16189 +               return 0;
16190 +       }
16191 +
16192 +       if (!more_frags) {
16193 +               if (!embedded) {
16194 +                       /* CHECK: UDP length must match. */
16195 +                       if (ntohs(udph->len) != datalen) {
16196 +                               limpk("UDP len too short %u vs %u\n",
16197 +                                     ntohs(udph->len), datalen);
16198 +                               return 0;
16199 +                       }
16200 +               } else {
16201 +                       /* CHECK: UDP length be >= this truncated pkt. */
16202 +                       if (ntohs(udph->len) < datalen) {
16203 +                               limpk("UDP len too long %u vs %u\n",
16204 +                                     ntohs(udph->len), datalen);
16205 +                               return 0;
16206 +                       }
16207 +               }
16208 +       } else {
16209 +               /* CHECK: UDP length must be > this frag's length. */
16210 +               if (ntohs(udph->len) <= datalen) {
16211 +                       limpk("UDP fragment len too short %u vs %u\n",
16212 +                             ntohs(udph->len), datalen);
16213 +                       return 0;
16214 +               }
16215 +       }
16216 +
16217 +       return 1;
16218 +}
16219 +
16220 +#define        TH_FIN  0x01
16221 +#define        TH_SYN  0x02
16222 +#define        TH_RST  0x04
16223 +#define        TH_PUSH 0x08
16224 +#define        TH_ACK  0x10
16225 +#define        TH_URG  0x20
16226 +#define        TH_ECE  0x40
16227 +#define        TH_CWR  0x80
16228 +
16229 +/* table of valid flag combinations - ECE and CWR are always valid */
16230 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
16231 +{
16232 +       [TH_SYN]                        = 1,
16233 +       [TH_SYN|TH_ACK]                 = 1,
16234 +       [TH_RST]                        = 1,
16235 +       [TH_RST|TH_ACK]                 = 1,
16236 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
16237 +       [TH_FIN|TH_ACK]                 = 1,
16238 +       [TH_ACK]                        = 1,
16239 +       [TH_ACK|TH_PUSH]                = 1,
16240 +       [TH_ACK|TH_URG]                 = 1,
16241 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
16242 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
16243 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
16244 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
16245 +};
16246 +
16247 +/* TCP-specific checks. */
16248 +static int
16249 +check_tcp(const struct iphdr *iph,
16250 +         const struct tcphdr *tcph,
16251 +         u_int16_t datalen,
16252 +         unsigned int offset,
16253 +         int more_frags,
16254 +         int embedded)
16255 +{
16256 +       u_int8_t *opt = (u_int8_t *)tcph;
16257 +       u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
16258 +       u_int8_t tcpflags;
16259 +       int end_of_options = 0;
16260 +       size_t i;
16261 +
16262 +       /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
16263 +       /* In fact, this is caught below (offset < 516). */
16264 +
16265 +       /* Can't do anything if it's a fragment. */
16266 +       if (offset)
16267 +               return 1;
16268 +
16269 +       /* CHECK: Smaller than minimal TCP hdr. */
16270 +       if (datalen < sizeof(struct tcphdr)) {
16271 +               if (!embedded) {
16272 +                       limpk("Packet length %u < TCP header.\n", datalen);
16273 +                       return 0;
16274 +               }
16275 +               /* Must have ports available (datalen >= 8), from
16276 +                   check_icmp which set embedded = 1 */
16277 +               /* CHECK: TCP ports inside ICMP error */
16278 +               if (!tcph->source || !tcph->dest) {
16279 +                       limpk("Zero TCP ports %u/%u.\n",
16280 +                             htons(tcph->source), htons(tcph->dest));
16281 +                       return 0;
16282 +               }
16283 +               return 1;
16284 +       }
16285 +
16286 +       /* CHECK: Smaller than actual TCP hdr. */
16287 +       if (datalen < tcph->doff * 4) {
16288 +               if (!embedded) {
16289 +                       limpk("Packet length %u < actual TCP header.\n",
16290 +                             datalen);
16291 +                       return 0;
16292 +               } else
16293 +                       return 1;
16294 +       }
16295 +
16296 +       /* Bad checksum?  Don't print, just say it's unclean. */
16297 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
16298 +       if (!more_frags && !embedded
16299 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
16300 +                                csum_partial((char *)tcph, datalen, 0)) != 0)
16301 +               return 0;
16302 +
16303 +       /* CHECK: TCP ports non-zero */
16304 +       if (!tcph->source || !tcph->dest) {
16305 +               limpk("Zero TCP ports %u/%u.\n",
16306 +                     htons(tcph->source), htons(tcph->dest));
16307 +               return 0;
16308 +       }
16309 +
16310 +       /* CHECK: TCP reserved bits zero. */
16311 +       if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
16312 +               limpk("TCP reserved bits not zero\n");
16313 +               return 0;
16314 +       }
16315 +
16316 +       /* CHECK: TCP flags. */
16317 +       tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
16318 +       if (!tcp_valid_flags[tcpflags]) {
16319 +               limpk("TCP flags bad: %u\n", tcpflags);
16320 +               return 0;
16321 +       }
16322 +
16323 +       for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
16324 +               switch (opt[i]) {
16325 +               case 0:
16326 +                       end_of_options = 1;
16327 +                       i++;
16328 +                       break;
16329 +               case 1:
16330 +                       i++;
16331 +                       break;
16332 +               default:
16333 +                       /* CHECK: options after EOO. */
16334 +                       if (end_of_options) {
16335 +                               limpk("TCP option %u after end\n",
16336 +                                     opt[i]);
16337 +                               return 0;
16338 +                       }
16339 +                       /* CHECK: options at tail. */
16340 +                       else if (i+1 >= tcph->doff * 4) {
16341 +                               limpk("TCP option %u at tail\n",
16342 +                                     opt[i]);
16343 +                               return 0;
16344 +                       }
16345 +                       /* CHECK: zero-length options. */
16346 +                       else if (opt[i+1] == 0) {
16347 +                               limpk("TCP option %u 0 len\n",
16348 +                                     opt[i]);
16349 +                               return 0;
16350 +                       }
16351 +                       /* CHECK: oversize options. */
16352 +                       else if (&opt[i] + opt[i+1] > endhdr) {
16353 +                               limpk("TCP option %u at %Zu too long\n",
16354 +                                     (unsigned int) opt[i], i);
16355 +                               return 0;
16356 +                       }
16357 +                       /* Move to next option */
16358 +                       i += opt[i+1];
16359 +               }
16360 +       }
16361 +
16362 +       return 1;
16363 +}
16364 +
16365 +/* Returns 1 if ok */
16366 +/* Standard IP checks. */
16367 +static int
16368 +check_ip(struct iphdr *iph, size_t length, int embedded)
16369 +{
16370 +       u_int8_t *opt = (u_int8_t *)iph;
16371 +       u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
16372 +       int end_of_options = 0;
16373 +       void *protoh;
16374 +       size_t datalen;
16375 +       unsigned int i;
16376 +       unsigned int offset;
16377 +
16378 +       /* Should only happen for local outgoing raw-socket packets. */
16379 +       /* CHECK: length >= ip header. */
16380 +       if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
16381 +               limpk("Packet length %Zu < IP header.\n", length);
16382 +               return 0;
16383 +       }
16384 +
16385 +       offset = ntohs(iph->frag_off) & IP_OFFSET;
16386 +       protoh = (void *)iph + iph->ihl * 4;
16387 +       datalen = length - iph->ihl * 4;
16388 +
16389 +       /* CHECK: Embedded fragment. */
16390 +       if (embedded && offset) {
16391 +               limpk("Embedded fragment.\n");
16392 +               return 0;
16393 +       }
16394 +
16395 +       for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
16396 +               switch (opt[i]) {
16397 +               case 0:
16398 +                       end_of_options = 1;
16399 +                       i++;
16400 +                       break;
16401 +               case 1:
16402 +                       i++;
16403 +                       break;
16404 +               default:
16405 +                       /* CHECK: options after EOO. */
16406 +                       if (end_of_options) {
16407 +                               limpk("IP option %u after end\n",
16408 +                                     opt[i]);
16409 +                               return 0;
16410 +                       }
16411 +                       /* CHECK: options at tail. */
16412 +                       else if (i+1 >= iph->ihl * 4) {
16413 +                               limpk("IP option %u at tail\n",
16414 +                                     opt[i]);
16415 +                               return 0;
16416 +                       }
16417 +                       /* CHECK: zero-length or one-length options. */
16418 +                       else if (opt[i+1] < 2) {
16419 +                               limpk("IP option %u %u len\n",
16420 +                                     opt[i], opt[i+1]);
16421 +                               return 0;
16422 +                       }
16423 +                       /* CHECK: oversize options. */
16424 +                       else if (&opt[i] + opt[i+1] > endhdr) {
16425 +                               limpk("IP option %u at %u too long\n",
16426 +                                     opt[i], i);
16427 +                               return 0;
16428 +                       }
16429 +                       /* Move to next option */
16430 +                       i += opt[i+1];
16431 +               }
16432 +       }
16433 +
16434 +       /* Fragment checks. */
16435 +
16436 +       /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
16437 +       if ((ntohs(iph->frag_off) & IP_MF)
16438 +           && (ntohs(iph->tot_len) % 8) != 0) {
16439 +               limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
16440 +               return 0;
16441 +       }
16442 +
16443 +       /* CHECK: Oversize fragment a-la Ping of Death. */
16444 +       if (offset * 8 + datalen > 65535) {
16445 +               limpk("Oversize fragment to %u.\n", offset * 8);
16446 +               return 0;
16447 +       }
16448 +
16449 +       /* CHECK: DF set and offset or MF set. */
16450 +       if ((ntohs(iph->frag_off) & IP_DF)
16451 +           && (offset || (ntohs(iph->frag_off) & IP_MF))) {
16452 +               limpk("DF set and offset=%u, MF=%u.\n",
16453 +                     offset, ntohs(iph->frag_off) & IP_MF);
16454 +               return 0;
16455 +       }
16456 +
16457 +       /* CHECK: Zero-sized fragments. */
16458 +       if ((offset || (ntohs(iph->frag_off) & IP_MF))
16459 +           && datalen == 0) {
16460 +               limpk("Zero size fragment offset=%u\n", offset);
16461 +               return 0;
16462 +       }
16463 +
16464 +       /* Note: we can have even middle fragments smaller than this:
16465 +          consider a large packet passing through a 600MTU then
16466 +          576MTU link: this gives a fragment of 24 data bytes.  But
16467 +          everyone packs fragments largest first, hence a fragment
16468 +          can't START before 576 - MAX_IP_HEADER_LEN. */
16469 +
16470 +       /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
16471 +          down to 128 (576 taken from RFC 791: All hosts must be
16472 +          prepared to accept datagrams of up to 576 octets).  Use 128
16473 +          here. */
16474 +#define MIN_LIKELY_MTU 128
16475 +       /* CHECK: Min size of first frag = 128. */
16476 +       if ((ntohs(iph->frag_off) & IP_MF)
16477 +           && offset == 0
16478 +           && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
16479 +               limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
16480 +                     MIN_LIKELY_MTU);
16481 +               return 0;
16482 +       }
16483 +
16484 +       /* CHECK: Min offset of frag = 128 - IP hdr len. */
16485 +       if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
16486 +               limpk("Fragment starts at %u < %u\n", offset * 8,
16487 +                     MIN_LIKELY_MTU - iph->ihl * 4);
16488 +               return 0;
16489 +       }
16490 +
16491 +       /* CHECK: Protocol specification non-zero. */
16492 +       if (iph->protocol == 0) {
16493 +               limpk("Zero protocol\n");
16494 +               return 0;
16495 +       }
16496 +
16497 +       /* CHECK: Do not use what is unused.
16498 +        * First bit of fragmentation flags should be unused.
16499 +        * May be used by OS fingerprinting tools.
16500 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
16501 +        */
16502 +       if (ntohs(iph->frag_off)>>15) {
16503 +               limpk("IP unused bit set\n");
16504 +               return 0;
16505 +       }
16506 +
16507 +       /* Per-protocol checks. */
16508 +       switch (iph->protocol) {
16509 +       case IPPROTO_ICMP:
16510 +               return check_icmp(protoh, datalen, offset,
16511 +                                 (ntohs(iph->frag_off) & IP_MF),
16512 +                                 embedded);
16513 +
16514 +       case IPPROTO_UDP:
16515 +               return check_udp(iph, protoh, datalen, offset,
16516 +                                (ntohs(iph->frag_off) & IP_MF),
16517 +                                embedded);
16518 +
16519 +       case IPPROTO_TCP:
16520 +               return check_tcp(iph, protoh, datalen, offset,
16521 +                                (ntohs(iph->frag_off) & IP_MF),
16522 +                                embedded);
16523 +       default:
16524 +               /* Ignorance is bliss. */
16525 +               return 1;
16526 +       }
16527 +}
16528 +
16529 +static int
16530 +match(const struct sk_buff *skb,
16531 +      const struct net_device *in,
16532 +      const struct net_device *out,
16533 +      const void *matchinfo,
16534 +      int offset,
16535 +      const void *hdr,
16536 +      u_int16_t datalen,
16537 +      int *hotdrop)
16538 +{
16539 +       return !check_ip(skb->nh.iph, skb->len, 0);
16540 +}
16541 +
16542 +/* Called when user tries to insert an entry of this type. */
16543 +static int
16544 +checkentry(const char *tablename,
16545 +          const struct ipt_ip *ip,
16546 +          void *matchinfo,
16547 +          unsigned int matchsize,
16548 +          unsigned int hook_mask)
16549 +{
16550 +       if (matchsize != IPT_ALIGN(0))
16551 +               return 0;
16552 +
16553 +       return 1;
16554 +}
16555 +
16556 +static struct ipt_match unclean_match
16557 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
16558 +
16559 +static int __init init(void)
16560 +{
16561 +       return ipt_register_match(&unclean_match);
16562 +}
16563 +
16564 +static void __exit fini(void)
16565 +{
16566 +       ipt_unregister_match(&unclean_match);
16567 +}
16568 +
16569 +module_init(init);
16570 +module_exit(fini);
16571 +MODULE_LICENSE("GPL");
16572 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.6/net/ipv4/netfilter/iptable_filter.c
16573 --- linux-2.6.6.org/net/ipv4/netfilter/iptable_filter.c 2004-05-10 04:32:28.000000000 +0200
16574 +++ linux-2.6.6/net/ipv4/netfilter/iptable_filter.c     2004-05-18 12:38:32.000000000 +0200
16575 @@ -59,7 +59,7 @@
16576                 0,
16577                 sizeof(struct ipt_entry),
16578                 sizeof(struct ipt_standard),
16579 -               0, { 0, 0 }, { } },
16580 +               0, NULL, 0, { 0, 0 }, { } },
16581               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16582                 -NF_ACCEPT - 1 } },
16583             /* FORWARD */
16584 @@ -67,7 +67,7 @@
16585                 0,
16586                 sizeof(struct ipt_entry),
16587                 sizeof(struct ipt_standard),
16588 -               0, { 0, 0 }, { } },
16589 +               0, NULL, 0, { 0, 0 }, { } },
16590               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16591                 -NF_ACCEPT - 1 } },
16592             /* LOCAL_OUT */
16593 @@ -75,7 +75,7 @@
16594                 0,
16595                 sizeof(struct ipt_entry),
16596                 sizeof(struct ipt_standard),
16597 -               0, { 0, 0 }, { } },
16598 +               0, NULL, 0, { 0, 0 }, { } },
16599               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16600                 -NF_ACCEPT - 1 } }
16601      },
16602 @@ -84,7 +84,7 @@
16603         0,
16604         sizeof(struct ipt_entry),
16605         sizeof(struct ipt_error),
16606 -       0, { 0, 0 }, { } },
16607 +       0, NULL, 0, { 0, 0 }, { } },
16608        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16609           { } },
16610         "ERROR"
16611 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.6/net/ipv4/netfilter/iptable_mangle.c
16612 --- linux-2.6.6.org/net/ipv4/netfilter/iptable_mangle.c 2004-05-10 04:33:14.000000000 +0200
16613 +++ linux-2.6.6/net/ipv4/netfilter/iptable_mangle.c     2004-05-18 12:38:32.000000000 +0200
16614 @@ -74,7 +74,7 @@
16615                 0,
16616                 sizeof(struct ipt_entry),
16617                 sizeof(struct ipt_standard),
16618 -               0, { 0, 0 }, { } },
16619 +               0, NULL, 0, { 0, 0 }, { } },
16620               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16621                 -NF_ACCEPT - 1 } },
16622             /* LOCAL_IN */
16623 @@ -82,7 +82,7 @@
16624                 0,
16625                 sizeof(struct ipt_entry),
16626                 sizeof(struct ipt_standard),
16627 -               0, { 0, 0 }, { } },
16628 +               0, NULL, 0, { 0, 0 }, { } },
16629               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16630                 -NF_ACCEPT - 1 } },
16631             /* FORWARD */
16632 @@ -90,7 +90,7 @@
16633                 0,
16634                 sizeof(struct ipt_entry),
16635                 sizeof(struct ipt_standard),
16636 -               0, { 0, 0 }, { } },
16637 +               0, NULL, 0, { 0, 0 }, { } },
16638               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16639                 -NF_ACCEPT - 1 } },
16640             /* LOCAL_OUT */
16641 @@ -98,7 +98,7 @@
16642                 0,
16643                 sizeof(struct ipt_entry),
16644                 sizeof(struct ipt_standard),
16645 -               0, { 0, 0 }, { } },
16646 +               0, NULL, 0, { 0, 0 }, { } },
16647               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16648                 -NF_ACCEPT - 1 } },
16649             /* POST_ROUTING */
16650 @@ -106,7 +106,7 @@
16651                 0,
16652                 sizeof(struct ipt_entry),
16653                 sizeof(struct ipt_standard),
16654 -               0, { 0, 0 }, { } },
16655 +               0, NULL, 0, { 0, 0 }, { } },
16656               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16657                 -NF_ACCEPT - 1 } },
16658      },
16659 @@ -115,7 +115,7 @@
16660         0,
16661         sizeof(struct ipt_entry),
16662         sizeof(struct ipt_error),
16663 -       0, { 0, 0 }, { } },
16664 +       0, NULL, 0, { 0, 0 }, { } },
16665        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16666           { } },
16667         "ERROR"
16668 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.6/net/ipv4/netfilter/iptable_raw.c
16669 --- linux-2.6.6.org/net/ipv4/netfilter/iptable_raw.c    2004-05-10 04:33:19.000000000 +0200
16670 +++ linux-2.6.6/net/ipv4/netfilter/iptable_raw.c        2004-05-18 12:38:32.000000000 +0200
16671 @@ -46,7 +46,7 @@
16672                 0,
16673                 sizeof(struct ipt_entry),
16674                 sizeof(struct ipt_standard),
16675 -               0, { 0, 0 }, { } },
16676 +               0, NULL, 0, { 0, 0 }, { } },
16677               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16678                 -NF_ACCEPT - 1 } },
16679             /* LOCAL_OUT */
16680 @@ -54,7 +54,7 @@
16681                 0,
16682                 sizeof(struct ipt_entry),
16683                 sizeof(struct ipt_standard),
16684 -               0, { 0, 0 }, { } },
16685 +               0, NULL, 0, { 0, 0 }, { } },
16686               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16687                 -NF_ACCEPT - 1 } }
16688      },
16689 @@ -63,7 +63,7 @@
16690         0,
16691         sizeof(struct ipt_entry),
16692         sizeof(struct ipt_error),
16693 -       0, { 0, 0 }, { } },
16694 +       0, NULL, 0, { 0, 0 }, { } },
16695        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16696           { } },
16697         "ERROR"
16698 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/raw.c linux-2.6.6/net/ipv4/raw.c
16699 --- linux-2.6.6.org/net/ipv4/raw.c      2004-05-10 04:32:38.000000000 +0200
16700 +++ linux-2.6.6/net/ipv4/raw.c  2004-05-18 12:39:23.000000000 +0200
16701 @@ -249,6 +249,7 @@
16702                 kfree_skb(skb);
16703                 return NET_RX_DROP;
16704         }
16705 +       nf_reset(skb);
16706  
16707         skb_push(skb, skb->data - skb->nh.raw);
16708  
16709 @@ -307,7 +308,7 @@
16710         }
16711  
16712         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
16713 -                     dst_output);
16714 +                     ip_dst_output);
16715         if (err > 0)
16716                 err = inet->recverr ? net_xmit_errno(err) : 0;
16717         if (err)
16718 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/tcp_ipv4.c linux-2.6.6/net/ipv4/tcp_ipv4.c
16719 --- linux-2.6.6.org/net/ipv4/tcp_ipv4.c 2004-05-18 11:20:48.000000000 +0200
16720 +++ linux-2.6.6/net/ipv4/tcp_ipv4.c     2004-05-18 12:39:47.000000000 +0200
16721 @@ -1785,6 +1785,7 @@
16722  
16723         if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
16724                 goto discard_and_relse;
16725 +       nf_reset(skb);
16726  
16727         if (sk_filter(sk, skb, 0))
16728                 goto discard_and_relse;
16729 @@ -2636,6 +2637,7 @@
16730  EXPORT_SYMBOL(tcp_v4_connect);
16731  EXPORT_SYMBOL(tcp_v4_do_rcv);
16732  EXPORT_SYMBOL(tcp_v4_lookup_listener);
16733 +EXPORT_SYMBOL(tcp_v4_lookup);
16734  EXPORT_SYMBOL(tcp_v4_rebuild_header);
16735  EXPORT_SYMBOL(tcp_v4_remember_stamp);
16736  EXPORT_SYMBOL(tcp_v4_send_check);
16737 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/udp.c linux-2.6.6/net/ipv4/udp.c
16738 --- linux-2.6.6.org/net/ipv4/udp.c      2004-05-10 04:32:01.000000000 +0200
16739 +++ linux-2.6.6/net/ipv4/udp.c  2004-05-18 12:39:47.000000000 +0200
16740 @@ -1045,6 +1045,7 @@
16741                 kfree_skb(skb);
16742                 return -1;
16743         }
16744 +       nf_reset(skb);
16745  
16746         if (up->encap_type) {
16747                 /*
16748 @@ -1210,6 +1211,7 @@
16749  
16750         if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
16751                 goto drop;
16752 +       nf_reset(skb);
16753  
16754         /* No socket. Drop packet silently, if checksum is wrong */
16755         if (udp_checksum_complete(skb))
16756 @@ -1558,6 +1560,7 @@
16757  EXPORT_SYMBOL(udp_port_rover);
16758  EXPORT_SYMBOL(udp_prot);
16759  EXPORT_SYMBOL(udp_sendmsg);
16760 +EXPORT_SYMBOL(udp_v4_lookup);
16761  
16762  #ifdef CONFIG_PROC_FS
16763  EXPORT_SYMBOL(udp_proc_register);
16764 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6/net/ipv4/xfrm4_tunnel.c
16765 --- linux-2.6.6.org/net/ipv4/xfrm4_tunnel.c     2004-05-10 04:32:00.000000000 +0200
16766 +++ linux-2.6.6/net/ipv4/xfrm4_tunnel.c 2004-05-18 12:39:22.000000000 +0200
16767 @@ -76,6 +76,7 @@
16768                 err = -EHOSTUNREACH;
16769                 goto error_nolock;
16770         }
16771 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
16772         return NET_XMIT_BYPASS;
16773  
16774  error_nolock:
16775 @@ -170,6 +171,7 @@
16776         .handler        =       ipip_rcv,
16777         .err_handler    =       ipip_err,
16778         .no_policy      =       1,
16779 +       .xfrm_prot      =       1,
16780  };
16781  
16782  static int __init ipip_init(void)
16783 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/ip6_tunnel.c linux-2.6.6/net/ipv6/ip6_tunnel.c
16784 --- linux-2.6.6.org/net/ipv6/ip6_tunnel.c       2004-05-10 04:31:59.000000000 +0200
16785 +++ linux-2.6.6/net/ipv6/ip6_tunnel.c   2004-05-18 12:35:50.000000000 +0200
16786 @@ -715,13 +715,7 @@
16787         ipv6h->nexthdr = proto;
16788         ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
16789         ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
16790 -#ifdef CONFIG_NETFILTER
16791 -       nf_conntrack_put(skb->nfct);
16792 -       skb->nfct = NULL;
16793 -#ifdef CONFIG_NETFILTER_DEBUG
16794 -       skb->nf_debug = 0;
16795 -#endif
16796 -#endif
16797 +       nf_reset(skb);
16798         pkt_len = skb->len;
16799         err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, 
16800                       skb->dst->dev, dst_output);
16801 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/Kconfig linux-2.6.6/net/ipv6/netfilter/Kconfig
16802 --- linux-2.6.6.org/net/ipv6/netfilter/Kconfig  2004-05-10 04:33:13.000000000 +0200
16803 +++ linux-2.6.6/net/ipv6/netfilter/Kconfig      2004-05-18 12:39:55.000000000 +0200
16804 @@ -230,5 +230,107 @@
16805           <file:Documentation/modules.txt>.  If unsure, say `N'.
16806           help
16807  
16808 +config IP6_NF_TARGET_HL
16809 +       tristate  'HL target support'
16810 +       depends on IP6_NF_MANGLE
16811 +       help
16812 +         This option adds a `HL' target, which allows you to modify the value of
16813 +         IPv6 Hop Limit field.
16814 +       
16815 +         If you want to compile it as a module, say M here and read
16816 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16817 +
16818 +config IP6_NF_TARGET_REJECT
16819 +       tristate  'REJECT target support'
16820 +       depends on IP6_NF_FILTER
16821 +       help
16822 +         The REJECT target allows a filtering rule to specify that an ICMPv6
16823 +         error should be issued in response to an incoming packet, rather
16824 +         than silently being dropped.
16825 +       
16826 +         If you want to compile it as a module, say M here and read
16827 +         Documentation/modules.txt.  If unsure, say `N'.
16828 +
16829 +config IP6_NF_MATCH_FUZZY
16830 +       tristate  'Fuzzy match support'
16831 +       depends on IP6_NF_FILTER
16832 +       help
16833 +         This option adds a `fuzzy' match, which allows you to match
16834 +         packets according to a fuzzy logic based law.
16835 +       
16836 +         If you want to compile it as a module, say M here and read
16837 +         Documentation/modules.txt.  If unsure, say `N'.
16838 +
16839 +config IP6_NF_MATCH_NTH
16840 +       tristate  'Nth match support'
16841 +       depends on IP6_NF_IPTABLES
16842 +       help
16843 +         This option adds a `Nth' match, which allow you to make
16844 +         rules that match every Nth packet.  By default there are 
16845 +         16 different counters.
16846 +       
16847 +         [options]
16848 +          --every     Nth              Match every Nth packet
16849 +         [--counter]  num              Use counter 0-15 (default:0)
16850 +         [--start]    num              Initialize the counter at the number 'num'
16851 +                                       instead of 0. Must be between 0 and Nth-1
16852 +         [--packet]   num              Match on 'num' packet. Must be between 0
16853 +                                       and Nth-1.
16854 +       
16855 +                                       If --packet is used for a counter than
16856 +                                       there must be Nth number of --packet
16857 +                                       rules, covering all values between 0 and
16858 +                                       Nth-1 inclusively.
16859 +        
16860 +         If you want to compile it as a module, say M here and read
16861 +         Documentation/modules.txt.  If unsure, say `N'.
16862 +
16863 +config IP6_NF_MATCH_RANDOM
16864 +       tristate  'Random match support'
16865 +       depends on IP6_NF_IPTABLES
16866 +       help
16867 +         This option adds a `random' match,
16868 +         which allow you to match packets randomly
16869 +         following a given probability.
16870 +        
16871 +         If you want to compile it as a module, say M here and read
16872 +         Documentation/modules.txt.  If unsure, say `N'.
16873 +
16874 +config IP6_NF_TARGET_ROUTE
16875 +       tristate '    ROUTE target support'
16876 +       depends on IP6_NF_MANGLE
16877 +       help
16878 +         This option adds a `ROUTE' target, which enables you to setup unusual
16879 +         routes. The ROUTE target is also able to change the incoming interface
16880 +         of a packet.
16881 +       
16882 +         The target can be or not a final target. It has to be used inside the 
16883 +         mangle table.
16884 +         
16885 +         Not working as a module.
16886 +
16887 +config IP6_NF_TARGET_TRACE
16888 +       tristate  'TRACE target support'
16889 +       depends on IP6_NF_RAW
16890 +       help
16891 +         The TRACE target allows packets to be traced as those
16892 +         matches any subsequent rule in any table/rule. The matched
16893 +         rule and the packet is logged with the prefix
16894 +       
16895 +         TRACE: tablename/chainname/rulenum  
16896 +       
16897 +         If you want to compile it as a module, say M here and read
16898 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16899 +
16900 +config IP6_NF_MATCH_POLICY
16901 +       tristate "IPsec policy match support"
16902 +       depends on IP6_NF_IPTABLES && XFRM
16903 +       help
16904 +         Policy matching allows you to match packets based on the
16905 +         IPsec policy that was used during decapsulation/will
16906 +         be used during encapsulation.
16907 +
16908 +         To compile it as a module, choose M here.  If unsure, say N.
16909 +
16910  endmenu
16911  
16912 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/Makefile linux-2.6.6/net/ipv6/netfilter/Makefile
16913 --- linux-2.6.6.org/net/ipv6/netfilter/Makefile 2004-05-10 04:32:39.000000000 +0200
16914 +++ linux-2.6.6/net/ipv6/netfilter/Makefile     2004-05-18 12:39:55.000000000 +0200
16915 @@ -8,18 +8,28 @@
16916  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
16917  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
16918  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
16919 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
16920  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
16921  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
16922  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
16923  obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
16924  obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
16925 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
16926  obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
16927  obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
16928  obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
16929  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16930  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
16931  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
16932 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
16933 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
16934  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
16935  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
16936 +
16937 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
16938 +
16939 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
16940 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
16941  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
16942 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
16943  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
16944 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.6/net/ipv6/netfilter/ip6_tables.c
16945 --- linux-2.6.6.org/net/ipv6/netfilter/ip6_tables.c     2004-05-10 04:33:19.000000000 +0200
16946 +++ linux-2.6.6/net/ipv6/netfilter/ip6_tables.c 2004-05-18 12:38:32.000000000 +0200
16947 @@ -38,6 +38,14 @@
16948  #define IPV6_HDR_LEN   (sizeof(struct ipv6hdr))
16949  #define IPV6_OPTHDR_LEN        (sizeof(struct ipv6_opt_hdr))
16950  
16951 +static const char *hook6names[] = { 
16952 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
16953 +       [NF_IP6_LOCAL_IN] "INPUT",
16954 +       [NF_IP6_FORWARD] "FORWARD",
16955 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
16956 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
16957 +};
16958 +
16959  /*#define DEBUG_IP_FIREWALL*/
16960  /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
16961  /*#define DEBUG_IP_FIREWALL_USER*/
16962 @@ -408,6 +416,12 @@
16963  
16964                         t = ip6t_get_target(e);
16965                         IP_NF_ASSERT(t->u.kernel.target);
16966 +
16967 +                       /* The packet traced and the rule isn't an unconditional return/END. */
16968 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
16969 +                               nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
16970 +                                             table->name, e->chainname, e->rulenum);
16971 +                       }
16972                         /* Standard target? */
16973                         if (!t->u.kernel.target->target) {
16974                                 int v;
16975 @@ -561,6 +575,29 @@
16976         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
16977  }
16978  
16979 +static inline int
16980 +find_error_target(struct ip6t_entry *s, 
16981 +                 struct ip6t_entry *e,
16982 +                 char **chainname)
16983 +{
16984 +       struct ip6t_entry_target *t;
16985 +       static struct ip6t_entry *found = NULL;
16986 +
16987 +       if (s == e) {
16988 +               if (!found)
16989 +                       return 0;
16990 +               t = ip6t_get_target(found);
16991 +               if (strcmp(t->u.user.name, 
16992 +                          IP6T_ERROR_TARGET) == 0) {
16993 +                       *chainname = t->data;
16994 +                       return 1;
16995 +               }
16996 +       } else
16997 +               found = s;
16998 +       
16999 +       return 0;
17000 +}
17001 +
17002  /* All zeroes == unconditional rule. */
17003  static inline int
17004  unconditional(const struct ip6t_ip6 *ipv6)
17005 @@ -580,6 +617,8 @@
17006  mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
17007  {
17008         unsigned int hook;
17009 +       char *chainname = NULL;
17010 +       u_int32_t rulenum;
17011  
17012         /* No recursion; use packet counter to save back ptrs (reset
17013            to 0 as we leave), and comefrom to save source hook bitmask */
17014 @@ -593,6 +632,8 @@
17015  
17016                 /* Set initial back pointer. */
17017                 e->counters.pcnt = pos;
17018 +               rulenum = 1;
17019 +               chainname = (char *) hook6names[hook];
17020  
17021                 for (;;) {
17022                         struct ip6t_standard_target *t
17023 @@ -605,6 +646,8 @@
17024                         }
17025                         e->comefrom
17026                                 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
17027 +                       e->rulenum = rulenum++;
17028 +                       e->chainname = chainname;
17029  
17030                         /* Unconditional return/END. */
17031                         if (e->target_offset == sizeof(struct ip6t_entry)
17032 @@ -614,6 +657,10 @@
17033                             && unconditional(&e->ipv6)) {
17034                                 unsigned int oldpos, size;
17035  
17036 +                               /* Set unconditional rulenum to zero. */
17037 +                               e->rulenum = 0;
17038 +                               e->counters.bcnt = 0;
17039 +
17040                                 /* Return: backtrack through the last
17041                                    big jump. */
17042                                 do {
17043 @@ -639,6 +686,11 @@
17044                                                 (newinfo->entries + pos);
17045                                 } while (oldpos == pos + e->next_offset);
17046  
17047 +                               /* Restore chainname, rulenum. */
17048 +                               chainname = e->chainname;
17049 +                               rulenum = e->counters.bcnt;
17050 +                               e->counters.bcnt = 0;
17051 +
17052                                 /* Move along one */
17053                                 size = e->next_offset;
17054                                 e = (struct ip6t_entry *)
17055 @@ -654,6 +706,17 @@
17056                                         /* This a jump; chase it. */
17057                                         duprintf("Jump rule %u -> %u\n",
17058                                                  pos, newpos);
17059 +                                       e->counters.bcnt = rulenum++;
17060 +                                       rulenum = 1;
17061 +                                       e = (struct ip6t_entry *)
17062 +                                               (newinfo->entries + newpos);
17063 +                                       if (IP6T_ENTRY_ITERATE(newinfo->entries,
17064 +                                                              newinfo->size,
17065 +                                                              find_error_target,
17066 +                                                              e, &chainname) == 0) {
17067 +                                               printk("ip6_tables: table screwed up!\n");
17068 +                                               return 0;
17069 +                                       }
17070                                 } else {
17071                                         /* ... this is a fallthru */
17072                                         newpos = pos + e->next_offset;
17073 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.6/net/ipv6/netfilter/ip6t_HL.c
17074 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_HL.c        1970-01-01 01:00:00.000000000 +0100
17075 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_HL.c    2004-05-18 12:35:59.000000000 +0200
17076 @@ -0,0 +1,105 @@
17077 +/* 
17078 + * Hop Limit modification target for ip6tables
17079 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
17080 + * Based on HW's TTL module
17081 + *
17082 + * This software is distributed under the terms of GNU GPL
17083 + */
17084 +
17085 +#include <linux/module.h>
17086 +#include <linux/skbuff.h>
17087 +#include <linux/ip.h>
17088 +
17089 +#include <linux/netfilter_ipv6/ip6_tables.h>
17090 +#include <linux/netfilter_ipv6/ip6t_HL.h>
17091 +
17092 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
17093 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
17094 +MODULE_LICENSE("GPL");
17095 +
17096 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
17097 +               const struct net_device *in, const struct net_device *out,
17098 +               const void *targinfo, void *userinfo)
17099 +{
17100 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
17101 +       const struct ip6t_HL_info *info = targinfo;
17102 +       u_int16_t diffs[2];
17103 +       int new_hl;
17104 +                        
17105 +       switch (info->mode) {
17106 +               case IP6T_HL_SET:
17107 +                       new_hl = info->hop_limit;
17108 +                       break;
17109 +               case IP6T_HL_INC:
17110 +                       new_hl = ip6h->hop_limit + info->hop_limit;
17111 +                       if (new_hl > 255)
17112 +                               new_hl = 255;
17113 +                       break;
17114 +               case IP6T_HL_DEC:
17115 +                       new_hl = ip6h->hop_limit + info->hop_limit;
17116 +                       if (new_hl < 0)
17117 +                               new_hl = 0;
17118 +                       break;
17119 +               default:
17120 +                       new_hl = ip6h->hop_limit;
17121 +                       break;
17122 +       }
17123 +
17124 +       if (new_hl != ip6h->hop_limit) {
17125 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
17126 +               ip6h->hop_limit = new_hl;
17127 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
17128 +       }
17129 +
17130 +       return IP6T_CONTINUE;
17131 +}
17132 +
17133 +static int ip6t_hl_checkentry(const char *tablename,
17134 +               const struct ip6t_entry *e,
17135 +               void *targinfo,
17136 +               unsigned int targinfosize,
17137 +               unsigned int hook_mask)
17138 +{
17139 +       struct ip6t_HL_info *info = targinfo;
17140 +
17141 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
17142 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
17143 +                               targinfosize,
17144 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
17145 +               return 0;       
17146 +       }       
17147 +
17148 +       if (strcmp(tablename, "mangle")) {
17149 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
17150 +               return 0;
17151 +       }
17152 +
17153 +       if (info->mode > IP6T_HL_MAXMODE) {
17154 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
17155 +                       info->mode);
17156 +               return 0;
17157 +       }
17158 +
17159 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
17160 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
17161 +               return 0;
17162 +       }
17163 +       
17164 +       return 1;
17165 +}
17166 +
17167 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
17168 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
17169 +
17170 +static int __init init(void)
17171 +{
17172 +       return ip6t_register_target(&ip6t_HL);
17173 +}
17174 +
17175 +static void __exit fini(void)
17176 +{
17177 +       ip6t_unregister_target(&ip6t_HL);
17178 +}
17179 +
17180 +module_init(init);
17181 +module_exit(fini);
17182 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.6/net/ipv6/netfilter/ip6t_REJECT.c
17183 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_REJECT.c    1970-01-01 01:00:00.000000000 +0100
17184 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_REJECT.c        2004-05-18 12:36:05.000000000 +0200
17185 @@ -0,0 +1,458 @@
17186 +/*
17187 + * IP6 tables REJECT target module
17188 + * Linux INET6 implementation
17189 + *
17190 + * Copyright (C)2003 USAGI/WIDE Project
17191 + *
17192 + * Authors:
17193 + *     Yasuyuki Kozakai        <yasuyuki.kozakai@toshiba.co.jp>
17194 + *
17195 + * Based on net/ipv4/netfilter/ipt_REJECT.c
17196 + *
17197 + * This program is free software; you can redistribute it and/or
17198 + * modify it under the terms of the GNU General Public License
17199 + * as published by the Free Software Foundation; either version
17200 + * 2 of the License, or (at your option) any later version.
17201 + */
17202 +
17203 +#include <linux/config.h>
17204 +#include <linux/module.h>
17205 +#include <linux/skbuff.h>
17206 +#include <linux/icmpv6.h>
17207 +#include <net/ipv6.h>
17208 +#include <net/tcp.h>
17209 +#include <net/icmp.h>
17210 +#include <net/ip6_fib.h>
17211 +#include <net/ip6_route.h>
17212 +#include <net/flow.h>
17213 +#include <linux/netfilter_ipv6/ip6_tables.h>
17214 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
17215 +
17216 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
17217 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
17218 +MODULE_LICENSE("GPL");
17219 +
17220 +#if 0
17221 +#define DEBUGP printk
17222 +#else
17223 +#define DEBUGP(format, args...)
17224 +#endif
17225 +
17226 +#if 0
17227 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
17228 +{
17229 +       void (*attach)(struct sk_buff *, struct nf_ct_info *);
17230 +       if (nfct && (attach = ip6_ct_attach) != NULL) {
17231 +               mb();
17232 +               attach(new_skb, nfct);
17233 +       }
17234 +}
17235 +#endif
17236 +
17237 +static int maybe_reroute(struct sk_buff *skb)
17238 +{
17239 +       if (skb->nfcache & NFC_ALTERED){
17240 +               if (ip6_route_me_harder(skb) != 0){
17241 +                       kfree_skb(skb);
17242 +                       return -EINVAL;
17243 +               }
17244 +       }
17245 +
17246 +       return dst_output(skb);
17247 +}
17248 +
17249 +/* Send RST reply */
17250 +static void send_reset(struct sk_buff *oldskb)
17251 +{
17252 +       struct sk_buff *nskb;
17253 +       struct tcphdr otcph, *tcph;
17254 +       unsigned int otcplen, tcphoff, hh_len;
17255 +       int needs_ack;
17256 +       struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
17257 +       struct dst_entry *dst = NULL;
17258 +       u8 proto;
17259 +       struct flowi fl;
17260 +       proto = oip6h->nexthdr;
17261 +       int err;
17262 +
17263 +       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
17264 +           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
17265 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
17266 +               return;
17267 +       }
17268 +
17269 +       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
17270 +                                  &proto, oldskb->len - ((u8*)(oip6h+1)
17271 +                                                         - oldskb->data));
17272 +
17273 +       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
17274 +               DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
17275 +               return;
17276 +       }
17277 +
17278 +       otcplen = oldskb->len - tcphoff;
17279 +
17280 +       /* IP header checks: fragment, too short. */
17281 +       if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
17282 +               DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
17283 +                       proto, otcplen);
17284 +               return;
17285 +       }
17286 +
17287 +       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
17288 +               if (net_ratelimit())
17289 +                       printk("ip6t_REJECT: Can't copy tcp header\n");
17290 +               return;
17291 +       }
17292 +
17293 +       /* No RST for RST. */
17294 +       if (otcph.rst) {
17295 +               DEBUGP("ip6t_REJECT: RST is set\n");
17296 +               return;
17297 +       }
17298 +
17299 +       /* Check checksum. */
17300 +       if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
17301 +                           skb_checksum(oldskb, tcphoff, otcplen, 0))) {
17302 +               DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
17303 +               return;
17304 +       }
17305 +
17306 +       memset(&fl, 0, sizeof(fl));
17307 +       fl.proto = IPPROTO_TCP;
17308 +       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
17309 +       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
17310 +       fl.fl_ip_sport = otcph.dest;
17311 +       fl.fl_ip_dport = otcph.source;
17312 +       err = ip6_dst_lookup(NULL, &dst, &fl);
17313 +       if (err) {
17314 +               if (net_ratelimit())
17315 +                       printk("ip6t_REJECT: can't find dst. err = %d\n", err);
17316 +               return;
17317 +       }
17318 +
17319 +       hh_len = (dst->dev->hard_header_len + 15)&~15;
17320 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
17321 +                        + sizeof(struct tcphdr) + dst->trailer_len,
17322 +                        GFP_ATOMIC);
17323 +
17324 +       if (!nskb) {
17325 +               if (net_ratelimit())
17326 +                       printk("ip6t_REJECT: Can't alloc skb\n");
17327 +               dst_release(dst);
17328 +               return;
17329 +       }
17330 +
17331 +       nskb->dst = dst;
17332 +       dst_hold(dst);
17333 +
17334 +       skb_reserve(nskb, hh_len + dst->header_len);
17335 +
17336 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17337 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
17338 +       ip6h->version = 6;
17339 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17340 +       ip6h->nexthdr = IPPROTO_TCP;
17341 +       ip6h->payload_len = htons(sizeof(struct tcphdr));
17342 +       ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
17343 +       ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
17344 +
17345 +       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
17346 +       /* Truncate to length (no data) */
17347 +       tcph->doff = sizeof(struct tcphdr)/4;
17348 +       tcph->source = otcph.dest;
17349 +       tcph->dest = otcph.source;
17350 +
17351 +       if (otcph.ack) {
17352 +               needs_ack = 0;
17353 +               tcph->seq = otcph.ack_seq;
17354 +               tcph->ack_seq = 0;
17355 +       } else {
17356 +               needs_ack = 1;
17357 +               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
17358 +                                     + otcplen - (otcph.doff<<2));
17359 +               tcph->seq = 0;
17360 +       }
17361 +
17362 +       /* Reset flags */
17363 +       ((u_int8_t *)tcph)[13] = 0;
17364 +       tcph->rst = 1;
17365 +       tcph->ack = needs_ack;
17366 +       tcph->window = 0;
17367 +       tcph->urg_ptr = 0;
17368 +       tcph->check = 0;
17369 +
17370 +       /* Adjust TCP checksum */
17371 +       tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
17372 +                                     &nskb->nh.ipv6h->daddr,
17373 +                                     sizeof(struct tcphdr), IPPROTO_TCP,
17374 +                                     csum_partial((char *)tcph,
17375 +                                                  sizeof(struct tcphdr), 0));
17376 +
17377 +#if 0
17378 +       connection_attach(nskb, oldskb->nfct);
17379 +#endif
17380 +
17381 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17382 +               maybe_reroute);
17383 +
17384 +       dst_release(dst);
17385 +}
17386 +
17387 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
17388 +{
17389 +       struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
17390 +       struct icmp6hdr *icmp6h;
17391 +       struct dst_entry *dst = NULL;
17392 +       struct rt6_info *rt;
17393 +       int tmo;
17394 +       __u32 csum;
17395 +       unsigned int len, datalen, hh_len;
17396 +       int saddr_type, daddr_type;
17397 +       unsigned int ptr, ip6off;
17398 +       u8 proto;
17399 +       struct flowi fl;
17400 +       struct sk_buff *nskb;
17401 +       char *data;
17402 +
17403 +       saddr_type = ipv6_addr_type(&hdr->saddr);
17404 +       daddr_type = ipv6_addr_type(&hdr->daddr);
17405 +
17406 +       if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
17407 +           (!(daddr_type & IPV6_ADDR_UNICAST))) {
17408 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
17409 +               return;
17410 +       }
17411 +
17412 +       ip6off = skb_in->nh.raw - skb_in->data;
17413 +       proto = hdr->nexthdr;
17414 +       ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
17415 +                              skb_in->len - ip6off);
17416 +
17417 +       if ((ptr < 0) || (ptr > skb_in->len)) {
17418 +               ptr = ip6off + sizeof(struct ipv6hdr);
17419 +               proto = hdr->nexthdr;
17420 +       } else if (proto == IPPROTO_ICMPV6) {
17421 +                u8 type;
17422 +
17423 +                if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
17424 +                                                     icmp6_type), &type, 1)) {
17425 +                       DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
17426 +                       return;
17427 +               }
17428 +
17429 +               if (!(type & ICMPV6_INFOMSG_MASK)) {
17430 +                       DEBUGP("ip6t_REJECT: no reply to icmp error\n");
17431 +                       return;
17432 +               }
17433 +        } else if (proto == IPPROTO_UDP) {
17434 +               int plen = skb_in->len - (ptr - ip6off);
17435 +               uint16_t check;
17436 +
17437 +               if (plen < sizeof(struct udphdr)) {
17438 +                       DEBUGP("ip6t_REJECT: too short\n");
17439 +                       return;
17440 +               }
17441 +
17442 +               if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
17443 +                                 &check, 2)) {
17444 +                       if (net_ratelimit())
17445 +                               printk("ip6t_REJECT: can't get copy from skb");
17446 +                       return;
17447 +               }
17448 +
17449 +               if (check &&
17450 +                   csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
17451 +                                   IPPROTO_UDP,
17452 +                                   skb_checksum(skb_in, ptr, plen, 0))) {
17453 +                       DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
17454 +                       return;
17455 +               }
17456 +       }
17457 +
17458 +       memset(&fl, 0, sizeof(fl));
17459 +       fl.proto = IPPROTO_ICMPV6;
17460 +       ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
17461 +       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
17462 +       fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
17463 +       fl.fl_icmp_code = code;
17464 +
17465 +       if (ip6_dst_lookup(NULL, &dst, &fl)) {
17466 +               return;
17467 +       }
17468 +
17469 +       rt = (struct rt6_info *)dst;
17470 +       tmo = 1*HZ;
17471 +
17472 +       if (rt->rt6i_dst.plen < 128)
17473 +               tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
17474 +
17475 +       if (!xrlim_allow(dst, tmo)) {
17476 +               if (net_ratelimit())
17477 +                       printk("ip6t_REJECT: rate limitted\n");
17478 +               goto dst_release_out;
17479 +       }
17480 +
17481 +       len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
17482 +
17483 +       if (len > dst_pmtu(dst))
17484 +               len = dst_pmtu(dst);
17485 +       if (len > IPV6_MIN_MTU)
17486 +               len = IPV6_MIN_MTU;
17487 +
17488 +       datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
17489 +       hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
17490 +
17491 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
17492 +                        GFP_ATOMIC);
17493 +
17494 +       if (!nskb) {
17495 +               if (net_ratelimit())
17496 +                       printk("ip6t_REJECT: can't alloc skb\n");
17497 +               goto dst_release_out;
17498 +       }
17499 +
17500 +       nskb->priority = 0;
17501 +       nskb->dst = dst;
17502 +       dst_hold(dst);
17503 +
17504 +       skb_reserve(nskb, hh_len + dst->header_len);
17505 +
17506 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17507 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
17508 +       ip6h->version = 6;
17509 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17510 +       ip6h->nexthdr = IPPROTO_ICMPV6;
17511 +       ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
17512 +       ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
17513 +       ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
17514 +
17515 +       icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
17516 +       icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
17517 +       icmp6h->icmp6_code = code;
17518 +       icmp6h->icmp6_cksum = 0;
17519 +
17520 +       data = skb_put(nskb, datalen);
17521 +
17522 +       csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
17523 +       csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
17524 +       icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
17525 +                                            datalen + sizeof(struct icmp6hdr),
17526 +                                            IPPROTO_ICMPV6, csum);
17527 +
17528 +#if 0
17529 +       connection_attach(nskb, skb_in->nfct);
17530 +#endif
17531 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17532 +               maybe_reroute);
17533 +
17534 +dst_release_out:
17535 +       dst_release(dst);
17536 +}
17537 +
17538 +static unsigned int reject6_target(struct sk_buff **pskb,
17539 +                          unsigned int hooknum,
17540 +                          const struct net_device *in,
17541 +                          const struct net_device *out,
17542 +                          const void *targinfo,
17543 +                          void *userinfo)
17544 +{
17545 +       const struct ip6t_reject_info *reject = targinfo;
17546 +
17547 +       DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
17548 +       /* WARNING: This code causes reentry within ip6tables.
17549 +          This means that the ip6tables jump stack is now crap.  We
17550 +          must return an absolute verdict. --RR */
17551 +       switch (reject->with) {
17552 +       case IP6T_ICMP6_NO_ROUTE:
17553 +               send_unreach(*pskb, ICMPV6_NOROUTE);
17554 +               break;
17555 +       case IP6T_ICMP6_ADM_PROHIBITED:
17556 +               send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
17557 +               break;
17558 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
17559 +               send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
17560 +               break;
17561 +       case IP6T_ICMP6_ADDR_UNREACH:
17562 +               send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
17563 +               break;
17564 +       case IP6T_ICMP6_PORT_UNREACH:
17565 +               send_unreach(*pskb, ICMPV6_PORT_UNREACH);
17566 +               break;
17567 +       case IP6T_ICMP6_ECHOREPLY:
17568 +               /* Do nothing */
17569 +               break;
17570 +       case IP6T_TCP_RESET:
17571 +               send_reset(*pskb);
17572 +               break;
17573 +       default:
17574 +               if (net_ratelimit())
17575 +                       printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
17576 +               break;
17577 +       }
17578 +
17579 +       return NF_DROP;
17580 +}
17581 +
17582 +static int check(const char *tablename,
17583 +                const struct ip6t_entry *e,
17584 +                void *targinfo,
17585 +                unsigned int targinfosize,
17586 +                unsigned int hook_mask)
17587 +{
17588 +       const struct ip6t_reject_info *rejinfo = targinfo;
17589 +
17590 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
17591 +               DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
17592 +               return 0;
17593 +       }
17594 +
17595 +       /* Only allow these for packet filtering. */
17596 +       if (strcmp(tablename, "filter") != 0) {
17597 +               DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
17598 +               return 0;
17599 +       }
17600 +
17601 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
17602 +                          | (1 << NF_IP6_FORWARD)
17603 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
17604 +               DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
17605 +               return 0;
17606 +       }
17607 +
17608 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
17609 +               printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
17610 +               return 0;
17611 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
17612 +               /* Must specify that it's a TCP packet */
17613 +               if (e->ipv6.proto != IPPROTO_TCP
17614 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
17615 +                       DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
17616 +                       return 0;
17617 +               }
17618 +       }
17619 +
17620 +       return 1;
17621 +}
17622 +
17623 +static struct ip6t_target ip6t_reject_reg = {
17624 +       .name           = "REJECT",
17625 +       .target         = reject6_target,
17626 +       .checkentry     = check,
17627 +       .me             = THIS_MODULE
17628 +};
17629 +
17630 +static int __init init(void)
17631 +{
17632 +       if (ip6t_register_target(&ip6t_reject_reg))
17633 +               return -EINVAL;
17634 +       return 0;
17635 +}
17636 +
17637 +static void __exit fini(void)
17638 +{
17639 +       ip6t_unregister_target(&ip6t_reject_reg);
17640 +}
17641 +
17642 +module_init(init);
17643 +module_exit(fini);
17644 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.6/net/ipv6/netfilter/ip6t_ROUTE.c
17645 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_ROUTE.c     1970-01-01 01:00:00.000000000 +0100
17646 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_ROUTE.c 2004-05-18 12:38:20.000000000 +0200
17647 @@ -0,0 +1,289 @@
17648 +/*
17649 + * This implements the ROUTE v6 target, which enables you to setup unusual
17650 + * routes not supported by the standard kernel routing table.
17651 + *
17652 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
17653 + *
17654 + * v 1.0 2003/08/05
17655 + *
17656 + * This software is distributed under GNU GPL v2, 1991
17657 + */
17658 +
17659 +#include <linux/module.h>
17660 +#include <linux/skbuff.h>
17661 +#include <linux/ipv6.h>
17662 +#include <linux/netfilter_ipv6/ip6_tables.h>
17663 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
17664 +#include <linux/netdevice.h>
17665 +#include <net/ipv6.h>
17666 +#include <net/ndisc.h>
17667 +#include <net/ip6_route.h>
17668 +#include <linux/icmpv6.h>
17669 +
17670 +#if 1
17671 +#define DEBUGP printk
17672 +#else
17673 +#define DEBUGP(format, args...)
17674 +#endif
17675 +
17676 +#define NIP6(addr) \
17677 +       ntohs((addr).s6_addr16[0]), \
17678 +       ntohs((addr).s6_addr16[1]), \
17679 +       ntohs((addr).s6_addr16[2]), \
17680 +       ntohs((addr).s6_addr16[3]), \
17681 +       ntohs((addr).s6_addr16[4]), \
17682 +       ntohs((addr).s6_addr16[5]), \
17683 +       ntohs((addr).s6_addr16[6]), \
17684 +       ntohs((addr).s6_addr16[7])
17685 +
17686 +/* Route the packet according to the routing keys specified in
17687 + * route_info. Keys are :
17688 + *  - ifindex : 
17689 + *      0 if no oif preferred, 
17690 + *      otherwise set to the index of the desired oif
17691 + *  - route_info->gw :
17692 + *      0 if no gateway specified,
17693 + *      otherwise set to the next host to which the pkt must be routed
17694 + * If success, skb->dev is the output device to which the packet must 
17695 + * be sent and skb->dst is not NULL
17696 + *
17697 + * RETURN:  1 if the packet was succesfully routed to the 
17698 + *            destination desired
17699 + *          0 if the kernel routing table could not route the packet
17700 + *            according to the keys specified
17701 + */
17702 +static int 
17703 +route6(struct sk_buff *skb,
17704 +       unsigned int ifindex,
17705 +       const struct ip6t_route_target_info *route_info)
17706 +{
17707 +       struct rt6_info *rt = NULL;
17708 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17709 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17710 +
17711 +       DEBUGP("ip6t_ROUTE: called with: ");
17712 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
17713 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
17714 +       DEBUGP("OUT=%s\n", route_info->oif);
17715 +       
17716 +       if (ipv6_addr_any(gw))
17717 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
17718 +       else
17719 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
17720 +
17721 +       if (!rt)
17722 +               goto no_route;
17723 +
17724 +       DEBUGP("ip6t_ROUTE: routing gives: ");
17725 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
17726 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
17727 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
17728 +
17729 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
17730 +               goto wrong_route;
17731 +       
17732 +       if (!rt->rt6i_nexthop) {
17733 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
17734 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
17735 +       }
17736 +
17737 +       /* Drop old route. */
17738 +       dst_release(skb->dst);
17739 +       skb->dst = &rt->u.dst;
17740 +       skb->dev = rt->rt6i_dev;
17741 +       return 1;
17742 +
17743 + wrong_route:
17744 +       dst_release(&rt->u.dst);
17745 + no_route:
17746 +       if (!net_ratelimit())
17747 +               return 0;
17748 +
17749 +       printk("ip6t_ROUTE: no explicit route found ");
17750 +       if (ifindex)
17751 +               printk("via interface %s ", route_info->oif);
17752 +       if (!ipv6_addr_any(gw))
17753 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
17754 +       printk("\n");
17755 +       return 0;
17756 +}
17757 +
17758 +
17759 +/* Stolen from ip6_output_finish
17760 + * PRE : skb->dev is set to the device we are leaving by
17761 + *       skb->dst is not NULL
17762 + * POST: the packet is sent with the link layer header pushed
17763 + *       the packet is destroyed
17764 + */
17765 +static void ip_direct_send(struct sk_buff *skb)
17766 +{
17767 +       struct dst_entry *dst = skb->dst;
17768 +       struct hh_cache *hh = dst->hh;
17769 +
17770 +       if (hh) {
17771 +               read_lock_bh(&hh->hh_lock);
17772 +               memcpy(skb->data - 16, hh->hh_data, 16);
17773 +               read_unlock_bh(&hh->hh_lock);
17774 +               skb_push(skb, hh->hh_len);
17775 +               hh->hh_output(skb);
17776 +       } else if (dst->neighbour)
17777 +               dst->neighbour->output(skb);
17778 +       else {
17779 +               if (net_ratelimit())
17780 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
17781 +               kfree_skb(skb);
17782 +       }
17783 +}
17784 +
17785 +
17786 +static unsigned int 
17787 +route6_oif(const struct ip6t_route_target_info *route_info,
17788 +          struct sk_buff *skb) 
17789 +{
17790 +       unsigned int ifindex = 0;
17791 +       struct net_device *dev_out = NULL;
17792 +
17793 +       /* The user set the interface name to use.
17794 +        * Getting the current interface index.
17795 +        */
17796 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
17797 +               ifindex = dev_out->ifindex;
17798 +       } else {
17799 +               /* Unknown interface name : packet dropped */
17800 +               if (net_ratelimit()) 
17801 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
17802 +
17803 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17804 +                       return IP6T_CONTINUE;
17805 +               else
17806 +                       return NF_DROP;
17807 +       }
17808 +
17809 +       /* Trying the standard way of routing packets */
17810 +       if (route6(skb, ifindex, route_info)) {
17811 +               dev_put(dev_out);
17812 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17813 +                       return IP6T_CONTINUE;
17814 +               
17815 +               ip_direct_send(skb);
17816 +               return NF_STOLEN;
17817 +       } else 
17818 +               return NF_DROP;
17819 +}
17820 +
17821 +
17822 +static unsigned int 
17823 +route6_gw(const struct ip6t_route_target_info *route_info,
17824 +         struct sk_buff *skb) 
17825 +{
17826 +       if (route6(skb, 0, route_info)) {
17827 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17828 +                       return IP6T_CONTINUE;
17829 +
17830 +               ip_direct_send(skb);
17831 +               return NF_STOLEN;
17832 +       } else
17833 +               return NF_DROP;
17834 +}
17835 +
17836 +
17837 +static unsigned int 
17838 +ip6t_route_target(struct sk_buff **pskb,
17839 +                 unsigned int hooknum,
17840 +                 const struct net_device *in,
17841 +                 const struct net_device *out,
17842 +                 const void *targinfo,
17843 +                 void *userinfo)
17844 +{
17845 +       const struct ip6t_route_target_info *route_info = targinfo;
17846 +       struct sk_buff *skb = *pskb;
17847 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17848 +
17849 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
17850 +               goto do_it;
17851 +
17852 +       /* If we are at PREROUTING or INPUT hook
17853 +        * the TTL isn't decreased by the IP stack
17854 +        */
17855 +       if (hooknum == NF_IP6_PRE_ROUTING ||
17856 +           hooknum == NF_IP6_LOCAL_IN) {
17857 +
17858 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17859 +
17860 +               if (ipv6h->hop_limit <= 1) {
17861 +                       /* Force OUTPUT device used as source address */
17862 +                       skb->dev = skb->dst->dev;
17863 +
17864 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
17865 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
17866 +
17867 +                       return NF_DROP;
17868 +               }
17869 +
17870 +               ipv6h->hop_limit--;
17871 +       }
17872 +
17873 +
17874 + do_it:
17875 +       if (route_info->oif[0]) 
17876 +               return route6_oif(route_info, *pskb);
17877 +       
17878 +       if (!ipv6_addr_any(gw))
17879 +               return route6_gw(route_info, *pskb);
17880 +
17881 +       if (net_ratelimit()) 
17882 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
17883 +
17884 +       return IP6T_CONTINUE;
17885 +}
17886 +
17887 +
17888 +static int 
17889 +ip6t_route_checkentry(const char *tablename,
17890 +                     const struct ip6t_entry *e,
17891 +                     void *targinfo,
17892 +                     unsigned int targinfosize,
17893 +                     unsigned int hook_mask)
17894 +{
17895 +       if (strcmp(tablename, "mangle") != 0) {
17896 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
17897 +               return 0;
17898 +       }
17899 +
17900 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
17901 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
17902 +                      targinfosize,
17903 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
17904 +               return 0;
17905 +       }
17906 +
17907 +       return 1;
17908 +}
17909 +
17910 +
17911 +static struct ip6t_target ip6t_route_reg = {
17912 +       .name       = "ROUTE",
17913 +       .target     = ip6t_route_target,
17914 +       .checkentry = ip6t_route_checkentry,
17915 +       .me         = THIS_MODULE
17916 +};
17917 +
17918 +
17919 +static int __init init(void)
17920 +{
17921 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
17922 +       if (ip6t_register_target(&ip6t_route_reg))
17923 +               return -EINVAL;
17924 +
17925 +       return 0;
17926 +}
17927 +
17928 +
17929 +static void __exit fini(void)
17930 +{
17931 +       ip6t_unregister_target(&ip6t_route_reg);
17932 +}
17933 +
17934 +module_init(init);
17935 +module_exit(fini);
17936 +MODULE_LICENSE("GPL");
17937 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.6/net/ipv6/netfilter/ip6t_TRACE.c
17938 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_TRACE.c     1970-01-01 01:00:00.000000000 +0100
17939 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_TRACE.c 2004-05-18 12:38:32.000000000 +0200
17940 @@ -0,0 +1,65 @@
17941 +/* This is a module which is used for setting
17942 + * the NFC_TRACE flag in the nfcache field of an skb. 
17943 + */
17944 +#include <linux/module.h>
17945 +#include <linux/skbuff.h>
17946 +
17947 +#include <linux/netfilter_ipv6/ip6_tables.h>
17948 +
17949 +MODULE_LICENSE("GPL");
17950 +
17951 +static unsigned int
17952 +target(struct sk_buff **pskb,
17953 +       unsigned int hooknum,
17954 +       const struct net_device *in,
17955 +       const struct net_device *out,
17956 +       const void *targinfo,
17957 +       void *userinfo)
17958 +{
17959 +       (*pskb)->nfcache |= NFC_TRACE;
17960 +       return IP6T_CONTINUE;
17961 +}
17962 +
17963 +static int 
17964 +checkentry(const char *tablename,
17965 +                  const struct ip6t_entry *e,
17966 +           void *targinfo,
17967 +           unsigned int targinfosize,
17968 +           unsigned int hook_mask)
17969 +{
17970 +       if (targinfosize != 0) {
17971 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17972 +                      targinfosize);
17973 +               return 0;
17974 +       }
17975 +
17976 +       if (strcmp(tablename, "raw") != 0) {
17977 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17978 +               return 0;
17979 +       }
17980 +
17981 +       return 1;
17982 +}
17983 +
17984 +static struct ip6t_target ip6t_trace_reg = { 
17985 +       .name = "TRACE",
17986 +       .target = target, 
17987 +       .checkentry = checkentry, 
17988 +       .me = THIS_MODULE
17989 +};
17990 +
17991 +static int __init init(void)
17992 +{
17993 +       if (ip6t_register_target(&ip6t_trace_reg))
17994 +               return -EINVAL;
17995 +
17996 +       return 0;
17997 +}
17998 +
17999 +static void __exit fini(void)
18000 +{
18001 +       ip6t_unregister_target(&ip6t_trace_reg);
18002 +}
18003 +
18004 +module_init(init);
18005 +module_exit(fini);
18006 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.6/net/ipv6/netfilter/ip6t_fuzzy.c
18007 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_fuzzy.c     1970-01-01 01:00:00.000000000 +0100
18008 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_fuzzy.c 2004-05-18 12:36:22.000000000 +0200
18009 @@ -0,0 +1,189 @@
18010 +/*
18011 + * This module implements a simple TSK FLC
18012 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
18013 + * to limit , in an adaptive and flexible way , the packet rate crossing
18014 + * a given stream . It serves as an initial and very simple (but effective)
18015 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
18016 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
18017 + * into our code in a precise , adaptive and efficient manner.
18018 + *  The goal is very similar to that of "limit" match , but using techniques of
18019 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
18020 + * avoiding over and undershoots - and stuff like that .
18021 + *
18022 + *
18023 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
18024 + * 2002-08-17  : Changed to eliminate floating point operations .
18025 + * 2002-08-23  : Coding style changes .
18026 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
18027 + */
18028 +
18029 +#include <linux/module.h>
18030 +#include <linux/skbuff.h>
18031 +#include <linux/ipv6.h>
18032 +#include <linux/random.h>
18033 +#include <net/tcp.h>
18034 +#include <linux/spinlock.h>
18035 +#include <linux/netfilter_ipv6/ip6_tables.h>
18036 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
18037 +
18038 +/*
18039 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
18040 + Expressed in percentage
18041 +*/
18042 +
18043 +#define PAR_LOW                1/100
18044 +#define PAR_HIGH       1
18045 +
18046 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
18047 +
18048 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
18049 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
18050 +MODULE_LICENSE("GPL");
18051 +
18052 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
18053 +{
18054 +       if (tx >= maxi) return 100;
18055 +
18056 +       if (tx <= mini) return 0;
18057 +
18058 +       return ((100 * (tx-mini)) / (maxi-mini));
18059 +}
18060 +
18061 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
18062 +{
18063 +       if (tx <= mini) return 100;
18064 +
18065 +       if (tx >= maxi) return 0;
18066 +
18067 +       return ((100 * (maxi - tx)) / (maxi - mini));
18068 +
18069 +}
18070 +
18071 +static int
18072 +ip6t_fuzzy_match(const struct sk_buff *pskb,
18073 +              const struct net_device *in,
18074 +              const struct net_device *out,
18075 +              const void *matchinfo,
18076 +              int offset,
18077 +              const void *hdr,
18078 +              u_int16_t datalen,
18079 +              int *hotdrop)
18080 +{
18081 +       /* From userspace */
18082 +
18083 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
18084 +
18085 +       u_int8_t random_number;
18086 +       unsigned long amount;
18087 +       u_int8_t howhigh, howlow;
18088 +
18089 +
18090 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
18091 +
18092 +       info->bytes_total += pskb->len;
18093 +       info->packets_total++;
18094 +
18095 +       info->present_time = jiffies;
18096 +
18097 +       if (info->present_time >= info->previous_time)
18098 +               amount = info->present_time - info->previous_time;
18099 +       else {
18100 +               /* There was a transition : I choose to re-sample
18101 +                  and keep the old acceptance rate...
18102 +               */
18103 +
18104 +               amount = 0;
18105 +               info->previous_time = info->present_time;
18106 +               info->bytes_total = info->packets_total = 0;
18107 +            };
18108 +
18109 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
18110 +
18111 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
18112 +                                       / amount);
18113 +
18114 +               info->previous_time = info->present_time;
18115 +               info->bytes_total = info->packets_total = 0;
18116 +
18117 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
18118 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
18119 +
18120 +               info->acceptance_rate = (u_int8_t) \
18121 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
18122 +
18123 +       /* In fact, the above defuzzification would require a denominator
18124 +        * proportional to (howhigh+howlow) but, in this particular case,
18125 +        * that expression is constant.
18126 +        * An imediate consequence is that it is not necessary to call
18127 +        * both mf_high and mf_low - but to keep things understandable,
18128 +        * I did so.
18129 +        */
18130 +
18131 +       }
18132 +
18133 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
18134 +
18135 +
18136 +       if (info->acceptance_rate < 100)
18137 +       {
18138 +               get_random_bytes((void *)(&random_number), 1);
18139 +
18140 +               /*  If within the acceptance , it can pass => don't match */
18141 +               if (random_number <= (255 * info->acceptance_rate) / 100)
18142 +                       return 0;
18143 +               else
18144 +                       return 1; /* It can't pass (It matches) */
18145 +       };
18146 +
18147 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
18148 +
18149 +}
18150 +
18151 +static int
18152 +ip6t_fuzzy_checkentry(const char *tablename,
18153 +                  const struct ip6t_ip6 *ip,
18154 +                  void *matchinfo,
18155 +                  unsigned int matchsize,
18156 +                  unsigned int hook_mask)
18157 +{
18158 +
18159 +       const struct ip6t_fuzzy_info *info = matchinfo;
18160 +
18161 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
18162 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
18163 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
18164 +               return 0;
18165 +       }
18166 +
18167 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
18168 +        || (info->minimum_rate >= info->maximum_rate)) {
18169 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
18170 +               return 0;
18171 +       }
18172 +
18173 +       return 1;
18174 +}
18175 +
18176 +static struct ip6t_match ip6t_fuzzy_reg = {
18177 +       {NULL, NULL},
18178 +       "fuzzy",
18179 +       ip6t_fuzzy_match,
18180 +       ip6t_fuzzy_checkentry,
18181 +       NULL,
18182 +       THIS_MODULE };
18183 +
18184 +static int __init init(void)
18185 +{
18186 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
18187 +               return -EINVAL;
18188 +
18189 +       return 0;
18190 +}
18191 +
18192 +static void __exit fini(void)
18193 +{
18194 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
18195 +}
18196 +
18197 +module_init(init);
18198 +module_exit(fini);
18199 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.6/net/ipv6/netfilter/ip6t_nth.c
18200 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_nth.c       1970-01-01 01:00:00.000000000 +0100
18201 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_nth.c   2004-05-18 12:36:40.000000000 +0200
18202 @@ -0,0 +1,173 @@
18203 +/*
18204 +  This is a module which is used for match support for every Nth packet
18205 +  This file is distributed under the terms of the GNU General Public
18206 +  License (GPL). Copies of the GPL can be obtained from:
18207 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
18208 +
18209 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18210 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
18211 +        * added support for multiple counters
18212 +        * added support for matching on individual packets
18213 +          in the counter cycle
18214 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18215 +
18216 +*/
18217 +
18218 +#include <linux/module.h>
18219 +#include <linux/skbuff.h>
18220 +#include <linux/ip.h>
18221 +#include <net/tcp.h>
18222 +#include <linux/spinlock.h>
18223 +#include <linux/netfilter_ipv6/ip6_tables.h>
18224 +#include <linux/netfilter_ipv6/ip6t_nth.h>
18225 +
18226 +MODULE_LICENSE("GPL");
18227 +
18228 +/*
18229 + * State information.
18230 + */
18231 +struct state {
18232 +       spinlock_t lock;
18233 +       u_int16_t number;
18234 +};
18235 +
18236 +static struct state states[IP6T_NTH_NUM_COUNTERS];
18237 +
18238 +static int
18239 +ip6t_nth_match(const struct sk_buff *pskb,
18240 +             const struct net_device *in,
18241 +             const struct net_device *out,
18242 +             const void *matchinfo,
18243 +             int offset,
18244 +             const void *hdr,
18245 +             u_int16_t datalen,
18246 +             int *hotdrop)
18247 +{
18248 +       /* Parameters from userspace */
18249 +       const struct ip6t_nth_info *info = matchinfo;
18250 +        unsigned counter = info->counter;
18251 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
18252 +       {
18253 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
18254 +               return 0;
18255 +        };
18256 +
18257 +        spin_lock(&states[counter].lock);
18258 +
18259 +        /* Are we matching every nth packet?*/
18260 +        if (info->packet == 0xFF)
18261 +        {
18262 +               /* We're matching every nth packet and only every nth packet*/
18263 +               /* Do we match or invert match? */
18264 +               if (info->not == 0)
18265 +               {
18266 +                       if (states[counter].number == 0)
18267 +                       {
18268 +                               ++states[counter].number;
18269 +                               goto match;
18270 +                       }
18271 +                       if (states[counter].number >= info->every)
18272 +                               states[counter].number = 0; /* reset the counter */
18273 +                       else
18274 +                               ++states[counter].number;
18275 +                       goto dontmatch;
18276 +               }
18277 +               else
18278 +               {
18279 +                       if (states[counter].number == 0)
18280 +                       {
18281 +                               ++states[counter].number;
18282 +                               goto dontmatch;
18283 +                       }
18284 +                       if (states[counter].number >= info->every)
18285 +                               states[counter].number = 0;
18286 +                       else
18287 +                               ++states[counter].number;
18288 +                       goto match;
18289 +               }
18290 +        }
18291 +        else
18292 +        {
18293 +               /* We're using the --packet, so there must be a rule for every value */
18294 +               if (states[counter].number == info->packet)
18295 +               {
18296 +                       /* only increment the counter when a match happens */
18297 +                       if (states[counter].number >= info->every)
18298 +                               states[counter].number = 0; /* reset the counter */
18299 +                       else
18300 +                               ++states[counter].number;
18301 +                       goto match;
18302 +               }
18303 +               else
18304 +                       goto dontmatch;
18305 +       }
18306 +
18307 + dontmatch:
18308 +       /* don't match */
18309 +       spin_unlock(&states[counter].lock);
18310 +       return 0;
18311 +
18312 + match:
18313 +       spin_unlock(&states[counter].lock);
18314 +       return 1;
18315 +}
18316 +
18317 +static int
18318 +ip6t_nth_checkentry(const char *tablename,
18319 +                  const struct ip6t_ip6 *e,
18320 +                  void *matchinfo,
18321 +                  unsigned int matchsize,
18322 +                  unsigned int hook_mask)
18323 +{
18324 +       /* Parameters from userspace */
18325 +       const struct ip6t_nth_info *info = matchinfo;
18326 +        unsigned counter = info->counter;
18327 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
18328 +       {
18329 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
18330 +                       return 0;
18331 +               };
18332 +
18333 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
18334 +               printk("nth: matchsize %u != %u\n", matchsize,
18335 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
18336 +               return 0;
18337 +       }
18338 +
18339 +       states[counter].number = info->startat;
18340 +
18341 +       return 1;
18342 +}
18343 +
18344 +static struct ip6t_match ip6t_nth_reg = { 
18345 +       {NULL, NULL},
18346 +       "nth",
18347 +       ip6t_nth_match,
18348 +       ip6t_nth_checkentry,
18349 +       NULL,
18350 +       THIS_MODULE };
18351 +
18352 +static int __init init(void)
18353 +{
18354 +       unsigned counter;
18355 +        memset(&states, 0, sizeof(states));
18356 +       if (ip6t_register_match(&ip6t_nth_reg))
18357 +               return -EINVAL;
18358 +
18359 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
18360 +       {
18361 +               spin_lock_init(&(states[counter].lock));
18362 +        };
18363 +
18364 +       printk("ip6t_nth match loaded\n");
18365 +       return 0;
18366 +}
18367 +
18368 +static void __exit fini(void)
18369 +{
18370 +       ip6t_unregister_match(&ip6t_nth_reg);
18371 +       printk("ip6t_nth match unloaded\n");
18372 +}
18373 +
18374 +module_init(init);
18375 +module_exit(fini);
18376 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6/net/ipv6/netfilter/ip6t_owner.c
18377 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_owner.c     2004-05-10 04:33:13.000000000 +0200
18378 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_owner.c 2004-05-18 12:39:53.000000000 +0200
18379 @@ -21,6 +21,39 @@
18380  MODULE_LICENSE("GPL");
18381  
18382  static int
18383 +match_comm(const struct sk_buff *skb, const char *comm)
18384 +{
18385 +       struct task_struct *p, *g;
18386 +       struct files_struct *files;
18387 +       int i;
18388 +
18389 +       read_lock(&tasklist_lock);
18390 +       do_each_thread(g, p) {
18391 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
18392 +                       continue;
18393 +
18394 +               task_lock(p);
18395 +               files = p->files;
18396 +               if(files) {
18397 +                       read_lock(&files->file_lock);
18398 +                       for (i=0; i < files->max_fds; i++) {
18399 +                               if (fcheck_files(files, i) ==
18400 +                                   skb->sk->sk_socket->file) {
18401 +                                       read_unlock(&files->file_lock);
18402 +                                       task_unlock(p);
18403 +                                       read_unlock(&tasklist_lock);
18404 +                                       return 1;
18405 +                               }
18406 +                       }
18407 +                       read_unlock(&files->file_lock);
18408 +               }
18409 +               task_unlock(p);
18410 +       } while_each_thread(g, p);
18411 +       read_unlock(&tasklist_lock);
18412 +       return 0;
18413 +}
18414 +
18415 +static int
18416  match_pid(const struct sk_buff *skb, pid_t pid)
18417  {
18418         struct task_struct *p;
18419 @@ -125,6 +158,12 @@
18420                         return 0;
18421         }
18422  
18423 +       if(info->match & IP6T_OWNER_COMM) {
18424 +               if (!match_comm(skb, info->comm) ^
18425 +                   !!(info->invert & IP6T_OWNER_COMM))
18426 +                       return 0;
18427 +       }
18428 +
18429         return 1;
18430  }
18431  
18432 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.6/net/ipv6/netfilter/ip6t_policy.c
18433 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_policy.c    1970-01-01 01:00:00.000000000 +0100
18434 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_policy.c        2004-05-18 12:39:55.000000000 +0200
18435 @@ -0,0 +1,201 @@
18436 +/* IP tables module for matching IPsec policy
18437 + *
18438 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
18439 + *
18440 + * This program is free software; you can redistribute it and/or modify
18441 + * it under the terms of the GNU General Public License version 2 as
18442 + * published by the Free Software Foundation.
18443 + */
18444 +
18445 +#include <linux/kernel.h>
18446 +#include <linux/config.h>
18447 +#include <linux/module.h>
18448 +#include <linux/skbuff.h>
18449 +#include <linux/init.h>
18450 +#include <net/xfrm.h>
18451 +
18452 +#include <linux/netfilter_ipv6.h>
18453 +#include <linux/netfilter_ipv6/ip6t_policy.h>
18454 +#include <linux/netfilter_ipv6/ip6_tables.h>
18455 +
18456 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
18457 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
18458 +MODULE_LICENSE("GPL");
18459 +
18460 +
18461 +static inline int ip6_masked_addrcmp(struct in6_addr addr1,
18462 +                                     struct in6_addr mask,
18463 +                                     struct in6_addr addr2)
18464 +{
18465 +       int i;
18466 +
18467 +       for (i = 0; i < 16; i++) {
18468 +               if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
18469 +                   (addr2.s6_addr[i] & mask.s6_addr[i]))
18470 +                       return 1;
18471 +       }
18472 +       return 0;
18473 +}
18474 +
18475 +
18476 +static inline int
18477 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
18478 +{
18479 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
18480 +       
18481 +       struct in6_addr xfrm_saddr, xfrm_daddr;
18482 +       
18483 +       if ((e->match.saddr
18484 +            && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
18485 +               ^ e->invert.saddr ) ||
18486 +           (e->match.daddr
18487 +            && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
18488 +               ^ e->invert.daddr ) ||
18489 +           MISMATCH(proto, x->id.proto) ||
18490 +           MISMATCH(mode, x->props.mode) ||
18491 +           MISMATCH(spi, x->id.spi) ||
18492 +           MISMATCH(reqid, x->props.reqid))
18493 +               return 0;
18494 +       return 1;
18495 +}
18496 +
18497 +static int
18498 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18499 +{
18500 +       const struct ip6t_policy_elem *e;
18501 +       struct sec_path *sp = skb->sp;
18502 +       int strict = info->flags & POLICY_MATCH_STRICT;
18503 +       int i, pos;
18504 +
18505 +       if (sp == NULL)
18506 +               return -1;
18507 +       if (strict && info->len != sp->len)
18508 +               return 0;
18509 +
18510 +       for (i = sp->len - 1; i >= 0; i--) {
18511 +               pos = strict ? i - sp->len + 1 : 0;
18512 +               if (pos >= info->len)
18513 +                       return 0;
18514 +               e = &info->pol[pos];
18515 +
18516 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
18517 +                       if (!strict)
18518 +                               return 1;
18519 +               } else if (strict)
18520 +                       return 0;
18521 +       }
18522 +
18523 +       return strict ? 1 : 0;
18524 +}
18525 +
18526 +static int
18527 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18528 +{
18529 +       const struct ip6t_policy_elem *e;
18530 +       struct dst_entry *dst = skb->dst;
18531 +       int strict = info->flags & POLICY_MATCH_STRICT;
18532 +       int i, pos;
18533 +
18534 +       if (dst->xfrm == NULL)
18535 +               return -1;
18536 +
18537 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
18538 +               pos = strict ? i : 0;
18539 +               if (pos >= info->len)
18540 +                       return 0;
18541 +               e = &info->pol[pos];
18542 +
18543 +               if (match_xfrm_state(dst->xfrm, e)) {
18544 +                       if (!strict)
18545 +                               return 1;
18546 +               } else if (strict)
18547 +                       return 0;
18548 +       }
18549 +
18550 +       return strict ? 1 : 0;
18551 +}
18552 +
18553 +static int match(const struct sk_buff *skb,
18554 +                 const struct net_device *in,
18555 +                 const struct net_device *out,
18556 +                 const void *matchinfo,
18557 +                int offset,
18558 +                const void *hdr,
18559 +                u_int16_t datalen,
18560 +                int *hotdrop)
18561 +{
18562 +       const struct ip6t_policy_info *info = matchinfo;
18563 +       int ret;
18564 +
18565 +       if (info->flags & POLICY_MATCH_IN)
18566 +               ret = match_policy_in(skb, info);
18567 +       else
18568 +               ret = match_policy_out(skb, info);
18569 +
18570 +       if (ret < 0) {
18571 +               if (info->flags & POLICY_MATCH_NONE)
18572 +                       ret = 1;
18573 +               else
18574 +                       ret = 0;
18575 +       } else if (info->flags & POLICY_MATCH_NONE)
18576 +               ret = 0;
18577 +
18578 +       return ret;
18579 +}
18580 +
18581 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
18582 +                      void *matchinfo, unsigned int matchsize,
18583 +                      unsigned int hook_mask)
18584 +{
18585 +       struct ip6t_policy_info *info = matchinfo;
18586 +
18587 +       if (matchsize != IP6T_ALIGN(sizeof(*info))) {
18588 +               printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
18589 +                      matchsize, IP6T_ALIGN(sizeof(*info)));
18590 +               return 0;
18591 +       }
18592 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
18593 +               printk(KERN_ERR "ip6t_policy: neither incoming nor "
18594 +                               "outgoing policy selected\n");
18595 +               return 0;
18596 +       }
18597 +       if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
18598 +           && info->flags & POLICY_MATCH_OUT) {
18599 +               printk(KERN_ERR "ip6t_policy: output policy not valid in "
18600 +                               "PRE_ROUTING and INPUT\n");
18601 +               return 0;
18602 +       }
18603 +       if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
18604 +           && info->flags & POLICY_MATCH_IN) {
18605 +               printk(KERN_ERR "ip6t_policy: input policy not valid in "
18606 +                               "POST_ROUTING and OUTPUT\n");
18607 +               return 0;
18608 +       }
18609 +       if (info->len > POLICY_MAX_ELEM) {
18610 +               printk(KERN_ERR "ip6t_policy: too many policy elements\n");
18611 +               return 0;
18612 +       }
18613 +
18614 +       return 1;
18615 +}
18616 +
18617 +static struct ip6t_match policy_match =
18618 +{
18619 +       .name           = "policy",
18620 +       .match          = match,
18621 +       .checkentry     = checkentry,
18622 +       .me             = THIS_MODULE,
18623 +};
18624 +
18625 +static int __init init(void)
18626 +{
18627 +       return ip6t_register_match(&policy_match);
18628 +}
18629 +
18630 +static void __exit fini(void)
18631 +{
18632 +       ip6t_unregister_match(&policy_match);
18633 +}
18634 +
18635 +module_init(init);
18636 +module_exit(fini);
18637 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.6/net/ipv6/netfilter/ip6t_random.c
18638 --- linux-2.6.6.org/net/ipv6/netfilter/ip6t_random.c    1970-01-01 01:00:00.000000000 +0100
18639 +++ linux-2.6.6/net/ipv6/netfilter/ip6t_random.c        2004-05-18 12:36:59.000000000 +0200
18640 @@ -0,0 +1,97 @@
18641 +/*
18642 +  This is a module which is used for a "random" match support.
18643 +  This file is distributed under the terms of the GNU General Public
18644 +  License (GPL). Copies of the GPL can be obtained from:
18645 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
18646 +
18647 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18648 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18649 +*/
18650 +
18651 +#include <linux/module.h>
18652 +#include <linux/skbuff.h>
18653 +#include <linux/ip.h>
18654 +#include <linux/random.h>
18655 +#include <net/tcp.h>
18656 +#include <linux/spinlock.h>
18657 +#include <linux/netfilter_ipv6/ip6_tables.h>
18658 +#include <linux/netfilter_ipv6/ip6t_random.h>
18659 +
18660 +MODULE_LICENSE("GPL");
18661 +
18662 +static int
18663 +ip6t_rand_match(const struct sk_buff *pskb,
18664 +              const struct net_device *in,
18665 +              const struct net_device *out,
18666 +              const void *matchinfo,
18667 +              int offset,
18668 +              const void *hdr,
18669 +              u_int16_t datalen,
18670 +              int *hotdrop)
18671 +{
18672 +       /* Parameters from userspace */
18673 +       const struct ip6t_rand_info *info = matchinfo;
18674 +       u_int8_t random_number;
18675 +
18676 +       /* get 1 random number from the kernel random number generation routine */
18677 +       get_random_bytes((void *)(&random_number), 1);
18678 +
18679 +       /* Do we match ? */
18680 +       if (random_number <= info->average)
18681 +               return 1;
18682 +       else
18683 +               return 0;
18684 +}
18685 +
18686 +static int
18687 +ip6t_rand_checkentry(const char *tablename,
18688 +                  const struct ip6t_ip6 *e,
18689 +                  void *matchinfo,
18690 +                  unsigned int matchsize,
18691 +                  unsigned int hook_mask)
18692 +{
18693 +       /* Parameters from userspace */
18694 +       const struct ip6t_rand_info *info = matchinfo;
18695 +
18696 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
18697 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
18698 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
18699 +               return 0;
18700 +       }
18701 +
18702 +       /* must be  1 <= average % <= 99 */
18703 +       /* 1  x 2.55 = 2   */
18704 +       /* 99 x 2.55 = 252 */
18705 +       if ((info->average < 2) || (info->average > 252)) {
18706 +               printk("ip6t_random:  invalid average %u\n", info->average);
18707 +               return 0;
18708 +       }
18709 +
18710 +       return 1;
18711 +}
18712 +
18713 +static struct ip6t_match ip6t_rand_reg = { 
18714 +       {NULL, NULL},
18715 +       "random",
18716 +       ip6t_rand_match,
18717 +       ip6t_rand_checkentry,
18718 +       NULL,
18719 +       THIS_MODULE };
18720 +
18721 +static int __init init(void)
18722 +{
18723 +       if (ip6t_register_match(&ip6t_rand_reg))
18724 +               return -EINVAL;
18725 +
18726 +       printk("ip6t_random match loaded\n");
18727 +       return 0;
18728 +}
18729 +
18730 +static void __exit fini(void)
18731 +{
18732 +       ip6t_unregister_match(&ip6t_rand_reg);
18733 +       printk("ip6t_random match unloaded\n");
18734 +}
18735 +
18736 +module_init(init);
18737 +module_exit(fini);
18738 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.6/net/ipv6/netfilter/ip6table_filter.c
18739 --- linux-2.6.6.org/net/ipv6/netfilter/ip6table_filter.c        2004-05-10 04:32:00.000000000 +0200
18740 +++ linux-2.6.6/net/ipv6/netfilter/ip6table_filter.c    2004-05-18 12:38:32.000000000 +0200
18741 @@ -58,7 +58,7 @@
18742                 0,
18743                 sizeof(struct ip6t_entry),
18744                 sizeof(struct ip6t_standard),
18745 -               0, { 0, 0 }, { } },
18746 +               0, NULL, 0, { 0, 0 }, { } },
18747               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18748                 -NF_ACCEPT - 1 } },
18749             /* FORWARD */
18750 @@ -66,7 +66,7 @@
18751                 0,
18752                 sizeof(struct ip6t_entry),
18753                 sizeof(struct ip6t_standard),
18754 -               0, { 0, 0 }, { } },
18755 +               0, NULL, 0, { 0, 0 }, { } },
18756               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18757                 -NF_ACCEPT - 1 } },
18758             /* LOCAL_OUT */
18759 @@ -74,7 +74,7 @@
18760                 0,
18761                 sizeof(struct ip6t_entry),
18762                 sizeof(struct ip6t_standard),
18763 -               0, { 0, 0 }, { } },
18764 +               0, NULL, 0, { 0, 0 }, { } },
18765               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18766                 -NF_ACCEPT - 1 } }
18767      },
18768 @@ -83,7 +83,7 @@
18769         0,
18770         sizeof(struct ip6t_entry),
18771         sizeof(struct ip6t_error),
18772 -       0, { 0, 0 }, { } },
18773 +       0, NULL, 0, { 0, 0 }, { } },
18774        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18775           { } },
18776         "ERROR"
18777 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.6/net/ipv6/netfilter/ip6table_mangle.c
18778 --- linux-2.6.6.org/net/ipv6/netfilter/ip6table_mangle.c        2004-05-10 04:32:28.000000000 +0200
18779 +++ linux-2.6.6/net/ipv6/netfilter/ip6table_mangle.c    2004-05-18 12:38:32.000000000 +0200
18780 @@ -73,7 +73,7 @@
18781                 0,
18782                 sizeof(struct ip6t_entry),
18783                 sizeof(struct ip6t_standard),
18784 -               0, { 0, 0 }, { } },
18785 +               0, NULL, 0, { 0, 0 }, { } },
18786               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18787                 -NF_ACCEPT - 1 } },
18788             /* LOCAL_IN */
18789 @@ -81,7 +81,7 @@
18790                 0,
18791                 sizeof(struct ip6t_entry),
18792                 sizeof(struct ip6t_standard),
18793 -               0, { 0, 0 }, { } },
18794 +               0, NULL, 0, { 0, 0 }, { } },
18795               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18796                 -NF_ACCEPT - 1 } },
18797             /* FORWARD */
18798 @@ -89,7 +89,7 @@
18799                 0,
18800                 sizeof(struct ip6t_entry),
18801                 sizeof(struct ip6t_standard),
18802 -               0, { 0, 0 }, { } },
18803 +               0, NULL, 0, { 0, 0 }, { } },
18804               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18805                 -NF_ACCEPT - 1 } },
18806             /* LOCAL_OUT */
18807 @@ -97,7 +97,7 @@
18808                 0,
18809                 sizeof(struct ip6t_entry),
18810                 sizeof(struct ip6t_standard),
18811 -               0, { 0, 0 }, { } },
18812 +               0, NULL, 0, { 0, 0 }, { } },
18813               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18814                 -NF_ACCEPT - 1 } },
18815             /* POST_ROUTING */
18816 @@ -105,7 +105,7 @@
18817                 0,
18818                 sizeof(struct ip6t_entry),
18819                 sizeof(struct ip6t_standard),
18820 -               0, { 0, 0 }, { } },
18821 +               0, NULL, 0, { 0, 0 }, { } },
18822               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18823                 -NF_ACCEPT - 1 } }
18824      },
18825 @@ -114,7 +114,7 @@
18826         0,
18827         sizeof(struct ip6t_entry),
18828         sizeof(struct ip6t_error),
18829 -       0, { 0, 0 }, { } },
18830 +       0, NULL, 0, { 0, 0 }, { } },
18831        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18832           { } },
18833         "ERROR"
18834 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.6/net/ipv6/netfilter/ip6table_raw.c
18835 --- linux-2.6.6.org/net/ipv6/netfilter/ip6table_raw.c   2004-05-10 04:32:53.000000000 +0200
18836 +++ linux-2.6.6/net/ipv6/netfilter/ip6table_raw.c       2004-05-18 12:38:32.000000000 +0200
18837 @@ -52,7 +52,7 @@
18838                 0,
18839                 sizeof(struct ip6t_entry),
18840                 sizeof(struct ip6t_standard),
18841 -               0, { 0, 0 }, { } },
18842 +               0, NULL, 0, { 0, 0 }, { } },
18843               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18844                 -NF_ACCEPT - 1 } },
18845             /* LOCAL_OUT */
18846 @@ -60,7 +60,7 @@
18847                 0,
18848                 sizeof(struct ip6t_entry),
18849                 sizeof(struct ip6t_standard),
18850 -               0, { 0, 0 }, { } },
18851 +               0, NULL, 0, { 0, 0 }, { } },
18852               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18853                 -NF_ACCEPT - 1 } },
18854      },
18855 @@ -69,7 +69,7 @@
18856         0,
18857         sizeof(struct ip6t_entry),
18858         sizeof(struct ip6t_error),
18859 -       0, { 0, 0 }, { } },
18860 +       0, NULL, 0, { 0, 0 }, { } },
18861        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18862           { } },
18863         "ERROR"
18864 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/ipv6/sit.c linux-2.6.6/net/ipv6/sit.c
18865 --- linux-2.6.6.org/net/ipv6/sit.c      2004-05-10 04:33:20.000000000 +0200
18866 +++ linux-2.6.6/net/ipv6/sit.c  2004-05-18 12:35:50.000000000 +0200
18867 @@ -388,13 +388,7 @@
18868                 skb->dev = tunnel->dev;
18869                 dst_release(skb->dst);
18870                 skb->dst = NULL;
18871 -#ifdef CONFIG_NETFILTER
18872 -               nf_conntrack_put(skb->nfct);
18873 -               skb->nfct = NULL;
18874 -#ifdef CONFIG_NETFILTER_DEBUG
18875 -               skb->nf_debug = 0;
18876 -#endif
18877 -#endif
18878 +               nf_reset(skb);
18879                 ipip6_ecn_decapsulate(iph, skb);
18880                 netif_rx(skb);
18881                 read_unlock(&ipip6_lock);
18882 @@ -580,13 +574,7 @@
18883         if ((iph->ttl = tiph->ttl) == 0)
18884                 iph->ttl        =       iph6->hop_limit;
18885  
18886 -#ifdef CONFIG_NETFILTER
18887 -       nf_conntrack_put(skb->nfct);
18888 -       skb->nfct = NULL;
18889 -#ifdef CONFIG_NETFILTER_DEBUG
18890 -       skb->nf_debug = 0;
18891 -#endif
18892 -#endif
18893 +       nf_reset(skb);
18894  
18895         IPTUNNEL_XMIT();
18896         tunnel->recursion--;
18897 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/xfrm/xfrm_input.c linux-2.6.6/net/xfrm/xfrm_input.c
18898 --- linux-2.6.6.org/net/xfrm/xfrm_input.c       2004-05-10 04:31:59.000000000 +0200
18899 +++ linux-2.6.6/net/xfrm/xfrm_input.c   2004-05-18 12:39:22.000000000 +0200
18900 @@ -29,6 +29,9 @@
18901         if (!sp)
18902                 return NULL;
18903  
18904 +#ifdef CONFIG_NETFILTER
18905 +       sp->decap_done = 0;
18906 +#endif
18907         sp->len = 0;
18908         if (src) {
18909                 int i;
18910 diff -Nur --exclude '*.orig' linux-2.6.6.org/net/xfrm/xfrm_policy.c linux-2.6.6/net/xfrm/xfrm_policy.c
18911 --- linux-2.6.6.org/net/xfrm/xfrm_policy.c      2004-05-10 04:32:37.000000000 +0200
18912 +++ linux-2.6.6/net/xfrm/xfrm_policy.c  2004-05-18 12:39:23.000000000 +0200
18913 @@ -21,6 +21,7 @@
18914  #include <linux/workqueue.h>
18915  #include <linux/notifier.h>
18916  #include <linux/netdevice.h>
18917 +#include <linux/netfilter.h>
18918  #include <net/xfrm.h>
18919  #include <net/ip.h>
18920  
18921 @@ -908,6 +909,7 @@
18922  
18923         if (_decode_session(skb, &fl, family) < 0)
18924                 return 0;
18925 +       nf_nat_decode_session(skb, &fl, family);
18926  
18927         /* First, check used SA against their selectors. */
18928         if (skb->sp) {
18929 --- linux-2.6.6/net/ipv6/ip6_output.c.org       2004-05-10 04:31:59.000000000 +0200
18930 +++ linux-2.6.6/net/ipv6/ip6_output.c   2004-05-11 18:35:06.402777016 +0200
18931 @@ -805,6 +805,7 @@
18932         *dst = NULL;
18933         return err;
18934  }
18935 +EXPORT_SYMBOL(ip6_dst_lookup);
18936  
18937  int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
18938                     void *from, int length, int transhdrlen,
This page took 1.631634 seconds and 3 git commands to generate.