]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.7-pom-ng-20040624.patch
- [sparc32] grsec disabled.
[packages/kernel.git] / 2.6.7-pom-ng-20040624.patch
1 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter.h linux-2.6.7/include/linux/netfilter.h
2 --- linux-2.6.7.org/include/linux/netfilter.h   2004-06-25 10:47:45.000000000 +0200
3 +++ linux-2.6.7/include/linux/netfilter.h       2004-06-25 12:21:38.694509280 +0200
4 @@ -138,12 +138,14 @@
5  /* This is gross, but inline doesn't cut it for avoiding the function
6     call in fast path: gcc doesn't inline (needs value tracking?). --RR */
7  #ifdef CONFIG_NETFILTER_DEBUG
8 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
9 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
10 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
11 +(!(cond)                                                               \
12 + ? (okfn)(skb)                                                                 \
13 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
14  #define NF_HOOK_THRESH nf_hook_slow
15  #else
16 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
17 -(list_empty(&nf_hooks[(pf)][(hook)])                                   \
18 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
19 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)])                                \
20   ? (okfn)(skb)                                                         \
21   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
22  #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)     \
23 @@ -151,6 +153,8 @@
24   ? (okfn)(skb)                                                         \
25   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
26  #endif
27 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
28 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
29  
30  int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
31                  struct net_device *indev, struct net_device *outdev,
32 @@ -189,7 +193,24 @@
33  
34  #else /* !CONFIG_NETFILTER */
35  #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
36 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
37  #endif /*CONFIG_NETFILTER*/
38  
39 +#ifdef CONFIG_XFRM
40 +#ifdef CONFIG_IP_NF_NAT_NEEDED
41 +struct flowi;
42 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
43 +
44 +static inline void
45 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
46 +{
47 +       if (family == AF_INET)
48 +               nf_nat_decode_session4(skb, fl);
49 +}
50 +#else /* CONFIG_IP_NF_NAT_NEEDED */
51 +#define nf_nat_decode_session(skb,fl,family)
52 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
53 +#endif /* CONFIG_XFRM */
54 +
55  #endif /*__KERNEL__*/
56  #endif /*__LINUX_NETFILTER_H*/
57 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_helpers.h linux-2.6.7/include/linux/netfilter_helpers.h
58 --- linux-2.6.7.org/include/linux/netfilter_helpers.h   1970-01-01 01:00:00.000000000 +0100
59 +++ linux-2.6.7/include/linux/netfilter_helpers.h       2004-06-25 12:24:50.026422408 +0200
60 @@ -0,0 +1,133 @@
61 +/*
62 + * Helpers for netfiler modules.  This file provides implementations for basic
63 + * functions such as strncasecmp(), etc.
64 + *
65 + * gcc will warn for defined but unused functions, so we only include the
66 + * functions requested.  The following macros are used:
67 + *   NF_NEED_STRNCASECMP        nf_strncasecmp()
68 + *   NF_NEED_STRTOU16           nf_strtou16()
69 + *   NF_NEED_STRTOU32           nf_strtou32()
70 + */
71 +#ifndef _NETFILTER_HELPERS_H
72 +#define _NETFILTER_HELPERS_H
73 +
74 +/* Only include these functions for kernel code. */
75 +#ifdef __KERNEL__
76 +
77 +#include <linux/ctype.h>
78 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
79 +
80 +/*
81 + * The standard strncasecmp()
82 + */
83 +#ifdef NF_NEED_STRNCASECMP
84 +static int
85 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
86 +{
87 +    if (s1 == NULL || s2 == NULL)
88 +    {
89 +        if (s1 == NULL && s2 == NULL)
90 +        {
91 +            return 0;
92 +        }
93 +        return (s1 == NULL) ? -1 : 1;
94 +    }
95 +    while (len > 0 && tolower(*s1) == tolower(*s2))
96 +    {
97 +        len--;
98 +        s1++;
99 +        s2++;
100 +    }
101 +    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
102 +}
103 +#endif /* NF_NEED_STRNCASECMP */
104 +
105 +/*
106 + * Parse a string containing a 16-bit unsigned integer.
107 + * Returns the number of chars used, or zero if no number is found.
108 + */
109 +#ifdef NF_NEED_STRTOU16
110 +static int
111 +nf_strtou16(const char* pbuf, u_int16_t* pval)
112 +{
113 +    int n = 0;
114 +
115 +    *pval = 0;
116 +    while (isdigit(pbuf[n]))
117 +    {
118 +        *pval = (*pval * 10) + (pbuf[n] - '0');
119 +        n++;
120 +    }
121 +
122 +    return n;
123 +}
124 +#endif /* NF_NEED_STRTOU16 */
125 +
126 +/*
127 + * Parse a string containing a 32-bit unsigned integer.
128 + * Returns the number of chars used, or zero if no number is found.
129 + */
130 +#ifdef NF_NEED_STRTOU32
131 +static int
132 +nf_strtou32(const char* pbuf, u_int32_t* pval)
133 +{
134 +    int n = 0;
135 +
136 +    *pval = 0;
137 +    while (pbuf[n] >= '0' && pbuf[n] <= '9')
138 +    {
139 +        *pval = (*pval * 10) + (pbuf[n] - '0');
140 +        n++;
141 +    }
142 +
143 +    return n;
144 +}
145 +#endif /* NF_NEED_STRTOU32 */
146 +
147 +/*
148 + * Given a buffer and length, advance to the next line and mark the current
149 + * line.
150 + */
151 +#ifdef NF_NEED_NEXTLINE
152 +static int
153 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
154 +{
155 +    uint    off = *poff;
156 +    uint    physlen = 0;
157 +
158 +    if (off >= len)
159 +    {
160 +        return 0;
161 +    }
162 +
163 +    while (p[off] != '\n')
164 +    {
165 +        if (len-off <= 1)
166 +        {
167 +            return 0;
168 +        }
169 +
170 +        physlen++;
171 +        off++;
172 +    }
173 +
174 +    /* if we saw a crlf, physlen needs adjusted */
175 +    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
176 +    {
177 +        physlen--;
178 +    }
179 +
180 +    /* advance past the newline */
181 +    off++;
182 +
183 +    *plineoff = *poff;
184 +    *plinelen = physlen;
185 +    *poff = off;
186 +
187 +    return 1;
188 +}
189 +#endif /* NF_NEED_NEXTLINE */
190 +
191 +#endif /* __KERNEL__ */
192 +
193 +#endif /* _NETFILTER_HELPERS_H */
194 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h
195 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-25 10:47:45.000000000 +0200
196 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h     2004-06-25 12:28:43.675902288 +0200
197 @@ -51,10 +51,12 @@
198  
199  #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
200  #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
201 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
202  
203  /* per conntrack: protocol private data */
204  union ip_conntrack_proto {
205         /* insert conntrack proto private data here */
206 +       struct ip_ct_sctp sctp;
207         struct ip_ct_tcp tcp;
208         struct ip_ct_icmp icmp;
209  };
210 @@ -64,6 +66,11 @@
211  };
212  
213  /* Add protocol helper include file here */
214 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
215 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
216 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
217 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
218 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
219  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
220  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
221  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
222 @@ -71,6 +78,11 @@
223  /* per expectation: application helper private data */
224  union ip_conntrack_expect_help {
225         /* insert conntrack helper private data (expect) here */
226 +       struct ip_ct_talk_expect exp_talk_info;
227 +       struct ip_ct_rtsp_expect exp_rtsp_info;
228 +       struct ip_ct_rsh_expect exp_rsh_info;
229 +       struct ip_ct_mms_expect exp_mms_info;
230 +       struct ip_ct_h225_expect exp_h225_info;
231         struct ip_ct_amanda_expect exp_amanda_info;
232         struct ip_ct_ftp_expect exp_ftp_info;
233         struct ip_ct_irc_expect exp_irc_info;
234 @@ -85,6 +97,11 @@
235  /* per conntrack: application helper private data */
236  union ip_conntrack_help {
237         /* insert conntrack helper private data (master) here */
238 +       struct ip_ct_talk_master ct_talk_info;
239 +       struct ip_ct_rtsp_master ct_rtsp_info;
240 +       struct ip_ct_rsh_master ct_rsh_info;
241 +       struct ip_ct_mms_master ct_mms_info;
242 +       struct ip_ct_h225_master ct_h225_info;
243         struct ip_ct_ftp_master ct_ftp_info;
244         struct ip_ct_irc_master ct_irc_info;
245  };
246 @@ -207,6 +224,10 @@
247         } nat;
248  #endif /* CONFIG_IP_NF_NAT_NEEDED */
249  
250 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
251 +       unsigned long mark;
252 +#endif
253 +
254  };
255  
256  /* get master conntrack via master expectation */
257 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h
258 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h    2004-06-16 07:20:26.000000000 +0200
259 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h        2004-06-25 12:21:02.302041776 +0200
260 @@ -21,15 +21,17 @@
261  extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
262  extern struct list_head protocol_list;
263  
264 -/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */
265 -extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
266 -                                            enum ip_conntrack_info *ctinfo,
267 -                                            unsigned int hooknum);
268 -extern int get_tuple(const struct iphdr *iph,
269 -                    const struct sk_buff *skb,
270 -                    unsigned int dataoff,
271 -                    struct ip_conntrack_tuple *tuple,
272 -                    const struct ip_conntrack_protocol *protocol);
273 +extern int
274 +ip_ct_get_tuple(const struct iphdr *iph,
275 +               const struct sk_buff *skb,
276 +               unsigned int dataoff,
277 +               struct ip_conntrack_tuple *tuple,
278 +               const struct ip_conntrack_protocol *protocol);
279 +
280 +extern int
281 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
282 +                  const struct ip_conntrack_tuple *orig,
283 +                  const struct ip_conntrack_protocol *protocol);
284  
285  /* Find a connection corresponding to a tuple. */
286  struct ip_conntrack_tuple_hash *
287 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_h323.h
288 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h    1970-01-01 01:00:00.000000000 +0100
289 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_h323.h        2004-06-25 12:21:34.914083992 +0200
290 @@ -0,0 +1,31 @@
291 +#ifndef _IP_CONNTRACK_H323_H
292 +#define _IP_CONNTRACK_H323_H
293 +/* H.323 connection tracking. */
294 +
295 +#ifdef __KERNEL__
296 +/* Protects H.323 related data */
297 +#include <linux/netfilter_ipv4/lockhelp.h>
298 +DECLARE_LOCK_EXTERN(ip_h323_lock);
299 +#endif
300 +
301 +/* Default H.225 port */
302 +#define H225_PORT      1720
303 +
304 +/* This structure is per expected connection */
305 +struct ip_ct_h225_expect {
306 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
307 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
308 +       unsigned int offset;            /* offset of the address in the payload */
309 +};
310 +
311 +/* This structure exists only once per master */
312 +struct ip_ct_h225_master {
313 +       int is_h225;                            /* H.225 or H.245 connection */
314 +#ifdef CONFIG_IP_NF_NAT_NEEDED
315 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
316 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
317 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
318 +#endif
319 +};
320 +
321 +#endif /* _IP_CONNTRACK_H323_H */
322 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_mms.h
323 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h     1970-01-01 01:00:00.000000000 +0100
324 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-06-25 12:23:10.833502024 +0200
325 @@ -0,0 +1,31 @@
326 +#ifndef _IP_CONNTRACK_MMS_H
327 +#define _IP_CONNTRACK_MMS_H
328 +/* MMS tracking. */
329 +
330 +#ifdef __KERNEL__
331 +#include <linux/netfilter_ipv4/lockhelp.h>
332 +
333 +DECLARE_LOCK_EXTERN(ip_mms_lock);
334 +
335 +#define MMS_PORT                         1755
336 +#define MMS_SRV_MSG_ID                   196610
337 +
338 +#define MMS_SRV_MSG_OFFSET               36
339 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
340 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
341 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
342 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
343 +#endif
344 +
345 +/* This structure is per expected connection */
346 +struct ip_ct_mms_expect {
347 +       u_int32_t len;
348 +       u_int32_t padding;
349 +       u_int16_t port;
350 +};
351 +
352 +/* This structure exists only once per master */
353 +struct ip_ct_mms_master {
354 +};
355 +
356 +#endif /* _IP_CONNTRACK_MMS_H */
357 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
358 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h        2004-06-16 07:20:04.000000000 +0200
359 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h    2004-06-25 12:21:02.304041472 +0200
360 @@ -50,6 +50,9 @@
361         int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
362                                const struct sk_buff *skb);
363  
364 +       int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
365 +                    unsigned int hooknum);
366 +
367         /* Module (if any) which this is connected to. */
368         struct module *me;
369  };
370 @@ -63,4 +66,17 @@
371  extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
372  extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
373  extern int ip_conntrack_protocol_tcp_init(void);
374 +
375 +/* Log invalid packets */
376 +extern unsigned int ip_ct_log_invalid;
377 +
378 +#ifdef DEBUG_INVALID_PACKETS
379 +#define LOG_INVALID(proto) \
380 +       (ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
381 +#else
382 +#define LOG_INVALID(proto) \
383 +       ((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
384 +        && net_ratelimit())
385 +#endif
386 +
387  #endif /*_IP_CONNTRACK_PROTOCOL_H*/
388 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
389 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h  1970-01-01 01:00:00.000000000 +0100
390 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_quake3.h      2004-06-25 12:24:42.547559368 +0200
391 @@ -0,0 +1,21 @@
392 +#ifndef _IP_CT_QUAKE3
393 +#define _IP_CT_QUAKE3
394 +
395 +/* Don't confuse with 27960, often used as the Server Port */
396 +#define QUAKE3_MASTER_PORT 27950
397 +
398 +struct quake3_search {
399 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
400 +       const char *pattern;
401 +       size_t plen;
402 +}; 
403 +
404 +/* This structure is per expected connection */
405 +struct ip_ct_quake3_expect {
406 +};
407 +
408 +/* This structure exists only once per master */
409 +struct ip_ct_quake3_master {
410 +};
411 +
412 +#endif /* _IP_CT_QUAKE3 */
413 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
414 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h     1970-01-01 01:00:00.000000000 +0100
415 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-06-25 12:24:48.839602832 +0200
416 @@ -0,0 +1,35 @@
417 +/* RSH extension for IP connection tracking, Version 1.0
418 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
419 + * based on HW's ip_conntrack_irc.c     
420 + *
421 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
422 + *
423 + *      This program is free software; you can redistribute it and/or
424 + *      modify it under the terms of the GNU General Public License
425 + *      as published by the Free Software Foundation; either version
426 + *      2 of the License, or (at your option) any later version.
427 + */
428 +#ifndef _IP_CONNTRACK_RSH_H
429 +#define _IP_CONNTRACK_RSH_H
430 +
431 +#ifdef __KERNEL__
432 +#include <linux/netfilter_ipv4/lockhelp.h>
433 +
434 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
435 +#endif
436 +
437 +
438 +#define RSH_PORT       514
439 +
440 +/* This structure is per expected connection */
441 +struct ip_ct_rsh_expect
442 +{
443 +       u_int16_t port;
444 +};
445 +
446 +/* This structure exists only once per master */
447 +struct ip_ct_rsh_master {
448 +};
449 +
450 +#endif /* _IP_CONNTRACK_RSH_H */
451 +
452 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
453 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h    1970-01-01 01:00:00.000000000 +0100
454 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h        2004-06-25 12:24:50.028422104 +0200
455 @@ -0,0 +1,68 @@
456 +/*
457 + * RTSP extension for IP connection tracking.
458 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
459 + * based on ip_conntrack_irc.h
460 + *
461 + *      This program is free software; you can redistribute it and/or
462 + *      modify it under the terms of the GNU General Public License
463 + *      as published by the Free Software Foundation; either version
464 + *      2 of the License, or (at your option) any later version.
465 + */
466 +#ifndef _IP_CONNTRACK_RTSP_H
467 +#define _IP_CONNTRACK_RTSP_H
468 +
469 +/* #define IP_NF_RTSP_DEBUG */
470 +#define IP_NF_RTSP_VERSION "0.01"
471 +
472 +/* port block types */
473 +typedef enum {
474 +    pb_single,  /* client_port=x */
475 +    pb_range,   /* client_port=x-y */
476 +    pb_discon   /* client_port=x/y (rtspbis) */
477 +} portblock_t;
478 +
479 +/* We record seq number and length of rtsp headers here, all in host order. */
480 +
481 +/*
482 + * This structure is per expected connection.  It is a member of struct
483 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
484 + * there and we are expected to only store the length of the data which
485 + * needs replaced.  If a packet contains multiple RTSP messages, we create
486 + * one expected connection per message.
487 + *
488 + * We use these variables to mark the entire header block.  This may seem
489 + * like overkill, but the nature of RTSP requires it.  A header may appear
490 + * multiple times in a message.  We must treat two Transport headers the
491 + * same as one Transport header with two entries.
492 + */
493 +struct ip_ct_rtsp_expect
494 +{
495 +    u_int32_t   len;        /* length of header block */
496 +    portblock_t pbtype;     /* Type of port block that was requested */
497 +    u_int16_t   loport;     /* Port that was requested, low or first */
498 +    u_int16_t   hiport;     /* Port that was requested, high or second */
499 +#if 0
500 +    uint        method;     /* RTSP method */
501 +    uint        cseq;       /* CSeq from request */
502 +#endif
503 +};
504 +
505 +/* This structure exists only once per master */
506 +struct ip_ct_rtsp_master
507 +{
508 +    /* Empty (?) */
509 +};
510 +
511 +
512 +#ifdef __KERNEL__
513 +
514 +#include <linux/netfilter_ipv4/lockhelp.h>
515 +
516 +#define RTSP_PORT   554
517 +
518 +/* Protects rtsp part of conntracks */
519 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
520 +
521 +#endif /* __KERNEL__ */
522 +
523 +#endif /* _IP_CONNTRACK_RTSP_H */
524 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
525 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h    1970-01-01 01:00:00.000000000 +0100
526 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_sctp.h        2004-06-25 12:24:51.922134216 +0200
527 @@ -0,0 +1,25 @@
528 +#ifndef _IP_CONNTRACK_SCTP_H
529 +#define _IP_CONNTRACK_SCTP_H
530 +/* SCTP tracking. */
531 +
532 +enum sctp_conntrack {
533 +       SCTP_CONNTRACK_NONE,
534 +       SCTP_CONNTRACK_CLOSED,
535 +       SCTP_CONNTRACK_COOKIE_WAIT,
536 +       SCTP_CONNTRACK_COOKIE_ECHOED,
537 +       SCTP_CONNTRACK_ESTABLISHED,
538 +       SCTP_CONNTRACK_SHUTDOWN_SENT,
539 +       SCTP_CONNTRACK_SHUTDOWN_RECD,
540 +       SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
541 +       SCTP_CONNTRACK_MAX
542 +};
543 +
544 +struct ip_ct_sctp
545 +{
546 +       enum sctp_conntrack state;
547 +
548 +       u_int32_t vtag[IP_CT_DIR_MAX];
549 +       u_int32_t ttag[IP_CT_DIR_MAX];
550 +};
551 +
552 +#endif /* _IP_CONNTRACK_SCTP_H */
553 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_talk.h
554 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h    1970-01-01 01:00:00.000000000 +0100
555 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_talk.h        2004-06-25 12:28:43.647906544 +0200
556 @@ -0,0 +1,152 @@
557 +#ifndef _IP_CONNTRACK_TALK_H
558 +#define _IP_CONNTRACK_TALK_H
559 +/* TALK tracking. */
560 +
561 +#ifdef __KERNEL__
562 +#include <linux/in.h>
563 +#include <linux/netfilter_ipv4/lockhelp.h>
564 +
565 +/* Protects talk part of conntracks */
566 +DECLARE_LOCK_EXTERN(ip_talk_lock);
567 +#endif
568 +
569 +
570 +#define TALK_PORT      517
571 +#define NTALK_PORT     518
572 +
573 +/* talk structures and constants from <protocols/talkd.h> */
574 +
575 +/*
576 + * 4.3BSD struct sockaddr
577 + */
578 +struct talk_addr {
579 +       u_int16_t ta_family;
580 +       u_int16_t ta_port;
581 +       u_int32_t ta_addr;
582 +       u_int32_t ta_junk1;
583 +       u_int32_t ta_junk2;
584 +};
585 +
586 +#define        TALK_OLD_NSIZE  9
587 +#define        TALK_NSIZE      12
588 +#define        TALK_TTY_NSIZE  16
589 +
590 +/*
591 + * Client->server request message formats.
592 + */
593 +struct talk_msg {
594 +       u_char  type;           /* request type, see below */
595 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
596 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
597 +       u_char  pad;
598 +       u_int32_t id_num;       /* message id */
599 +       int32_t pid;            /* caller's process id */
600 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
601 +       struct  talk_addr addr;         /* old (4.3) style */
602 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
603 +};
604 +
605 +struct ntalk_msg {
606 +       u_char  vers;           /* protocol version */
607 +       u_char  type;           /* request type, see below */
608 +       u_char  answer;         /* not used */
609 +       u_char  pad;
610 +       u_int32_t id_num;       /* message id */
611 +       struct  talk_addr addr;         /* old (4.3) style */
612 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
613 +       int32_t pid;            /* caller's process id */
614 +       char    l_name[TALK_NSIZE];/* caller's name */
615 +       char    r_name[TALK_NSIZE];/* callee's name */
616 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
617 +};
618 +
619 +struct ntalk2_msg {
620 +       u_char  vers;           /* talk protocol version    */
621 +       u_char  type;           /* request type             */
622 +       u_char  answer;         /*  */
623 +       u_char  extended;       /* !0 if additional parts   */
624 +       u_int32_t id_num;       /* message id number (dels) */
625 +       struct  talk_addr addr;         /* target address   */
626 +       struct  talk_addr ctl_addr;     /* reply to address */
627 +       int32_t pid;            /* caller's process id */
628 +       char    l_name[TALK_NSIZE];  /* caller's name */
629 +       char    r_name[TALK_NSIZE];  /* callee's name */
630 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
631 +};
632 +
633 +/*
634 + * Server->client response message formats.
635 + */
636 +struct talk_response {
637 +       u_char  type;           /* type of request message, see below */
638 +       u_char  answer;         /* response to request message, see below */
639 +       u_char  pad[2];
640 +       u_int32_t id_num;       /* message id */
641 +       struct  talk_addr addr; /* address for establishing conversation */
642 +};
643 +
644 +struct ntalk_response {
645 +       u_char  vers;           /* protocol version */
646 +       u_char  type;           /* type of request message, see below */
647 +       u_char  answer;         /* response to request message, see below */
648 +       u_char  pad;
649 +       u_int32_t id_num;       /* message id */
650 +       struct  talk_addr addr; /* address for establishing conversation */
651 +};
652 +
653 +struct ntalk2_response {
654 +       u_char  vers;           /* protocol version         */
655 +       u_char  type;           /* type of request message  */
656 +       u_char  answer;         /* response to request      */
657 +       u_char  rvers;          /* Version of answering vers*/
658 +       u_int32_t id_num;       /* message id number        */
659 +       struct  talk_addr addr; /* address for connection   */
660 +       /* This is at the end to compatiblize this with NTALK version.   */
661 +       char    r_name[TALK_NSIZE]; /* callee's name            */
662 +};
663 +
664 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
665 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
666 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
667 +
668 +#define        TALK_VERSION    0               /* protocol versions */
669 +#define        NTALK_VERSION   1
670 +#define        NTALK2_VERSION  2
671 +
672 +/* message type values */
673 +#define LEAVE_INVITE   0       /* leave invitation with server */
674 +#define LOOK_UP                1       /* check for invitation by callee */
675 +#define DELETE         2       /* delete invitation by caller */
676 +#define ANNOUNCE       3       /* announce invitation by caller */
677 +/* NTALK2 */
678 +#define REPLY_QUERY    4       /* request reply data from local daemon */
679 +
680 +/* answer values */
681 +#define SUCCESS                0       /* operation completed properly */
682 +#define NOT_HERE       1       /* callee not logged in */
683 +#define FAILED         2       /* operation failed for unexplained reason */
684 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
685 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
686 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
687 +#define        BADVERSION      6       /* request has invalid protocol version */
688 +#define        BADADDR         7       /* request has invalid addr value */
689 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
690 +/* NTALK2 */
691 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
692 +#define TRY_HERE       10      /* Not on this machine, try this      */
693 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
694 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
695 +
696 +/* We don't really need much for talk */
697 +struct ip_ct_talk_expect
698 +{
699 +       /* Port that was to be used */
700 +       u_int16_t port;
701 +};
702 +
703 +/* This structure exists only once per master */
704 +struct ip_ct_talk_master
705 +{
706 +};
707 +
708 +#endif /* _IP_CONNTRACK_TALK_H */
709 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
710 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h   2004-06-16 07:19:43.000000000 +0200
711 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_tuple.h       2004-06-25 12:24:52.000122360 +0200
712 @@ -25,6 +25,9 @@
713         struct {
714                 u_int16_t id;
715         } icmp;
716 +       struct {
717 +               u_int16_t port;
718 +       } sctp;
719  };
720  
721  /* The manipulable part of the tuple. */
722 @@ -55,6 +58,9 @@
723                         struct {
724                                 u_int8_t type, code;
725                         } icmp;
726 +                       struct {
727 +                               u_int16_t port;
728 +                       } sctp;
729                 } u;
730  
731                 /* The protocol. */
732 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.7/include/linux/netfilter_ipv4/ip_pool.h
733 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_pool.h      1970-01-01 01:00:00.000000000 +0100
734 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_pool.h  2004-06-25 12:21:11.460649456 +0200
735 @@ -0,0 +1,64 @@
736 +#ifndef _IP_POOL_H
737 +#define _IP_POOL_H
738 +
739 +/***************************************************************************/
740 +/*  This program is free software; you can redistribute it and/or modify   */
741 +/*  it under the terms of the GNU General Public License as published by   */
742 +/*  the Free Software Foundation; either version 2 of the License, or     */
743 +/*  (at your option) any later version.                                           */
744 +/*                                                                        */
745 +/*  This program is distributed in the hope that it will be useful,       */
746 +/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
747 +/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
748 +/*  GNU General Public License for more details.                          */
749 +/*                                                                        */
750 +/*  You should have received a copy of the GNU General Public License     */
751 +/*  along with this program; if not, write to the Free Software                   */
752 +/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
753 +/***************************************************************************/
754 +
755 +/* A sockopt of such quality has hardly ever been seen before on the open
756 + * market!  This little beauty, hardly ever used: above 64, so it's
757 + * traditionally used for firewalling, not touched (even once!) by the
758 + * 2.0, 2.2 and 2.4 kernels!
759 + *
760 + * Comes with its own certificate of authenticity, valid anywhere in the
761 + * Free world!
762 + *
763 + * Rusty, 19.4.2000
764 + */
765 +#define SO_IP_POOL 81
766 +
767 +typedef int ip_pool_t;                 /* pool index */
768 +#define IP_POOL_NONE   ((ip_pool_t)-1)
769 +
770 +struct ip_pool_request {
771 +       int op;
772 +       ip_pool_t index;
773 +       u_int32_t addr;
774 +       u_int32_t addr2;
775 +};
776 +
777 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
778 +
779 +#define IP_POOL_BAD001         0x00000010
780 +
781 +#define IP_POOL_FLUSH          0x00000011      /* req.index, no arguments */
782 +#define IP_POOL_INIT           0x00000012      /* from addr to addr2 incl. */
783 +#define IP_POOL_DESTROY                0x00000013      /* req.index, no arguments */
784 +#define IP_POOL_ADD_ADDR       0x00000014      /* add addr to pool */
785 +#define IP_POOL_DEL_ADDR       0x00000015      /* del addr from pool */
786 +#define IP_POOL_HIGH_NR                0x00000016      /* result in req.index */
787 +#define IP_POOL_LOOKUP         0x00000017      /* result in addr and addr2 */
788 +#define IP_POOL_USAGE          0x00000018      /* result in addr */
789 +#define IP_POOL_TEST_ADDR      0x00000019      /* result (0/1) returned */
790 +
791 +#ifdef __KERNEL__
792 +
793 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
794 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
795 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
796 +
797 +#endif
798 +
799 +#endif /*_IP_POOL_H*/
800 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_CONNMARK.h
801 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
802 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_CONNMARK.h     2004-06-25 12:21:25.479518264 +0200
803 @@ -0,0 +1,25 @@
804 +#ifndef _IPT_CONNMARK_H_target
805 +#define _IPT_CONNMARK_H_target
806 +
807 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
808 + * by Henrik Nordstrom <hno@marasystems.com>
809 + *
810 + * This program is free software; you can redistribute it and/or modify
811 + * it under the terms of the GNU General Public License as published by
812 + * the Free Software Foundation; either version 2 of the License, or
813 + * (at your option) any later version.
814 + */
815 +
816 +enum {
817 +       IPT_CONNMARK_SET = 0,
818 +       IPT_CONNMARK_SAVE,
819 +       IPT_CONNMARK_RESTORE
820 +};
821 +
822 +struct ipt_connmark_target_info {
823 +       unsigned long mark;
824 +       unsigned long mask;
825 +       u_int8_t mode;
826 +};
827 +
828 +#endif /*_IPT_CONNMARK_H_target*/
829 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_IPMARK.h
830 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_IPMARK.h   1970-01-01 01:00:00.000000000 +0100
831 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_IPMARK.h       2004-06-25 12:21:27.026283120 +0200
832 @@ -0,0 +1,13 @@
833 +#ifndef _IPT_IPMARK_H_target
834 +#define _IPT_IPMARK_H_target
835 +
836 +struct ipt_ipmark_target_info {
837 +       unsigned long andmask;
838 +       unsigned long ormask;
839 +       unsigned int addr;
840 +};
841 +
842 +#define IPT_IPMARK_SRC    0
843 +#define IPT_IPMARK_DST    1
844 +
845 +#endif /*_IPT_IPMARK_H_target*/
846 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_NETLINK.h
847 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_NETLINK.h  1970-01-01 01:00:00.000000000 +0100
848 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_NETLINK.h      2004-06-25 12:21:06.895343488 +0200
849 @@ -0,0 +1,27 @@
850 +#ifndef _IPT_FWMON_H
851 +#define _IPT_FWMON_H
852 +
853 +/* Bitmask macros */
854 +#define MASK(x,y) (x & y)
855 +#define MASK_SET(x,y) x |= y
856 +#define MASK_UNSET(x,y) x &= ~y
857 +
858 +#define USE_MARK       0x00000001
859 +#define USE_DROP       0x00000002
860 +#define USE_SIZE       0x00000004
861 +
862 +struct ipt_nldata
863 +{      
864 +       unsigned int flags;
865 +       unsigned int mark;
866 +       unsigned int size;
867 +};
868 +
869 +/* Old header */
870 +struct netlink_t {
871 +       unsigned int len;
872 +       unsigned int mark;
873 +       char iface[IFNAMSIZ];
874 +};
875 +
876 +#endif /*_IPT_FWMON_H*/
877 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ROUTE.h
878 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ROUTE.h    1970-01-01 01:00:00.000000000 +0100
879 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ROUTE.h        2004-06-25 12:21:28.210103152 +0200
880 @@ -0,0 +1,22 @@
881 +/* Header file for iptables ipt_ROUTE target
882 + *
883 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
884 + *
885 + * This software is distributed under GNU GPL v2, 1991
886 + */
887 +#ifndef _IPT_ROUTE_H_target
888 +#define _IPT_ROUTE_H_target
889 +
890 +#define IPT_ROUTE_IFNAMSIZ 16
891 +
892 +struct ipt_route_target_info {
893 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
894 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
895 +       u_int32_t gw;                           /* IP address of gateway */
896 +       u_int8_t  flags;
897 +};
898 +
899 +/* Values for "flags" field */
900 +#define IPT_ROUTE_CONTINUE        0x01
901 +
902 +#endif /*_IPT_ROUTE_H_target*/
903 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h
904 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h      1970-01-01 01:00:00.000000000 +0100
905 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h  2004-06-25 12:21:07.940184648 +0200
906 @@ -0,0 +1,21 @@
907 +/* TTL modification module for IP tables
908 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
909 +
910 +#ifndef _IPT_TTL_H
911 +#define _IPT_TTL_H
912 +
913 +enum {
914 +       IPT_TTL_SET = 0,
915 +       IPT_TTL_INC,
916 +       IPT_TTL_DEC
917 +};
918 +
919 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
920 +
921 +struct ipt_TTL_info {
922 +       u_int8_t        mode;
923 +       u_int8_t        ttl;
924 +};
925 +
926 +
927 +#endif
928 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_XOR.h
929 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_XOR.h      1970-01-01 01:00:00.000000000 +0100
930 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_XOR.h  2004-06-25 12:21:31.653579664 +0200
931 @@ -0,0 +1,9 @@
932 +#ifndef _IPT_XOR_H
933 +#define _IPT_XOR_H
934 +
935 +struct ipt_XOR_info {
936 +       char            key[30];
937 +       u_int8_t        block_size;
938 +};
939 +
940 +#endif /* _IPT_XOR_H */
941 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_account.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_account.h
942 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_account.h  1970-01-01 01:00:00.000000000 +0100
943 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_account.h      2004-06-25 12:21:32.612433896 +0200
944 @@ -0,0 +1,21 @@
945 +/* 
946 + * accounting match (ipt_account.c)
947 + * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
948 + *
949 + * Version: 0.1.5
950 + *
951 + * This software is distributed under the terms of GNU GPL
952 + */
953 +
954 +#ifndef _IPT_ACCOUNT_H_
955 +#define _IPT_ACCOUNT_H_
956 +
957 +#define IPT_ACCOUNT_NAME_LEN 64
958 +
959 +struct t_ipt_account_info {
960 +       char name[IPT_ACCOUNT_NAME_LEN];
961 +       u_int32_t network;
962 +       u_int32_t netmask;
963 +};
964 +
965 +#endif
966 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_connmark.h
967 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
968 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_connmark.h     2004-06-25 12:21:25.482517808 +0200
969 @@ -0,0 +1,18 @@
970 +#ifndef _IPT_CONNMARK_H
971 +#define _IPT_CONNMARK_H
972 +
973 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
974 + * by Henrik Nordstrom <hno@marasystems.com>
975 + *
976 + * This program is free software; you can redistribute it and/or modify
977 + * it under the terms of the GNU General Public License as published by
978 + * the Free Software Foundation; either version 2 of the License, or
979 + * (at your option) any later version.
980 + */
981 +
982 +struct ipt_connmark_info {
983 +       unsigned long mark, mask;
984 +       u_int8_t invert;
985 +};
986 +
987 +#endif /*_IPT_CONNMARK_H*/
988 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h
989 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
990 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h     2004-06-25 12:21:08.427110624 +0200
991 @@ -0,0 +1,39 @@
992 +#ifndef _IPT_DSTLIMIT_H
993 +#define _IPT_DSTLIMIT_H
994 +
995 +/* timings are in milliseconds. */
996 +#define IPT_DSTLIMIT_SCALE 10000
997 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
998 +   seconds, or one every 59 hours. */
999 +
1000 +/* details of this structure hidden by the implementation */
1001 +struct ipt_dstlimit_htable;
1002 +
1003 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
1004 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
1005 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
1006 +
1007 +struct dstlimit_cfg {
1008 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
1009 +       u_int32_t avg;    /* Average secs between packets * scale */
1010 +       u_int32_t burst;  /* Period multiplier for upper limit. */
1011 +
1012 +       /* user specified */
1013 +       u_int32_t size;         /* how many buckets */
1014 +       u_int32_t max;          /* max number of entries */
1015 +       u_int32_t gc_interval;  /* gc interval */
1016 +       u_int32_t expire;       /* when do entries expire? */
1017 +};
1018 +
1019 +struct ipt_dstlimit_info {
1020 +       char name [IFNAMSIZ];           /* name */
1021 +       struct dstlimit_cfg cfg;
1022 +       struct ipt_dstlimit_htable *hinfo;
1023 +
1024 +       /* Used internally by the kernel */
1025 +       union {
1026 +               void *ptr;
1027 +               struct ipt_dstlimit_info *master;
1028 +       } u;
1029 +};
1030 +#endif /*_IPT_DSTLIMIT_H*/
1031 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h
1032 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h    1970-01-01 01:00:00.000000000 +0100
1033 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h        2004-06-25 12:21:08.958029912 +0200
1034 @@ -0,0 +1,21 @@
1035 +#ifndef _IPT_FUZZY_H
1036 +#define _IPT_FUZZY_H
1037 +
1038 +#include <linux/param.h>
1039 +#include <linux/types.h>
1040 +
1041 +#define MAXFUZZYRATE 10000000
1042 +#define MINFUZZYRATE 3
1043 +
1044 +struct ipt_fuzzy_info {
1045 +       u_int32_t minimum_rate;
1046 +       u_int32_t maximum_rate;
1047 +       u_int32_t packets_total;
1048 +       u_int32_t bytes_total;
1049 +       u_int32_t previous_time;
1050 +       u_int32_t present_time;
1051 +       u_int32_t mean_rate;
1052 +       u_int8_t acceptance_rate;
1053 +};
1054 +
1055 +#endif /*_IPT_FUZZY_H*/
1056 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h
1057 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h      1970-01-01 01:00:00.000000000 +0100
1058 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h  2004-06-25 12:21:09.436957104 +0200
1059 @@ -0,0 +1,21 @@
1060 +#ifndef __ipt_ipv4options_h_included__
1061 +#define __ipt_ipv4options_h_included__
1062 +
1063 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
1064 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
1065 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
1066 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
1067 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
1068 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
1069 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
1070 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
1071 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1072 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
1073 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
1074 +
1075 +struct ipt_ipv4options_info {
1076 +       u_int16_t options;
1077 +};
1078 +
1079 +
1080 +#endif /* __ipt_ipv4options_h_included__ */
1081 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h
1082 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h    1970-01-01 01:00:00.000000000 +0100
1083 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h        2004-06-25 12:21:09.924882928 +0200
1084 @@ -0,0 +1,24 @@
1085 +#ifndef _IPT_MPORT_H
1086 +#define _IPT_MPORT_H
1087 +#include <linux/netfilter_ipv4/ip_tables.h>
1088 +
1089 +#define IPT_MPORT_SOURCE (1<<0)
1090 +#define IPT_MPORT_DESTINATION (1<<1)
1091 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1092 +
1093 +#define IPT_MULTI_PORTS        15
1094 +
1095 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1096 +/* every entry in ports[] except for the last one has one bit in pflags
1097 + * associated with it. If this bit is set, the port is the first port of
1098 + * a portrange, with the next entry being the last.
1099 + * End of list is marked with pflags bit set and port=65535.
1100 + * If 14 ports are used (last one does not have a pflag), the last port
1101 + * is repeated to fill the last entry in ports[] */
1102 +struct ipt_mport
1103 +{
1104 +       u_int8_t flags:2;                       /* Type of comparison */
1105 +       u_int16_t pflags:14;                    /* Port flags */
1106 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
1107 +};
1108 +#endif /*_IPT_MPORT_H*/
1109 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h
1110 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h      1970-01-01 01:00:00.000000000 +0100
1111 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h  2004-06-25 12:21:10.456802064 +0200
1112 @@ -0,0 +1,19 @@
1113 +#ifndef _IPT_NTH_H
1114 +#define _IPT_NTH_H
1115 +
1116 +#include <linux/param.h>
1117 +#include <linux/types.h>
1118 +
1119 +#ifndef IPT_NTH_NUM_COUNTERS
1120 +#define IPT_NTH_NUM_COUNTERS 16
1121 +#endif
1122 +
1123 +struct ipt_nth_info {
1124 +       u_int8_t every;
1125 +       u_int8_t not;
1126 +       u_int8_t startat;
1127 +       u_int8_t counter;
1128 +       u_int8_t packet;
1129 +};
1130 +
1131 +#endif /*_IPT_NTH_H*/
1132 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h
1133 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h      1970-01-01 01:00:00.000000000 +0100
1134 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h  2004-06-25 12:21:10.970723936 +0200
1135 @@ -0,0 +1,148 @@
1136 +/*
1137 + * ipt_osf.h
1138 + *
1139 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1140 + *
1141 + *
1142 + * This program is free software; you can redistribute it and/or modify
1143 + * it under the terms of the GNU General Public License as published by
1144 + * the Free Software Foundation; either version 2 of the License, or
1145 + * (at your option) any later version.
1146 + *
1147 + * This program is distributed in the hope that it will be useful,
1148 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1149 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1150 + * GNU General Public License for more details.
1151 + *
1152 + * You should have received a copy of the GNU General Public License
1153 + * along with this program; if not, write to the Free Software
1154 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1155 + */
1156 +
1157 +#ifndef _IPT_OSF_H
1158 +#define _IPT_OSF_H
1159 +
1160 +#define MAXGENRELEN            32
1161 +#define MAXDETLEN              64
1162 +
1163 +#define IPT_OSF_GENRE          1
1164 +#define        IPT_OSF_SMART           2
1165 +#define IPT_OSF_LOG            4
1166 +#define IPT_OSF_NETLINK                8
1167 +
1168 +#define IPT_OSF_LOGLEVEL_ALL   0
1169 +#define IPT_OSF_LOGLEVEL_FIRST 1
1170 +
1171 +#include <linux/list.h>
1172 +
1173 +#ifndef __KERNEL__
1174 +#include <netinet/ip.h>
1175 +#include <netinet/tcp.h>
1176 +
1177 +struct list_head
1178 +{
1179 +       struct list_head *prev, *next;
1180 +};
1181 +#endif
1182 +
1183 +struct ipt_osf_info
1184 +{
1185 +       char                    genre[MAXGENRELEN];
1186 +       int                     len;
1187 +       unsigned long           flags;
1188 +       int                     loglevel;
1189 +       int                     invert; /* UNSUPPORTED */
1190 +};
1191 +
1192 +struct osf_wc
1193 +{
1194 +       char                    wc;
1195 +       unsigned long           val;
1196 +};
1197 +
1198 +/* This struct represents IANA options
1199 + * http://www.iana.org/assignments/tcp-parameters
1200 + */
1201 +struct osf_opt
1202 +{
1203 +       unsigned char           kind;
1204 +       unsigned char           length;
1205 +       struct osf_wc           wc;
1206 +};
1207 +
1208 +struct osf_finger
1209 +{
1210 +       struct list_head        flist;
1211 +       struct osf_wc           wss;
1212 +       unsigned char           ttl;
1213 +       unsigned char           df;
1214 +       unsigned long           ss;
1215 +       unsigned char           genre[MAXGENRELEN];
1216 +       unsigned char           version[MAXGENRELEN], subtype[MAXGENRELEN];
1217 +       
1218 +       /* Not needed, but for consistency with original table from Michal Zalewski */
1219 +       unsigned char           details[MAXDETLEN]; 
1220 +
1221 +       int                     opt_num;
1222 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1223 +
1224 +};
1225 +
1226 +struct ipt_osf_nlmsg
1227 +{
1228 +       struct osf_finger       f;
1229 +       struct iphdr            ip;
1230 +       struct tcphdr           tcp;
1231 +};
1232 +
1233 +#ifdef __KERNEL__
1234 +
1235 +/* Defines for IANA option kinds */
1236 +
1237 +#define OSFOPT_EOL             0       /* End of options */
1238 +#define OSFOPT_NOP             1       /* NOP */
1239 +#define OSFOPT_MSS             2       /* Maximum segment size */
1240 +#define OSFOPT_WSO             3       /* Window scale option */
1241 +#define OSFOPT_SACKP           4       /* SACK permitted */
1242 +#define OSFOPT_SACK            5       /* SACK */
1243 +#define OSFOPT_ECHO            6       
1244 +#define OSFOPT_ECHOREPLY       7
1245 +#define OSFOPT_TS              8       /* Timestamp option */
1246 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
1247 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
1248 +/* Others are not used in current OSF */
1249 +
1250 +static struct osf_opt IANA_opts[] = 
1251 +{
1252 +       {0, 1,},
1253 +       {1, 1,},
1254 +       {2, 4,},
1255 +       {3, 3,},
1256 +       {4, 2,},
1257 +       {5, 1 ,}, /* SACK length is not defined */
1258 +       {6, 6,},
1259 +       {7, 6,},
1260 +       {8, 10,},
1261 +       {9, 2,},
1262 +       {10, 3,},
1263 +       {11, 1,}, /* CC: Suppose 1 */
1264 +       {12, 1,}, /* the same */
1265 +       {13, 1,}, /* and here too */
1266 +       {14, 3,},
1267 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1268 +       {16, 1,},
1269 +       {17, 1,},
1270 +       {18, 3,},
1271 +       {19, 18,},
1272 +       {20, 1,},
1273 +       {21, 1,},
1274 +       {22, 1,},
1275 +       {23, 1,},
1276 +       {24, 1,},
1277 +       {25, 1,},
1278 +       {26, 1,},
1279 +};
1280 +
1281 +#endif /* __KERNEL__ */
1282 +
1283 +#endif /* _IPT_OSF_H */
1284 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_policy.h
1285 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_policy.h   1970-01-01 01:00:00.000000000 +0100
1286 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_policy.h       2004-03-08 05:19:04.000000000 +0100
1287 @@ -0,0 +1,52 @@
1288 +#ifndef _IPT_POLICY_H
1289 +#define _IPT_POLICY_H
1290 +
1291 +#define POLICY_MAX_ELEM        4
1292 +
1293 +enum ipt_policy_flags
1294 +{
1295 +       POLICY_MATCH_IN         = 0x1,
1296 +       POLICY_MATCH_OUT        = 0x2,
1297 +       POLICY_MATCH_NONE       = 0x4,
1298 +       POLICY_MATCH_STRICT     = 0x8,
1299 +};
1300 +
1301 +enum ipt_policy_modes
1302 +{
1303 +       POLICY_MODE_TRANSPORT,
1304 +       POLICY_MODE_TUNNEL
1305 +};
1306 +
1307 +struct ipt_policy_spec
1308 +{
1309 +       u_int8_t        saddr:1,
1310 +                       daddr:1,
1311 +                       proto:1,
1312 +                       mode:1,
1313 +                       spi:1,
1314 +                       reqid:1;
1315 +};
1316 +
1317 +struct ipt_policy_elem
1318 +{
1319 +       u_int32_t       saddr;
1320 +       u_int32_t       smask;
1321 +       u_int32_t       daddr;
1322 +       u_int32_t       dmask;
1323 +       u_int32_t       spi;
1324 +       u_int32_t       reqid;
1325 +       u_int8_t        proto;
1326 +       u_int8_t        mode;
1327 +
1328 +       struct ipt_policy_spec  match;
1329 +       struct ipt_policy_spec  invert;
1330 +};
1331 +
1332 +struct ipt_policy_info
1333 +{
1334 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1335 +       u_int16_t flags;
1336 +       u_int16_t len;
1337 +};
1338 +
1339 +#endif /* _IPT_POLICY_H */
1340 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_pool.h
1341 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_pool.h     1970-01-01 01:00:00.000000000 +0100
1342 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_pool.h 2004-06-25 12:21:11.462649152 +0200
1343 @@ -0,0 +1,25 @@
1344 +#ifndef _IPT_POOL_H
1345 +#define _IPT_POOL_H
1346 +
1347 +#include <linux/netfilter_ipv4/ip_pool.h>
1348 +
1349 +#define IPT_POOL_INV_SRC       0x00000001
1350 +#define IPT_POOL_INV_DST       0x00000002
1351 +#define IPT_POOL_DEL_SRC       0x00000004
1352 +#define IPT_POOL_DEL_DST       0x00000008
1353 +#define IPT_POOL_INV_MOD_SRC   0x00000010
1354 +#define IPT_POOL_INV_MOD_DST   0x00000020
1355 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
1356 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
1357 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
1358 +#define IPT_POOL_MOD_DST_DROP  0x00000200
1359 +
1360 +/* match info */
1361 +struct ipt_pool_info
1362 +{
1363 +       ip_pool_t src;
1364 +       ip_pool_t dst;
1365 +       unsigned flags;
1366 +};
1367 +
1368 +#endif /*_IPT_POOL_H*/
1369 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h
1370 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h      1970-01-01 01:00:00.000000000 +0100
1371 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h  2004-06-25 12:21:11.945575736 +0200
1372 @@ -0,0 +1,40 @@
1373 +#ifndef _IPT_PSD_H
1374 +#define _IPT_PSD_H
1375 +
1376 +#include <linux/param.h>
1377 +#include <linux/types.h>
1378 +
1379 +/*
1380 + * High port numbers have a lower weight to reduce the frequency of false
1381 + * positives, such as from passive mode FTP transfers.
1382 + */
1383 +#define PORT_WEIGHT_PRIV               3
1384 +#define PORT_WEIGHT_HIGH               1
1385 +
1386 +/*
1387 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1388 + * from the same source, with no longer than DELAY ticks between ports.
1389 + */
1390 +#define SCAN_MIN_COUNT                 7
1391 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1392 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
1393 +#define SCAN_DELAY_THRESHOLD           (300) /* old usage of HZ here was erroneously and broke under uml */
1394 +
1395 +/*
1396 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1397 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1398 + * HASH_MAX source addresses per the same hash value.
1399 + */
1400 +#define LIST_SIZE                      0x100
1401 +#define HASH_LOG                       9
1402 +#define HASH_SIZE                      (1 << HASH_LOG)
1403 +#define HASH_MAX                       0x10
1404 +
1405 +struct ipt_psd_info {
1406 +       unsigned int weight_threshold;
1407 +       unsigned int delay_threshold;
1408 +       unsigned short lo_ports_weight;
1409 +       unsigned short hi_ports_weight;
1410 +};
1411 +
1412 +#endif /*_IPT_PSD_H*/
1413 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h
1414 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h    1970-01-01 01:00:00.000000000 +0100
1415 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h        2004-06-25 12:21:12.433501560 +0200
1416 @@ -0,0 +1,11 @@
1417 +#ifndef _IPT_QUOTA_H
1418 +#define _IPT_QUOTA_H
1419 +
1420 +/* print debug info in both kernel/netfilter module & iptable library */
1421 +//#define DEBUG_IPT_QUOTA
1422 +
1423 +struct ipt_quota_info {
1424 +        u_int64_t quota;
1425 +};
1426 +
1427 +#endif /*_IPT_QUOTA_H*/
1428 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_random.h
1429 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_random.h   1970-01-01 01:00:00.000000000 +0100
1430 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_random.h       2004-06-25 12:21:12.934425408 +0200
1431 @@ -0,0 +1,11 @@
1432 +#ifndef _IPT_RAND_H
1433 +#define _IPT_RAND_H
1434 +
1435 +#include <linux/param.h>
1436 +#include <linux/types.h>
1437 +
1438 +struct ipt_rand_info {
1439 +       u_int8_t average;
1440 +};
1441 +
1442 +#endif /*_IPT_RAND_H*/
1443 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h
1444 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h     1970-01-01 01:00:00.000000000 +0100
1445 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h 2004-06-25 12:21:13.445347736 +0200
1446 @@ -0,0 +1,107 @@
1447 +#ifndef _IPT_SCTP_H_
1448 +#define _IPT_SCTP_H_
1449 +
1450 +#define IPT_SCTP_SRC_PORTS             0x01
1451 +#define IPT_SCTP_DEST_PORTS            0x02
1452 +#define IPT_SCTP_CHUNK_TYPES           0x04
1453 +
1454 +#define IPT_SCTP_VALID_FLAGS           0x07
1455 +
1456 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1457 +
1458 +
1459 +struct ipt_sctp_flag_info {
1460 +       u_int8_t chunktype;
1461 +       u_int8_t flag;
1462 +       u_int8_t flag_mask;
1463 +};
1464 +
1465 +#define IPT_NUM_SCTP_FLAGS     4
1466 +
1467 +struct ipt_sctp_info {
1468 +       u_int16_t dpts[2];  /* Min, Max */
1469 +       u_int16_t spts[2];  /* Min, Max */
1470 +
1471 +       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
1472 +
1473 +#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
1474 +#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
1475 +#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
1476 +
1477 +       u_int32_t chunk_match_type;
1478 +       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1479 +       int flag_count;
1480 +
1481 +       u_int32_t flags;
1482 +       u_int32_t invflags;
1483 +};
1484 +
1485 +#define bytes(type) (sizeof(type) * 8)
1486 +
1487 +#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
1488 +       do {                                            \
1489 +               chunkmap[type / bytes(u_int32_t)] |=    \
1490 +                       1 << (type % bytes(u_int32_t)); \
1491 +       } while (0)
1492 +
1493 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
1494 +       do {                                                    \
1495 +               chunkmap[type / bytes(u_int32_t)] &=            \
1496 +                       ~(1 << (type % bytes(u_int32_t)));      \
1497 +       } while (0)
1498 +
1499 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
1500 +({                                                             \
1501 +       (chunkmap[type / bytes (u_int32_t)] &                   \
1502 +               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
1503 +})
1504 +
1505 +#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
1506 +       do {                                                    \
1507 +               int i;                                          \
1508 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1509 +                       chunkmap[i] = 0;                        \
1510 +       } while (0)
1511 +
1512 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
1513 +       do {                                                    \
1514 +               int i;                                          \
1515 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1516 +                       chunkmap[i] = ~0;                       \
1517 +       } while (0)
1518 +
1519 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
1520 +       do {                                                    \
1521 +               int i;                                          \
1522 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1523 +                       destmap[i] = srcmap[i];                 \
1524 +       } while (0)
1525 +
1526 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
1527 +({                                                     \
1528 +       int i;                                          \
1529 +       int flag = 1;                                   \
1530 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1531 +               if (chunkmap[i]) {                      \
1532 +                       flag = 0;                       \
1533 +                       break;                          \
1534 +               }                                       \
1535 +       }                                               \
1536 +        flag;                                          \
1537 +})
1538 +
1539 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
1540 +({                                                     \
1541 +       int i;                                          \
1542 +       int flag = 1;                                   \
1543 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1544 +               if (chunkmap[i] != ~0) {                \
1545 +                       flag = 0;                       \
1546 +                               break;                  \
1547 +               }                                       \
1548 +       }                                               \
1549 +        flag;                                          \
1550 +})
1551 +
1552 +#endif /* _IPT_SCTP_H_ */
1553 +
1554 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_string.h
1555 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_string.h   1970-01-01 01:00:00.000000000 +0100
1556 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_string.h       2004-06-25 12:28:38.565679160 +0200
1557 @@ -0,0 +1,21 @@
1558 +#ifndef _IPT_STRING_H
1559 +#define _IPT_STRING_H
1560 +
1561 +/* *** PERFORMANCE TWEAK ***
1562 + * Packet size and search string threshold,
1563 + * above which sublinear searches is used. */
1564 +#define IPT_STRING_HAYSTACK_THRESH     100
1565 +#define IPT_STRING_NEEDLE_THRESH       20
1566 +
1567 +#define BM_MAX_NLEN 256
1568 +#define BM_MAX_HLEN 1024
1569 +
1570 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1571 +
1572 +struct ipt_string_info {
1573 +    char string[BM_MAX_NLEN];
1574 +    u_int16_t invert;
1575 +    u_int16_t len;
1576 +};
1577 +
1578 +#endif /* _IPT_STRING_H */
1579 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h
1580 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h     1970-01-01 01:00:00.000000000 +0100
1581 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h 2004-06-25 12:21:13.932273712 +0200
1582 @@ -0,0 +1,15 @@
1583 +#ifndef __ipt_time_h_included__
1584 +#define __ipt_time_h_included__
1585 +
1586 +
1587 +struct ipt_time_info {
1588 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
1589 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
1590 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
1591 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
1592 +       time_t    date_start;
1593 +       time_t    date_stop;
1594 +};
1595 +
1596 +
1597 +#endif /* __ipt_time_h_included__ */
1598 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h
1599 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h      1970-01-01 01:00:00.000000000 +0100
1600 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h  2004-06-25 12:21:14.420199536 +0200
1601 @@ -0,0 +1,40 @@
1602 +#ifndef _IPT_U32_H
1603 +#define _IPT_U32_H
1604 +#include <linux/netfilter_ipv4/ip_tables.h>
1605 +
1606 +enum ipt_u32_ops
1607 +{
1608 +       IPT_U32_AND,
1609 +       IPT_U32_LEFTSH,
1610 +       IPT_U32_RIGHTSH,
1611 +       IPT_U32_AT
1612 +};
1613 +
1614 +struct ipt_u32_location_element
1615 +{
1616 +       u_int32_t number;
1617 +       u_int8_t nextop;
1618 +};
1619 +struct ipt_u32_value_element
1620 +{
1621 +       u_int32_t min;
1622 +       u_int32_t max;
1623 +};
1624 +/* *** any way to allow for an arbitrary number of elements?
1625 +   for now I settle for a limit of 10 of each */
1626 +#define U32MAXSIZE 10
1627 +struct ipt_u32_test
1628 +{
1629 +       u_int8_t nnums;
1630 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
1631 +       u_int8_t nvalues;
1632 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
1633 +};
1634 +
1635 +struct ipt_u32
1636 +{
1637 +       u_int8_t ntests;
1638 +       struct ipt_u32_test tests[U32MAXSIZE+1];
1639 +};
1640 +
1641 +#endif /*_IPT_U32_H*/
1642 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4.h linux-2.6.7/include/linux/netfilter_ipv4.h
1643 --- linux-2.6.7.org/include/linux/netfilter_ipv4.h      2004-06-16 07:19:52.000000000 +0200
1644 +++ linux-2.6.7/include/linux/netfilter_ipv4.h  2004-06-25 12:21:37.077755064 +0200
1645 @@ -7,6 +7,8 @@
1646  
1647  #include <linux/config.h>
1648  #include <linux/netfilter.h>
1649 +#include <linux/netdevice.h>
1650 +#include <net/protocol.h>
1651  
1652  /* IP Cache bits. */
1653  /* Src IP address. */
1654 @@ -85,6 +87,58 @@
1655     Returns true or false. */
1656  extern int skb_ip_make_writable(struct sk_buff **pskb,
1657                                 unsigned int writable_len);
1658 +
1659 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1660 +#include <net/route.h>
1661 +#include <net/xfrm.h>
1662 +
1663 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1664 +{
1665 +       return !skb->sp || skb->sp->decap_done;
1666 +}
1667 +
1668 +static inline int
1669 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1670 +{
1671 +       return skb->sp && !skb->sp->decap_done
1672 +              && (!ipprot || !ipprot->xfrm_prot);
1673 +}
1674 +
1675 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1676 +{
1677 +       return skb->sp && !skb->sp->decap_done
1678 +              && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1679 +}
1680 +
1681 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1682 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1683 +#else /* CONFIG_XFRM */
1684 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1685 +{
1686 +       return 1;
1687 +}
1688 +
1689 +static inline int
1690 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1691 +{
1692 +       return 0;
1693 +}
1694 +
1695 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1696 +{
1697 +       return 0;
1698 +}
1699 +
1700 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1701 +{
1702 +       return 0;
1703 +}
1704 +
1705 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1706 +{
1707 +       return 0; 
1708 +}
1709 +#endif /* CONFIG_XFRM */
1710  #endif /*__KERNEL__*/
1711  
1712  #endif /*__LINUX_IP_NETFILTER_H*/
1713 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h
1714 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h      1970-01-01 01:00:00.000000000 +0100
1715 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h  2004-06-25 12:21:05.613538352 +0200
1716 @@ -0,0 +1,22 @@
1717 +/* Hop Limit modification module for ip6tables
1718 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1719 + * Based on HW's TTL module */
1720 +
1721 +#ifndef _IP6T_HL_H
1722 +#define _IP6T_HL_H
1723 +
1724 +enum {
1725 +       IP6T_HL_SET = 0,
1726 +       IP6T_HL_INC,
1727 +       IP6T_HL_DEC
1728 +};
1729 +
1730 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
1731 +
1732 +struct ip6t_HL_info {
1733 +       u_int8_t        mode;
1734 +       u_int8_t        hop_limit;
1735 +};
1736 +
1737 +
1738 +#endif
1739 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h
1740 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-06-16 07:18:38.000000000 +0200
1741 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-06-25 12:21:07.506250616 +0200
1742 @@ -2,15 +2,17 @@
1743  #define _IP6T_REJECT_H
1744  
1745  enum ip6t_reject_with {
1746 -       IP6T_ICMP_NET_UNREACHABLE,
1747 -       IP6T_ICMP_HOST_UNREACHABLE,
1748 -       IP6T_ICMP_PROT_UNREACHABLE,
1749 -       IP6T_ICMP_PORT_UNREACHABLE,
1750 -       IP6T_ICMP_ECHOREPLY
1751 +       IP6T_ICMP6_NO_ROUTE,
1752 +       IP6T_ICMP6_ADM_PROHIBITED,
1753 +       IP6T_ICMP6_NOT_NEIGHBOUR,
1754 +       IP6T_ICMP6_ADDR_UNREACH,
1755 +       IP6T_ICMP6_PORT_UNREACH,
1756 +       IP6T_ICMP6_ECHOREPLY,
1757 +       IP6T_TCP_RESET
1758  };
1759  
1760  struct ip6t_reject_info {
1761         enum ip6t_reject_with with;      /* reject type */
1762  };
1763  
1764 -#endif /*_IPT_REJECT_H*/
1765 +#endif /*_IP6T_REJECT_H*/
1766 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h
1767 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h   1970-01-01 01:00:00.000000000 +0100
1768 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h       2004-06-25 12:21:28.212102848 +0200
1769 @@ -0,0 +1,22 @@
1770 +/* Header file for iptables ip6t_ROUTE target
1771 + *
1772 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
1773 + *
1774 + * This software is distributed under GNU GPL v2, 1991
1775 + */
1776 +#ifndef _IPT_ROUTE_H_target
1777 +#define _IPT_ROUTE_H_target
1778 +
1779 +#define IP6T_ROUTE_IFNAMSIZ 16
1780 +
1781 +struct ip6t_route_target_info {
1782 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
1783 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
1784 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
1785 +       u_int8_t  flags;
1786 +};
1787 +
1788 +/* Values for "flags" field */
1789 +#define IP6T_ROUTE_CONTINUE        0x01
1790 +
1791 +#endif /*_IP6T_ROUTE_H_target*/
1792 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1793 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h   1970-01-01 01:00:00.000000000 +0100
1794 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h       2004-06-25 12:21:08.960029608 +0200
1795 @@ -0,0 +1,21 @@
1796 +#ifndef _IP6T_FUZZY_H
1797 +#define _IP6T_FUZZY_H
1798 +
1799 +#include <linux/param.h>
1800 +#include <linux/types.h>
1801 +
1802 +#define MAXFUZZYRATE 10000000
1803 +#define MINFUZZYRATE 3
1804 +
1805 +struct ip6t_fuzzy_info {
1806 +       u_int32_t minimum_rate;
1807 +       u_int32_t maximum_rate;
1808 +       u_int32_t packets_total;
1809 +       u_int32_t bytes_total;
1810 +       u_int32_t previous_time;
1811 +       u_int32_t present_time;
1812 +       u_int32_t mean_rate;
1813 +       u_int8_t acceptance_rate;
1814 +};
1815 +
1816 +#endif /*_IP6T_FUZZY_H*/
1817 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h
1818 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h     1970-01-01 01:00:00.000000000 +0100
1819 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h 2004-06-25 12:21:10.458801760 +0200
1820 @@ -0,0 +1,19 @@
1821 +#ifndef _IP6T_NTH_H
1822 +#define _IP6T_NTH_H
1823 +
1824 +#include <linux/param.h>
1825 +#include <linux/types.h>
1826 +
1827 +#ifndef IP6T_NTH_NUM_COUNTERS
1828 +#define IP6T_NTH_NUM_COUNTERS 16
1829 +#endif
1830 +
1831 +struct ip6t_nth_info {
1832 +       u_int8_t every;
1833 +       u_int8_t not;
1834 +       u_int8_t startat;
1835 +       u_int8_t counter;
1836 +       u_int8_t packet;
1837 +};
1838 +
1839 +#endif /*_IP6T_NTH_H*/
1840 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_owner.h
1841 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_owner.h   2004-06-16 07:19:37.000000000 +0200
1842 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_owner.h       2004-06-25 12:23:17.497488944 +0200
1843 @@ -6,12 +6,14 @@
1844  #define IP6T_OWNER_GID 0x02
1845  #define IP6T_OWNER_PID 0x04
1846  #define IP6T_OWNER_SID 0x08
1847 +#define IP6T_OWNER_COMM 0x10
1848  
1849  struct ip6t_owner_info {
1850      uid_t uid;
1851      gid_t gid;
1852      pid_t pid;
1853      pid_t sid;
1854 +    char comm[16];
1855      u_int8_t match, invert;    /* flags */
1856  };
1857  
1858 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_policy.h
1859 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_policy.h  1970-01-01 01:00:00.000000000 +0100
1860 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_policy.h      2004-05-07 18:20:56.000000000 +0200
1861 @@ -0,0 +1,52 @@
1862 +#ifndef _IP6T_POLICY_H
1863 +#define _IP6T_POLICY_H
1864 +
1865 +#define POLICY_MAX_ELEM        4
1866 +
1867 +enum ip6t_policy_flags
1868 +{
1869 +       POLICY_MATCH_IN         = 0x1,
1870 +       POLICY_MATCH_OUT        = 0x2,
1871 +       POLICY_MATCH_NONE       = 0x4,
1872 +       POLICY_MATCH_STRICT     = 0x8,
1873 +};
1874 +
1875 +enum ip6t_policy_modes
1876 +{
1877 +       POLICY_MODE_TRANSPORT,
1878 +       POLICY_MODE_TUNNEL
1879 +};
1880 +
1881 +struct ip6t_policy_spec
1882 +{
1883 +       u_int8_t        saddr:1,
1884 +                       daddr:1,
1885 +                       proto:1,
1886 +                       mode:1,
1887 +                       spi:1,
1888 +                       reqid:1;
1889 +};
1890 +
1891 +struct ip6t_policy_elem
1892 +{
1893 +       struct in6_addr saddr;
1894 +       struct in6_addr smask;
1895 +       struct in6_addr daddr;
1896 +       struct in6_addr dmask;
1897 +       u_int32_t       spi;
1898 +       u_int32_t       reqid;
1899 +       u_int8_t        proto;
1900 +       u_int8_t        mode;
1901 +
1902 +       struct ip6t_policy_spec match;
1903 +       struct ip6t_policy_spec invert;
1904 +};
1905 +
1906 +struct ip6t_policy_info
1907 +{
1908 +       struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
1909 +       u_int16_t flags;
1910 +       u_int16_t len;
1911 +};
1912 +
1913 +#endif /* _IP6T_POLICY_H */
1914 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_random.h
1915 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_random.h  1970-01-01 01:00:00.000000000 +0100
1916 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_random.h      2004-06-25 12:21:12.936425104 +0200
1917 @@ -0,0 +1,11 @@
1918 +#ifndef _IP6T_RAND_H
1919 +#define _IP6T_RAND_H
1920 +
1921 +#include <linux/param.h>
1922 +#include <linux/types.h>
1923 +
1924 +struct ip6t_rand_info {
1925 +       u_int8_t average;
1926 +};
1927 +
1928 +#endif /*_IP6T_RAND_H*/
1929 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_mime.h linux-2.6.7/include/linux/netfilter_mime.h
1930 --- linux-2.6.7.org/include/linux/netfilter_mime.h      1970-01-01 01:00:00.000000000 +0100
1931 +++ linux-2.6.7/include/linux/netfilter_mime.h  2004-06-25 12:24:50.030421800 +0200
1932 @@ -0,0 +1,89 @@
1933 +/*
1934 + * MIME functions for netfilter modules.  This file provides implementations
1935 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
1936 + * HTTP, RTSP, SIP, etc.
1937 + *
1938 + * gcc will warn for defined but unused functions, so we only include the
1939 + * functions requested.  The following macros are used:
1940 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
1941 + */
1942 +#ifndef _NETFILTER_MIME_H
1943 +#define _NETFILTER_MIME_H
1944 +
1945 +/* Only include these functions for kernel code. */
1946 +#ifdef __KERNEL__
1947 +
1948 +#include <linux/ctype.h>
1949 +
1950 +/*
1951 + * Given a buffer and length, advance to the next line and mark the current
1952 + * line.  If the current line is empty, *plinelen will be set to zero.  If
1953 + * not, it will be set to the actual line length (including CRLF).
1954 + *
1955 + * 'line' in this context means logical line (includes LWS continuations).
1956 + * Returns 1 on success, 0 on failure.
1957 + */
1958 +#ifdef NF_NEED_MIME_NEXTLINE
1959 +static int
1960 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1961 +{
1962 +    uint    off = *poff;
1963 +    uint    physlen = 0;
1964 +    int     is_first_line = 1;
1965 +
1966 +    if (off >= len)
1967 +    {
1968 +        return 0;
1969 +    }
1970 +
1971 +    do
1972 +    {
1973 +        while (p[off] != '\n')
1974 +        {
1975 +            if (len-off <= 1)
1976 +            {
1977 +                return 0;
1978 +            }
1979 +
1980 +            physlen++;
1981 +            off++;
1982 +        }
1983 +
1984 +        /* if we saw a crlf, physlen needs adjusted */
1985 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1986 +        {
1987 +            physlen--;
1988 +        }
1989 +
1990 +        /* advance past the newline */
1991 +        off++;
1992 +
1993 +        /* check for an empty line */
1994 +        if (physlen == 0)
1995 +        {
1996 +            break;
1997 +        }
1998 +
1999 +        /* check for colon on the first physical line */
2000 +        if (is_first_line)
2001 +        {
2002 +            is_first_line = 0;
2003 +            if (memchr(p+(*poff), ':', physlen) == NULL)
2004 +            {
2005 +                return 0;
2006 +            }
2007 +        }
2008 +    }
2009 +    while (p[off] == ' ' || p[off] == '\t');
2010 +
2011 +    *plineoff = *poff;
2012 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
2013 +    *poff = off;
2014 +
2015 +    return 1;
2016 +}
2017 +#endif /* NF_NEED_MIME_NEXTLINE */
2018 +
2019 +#endif /* __KERNEL__ */
2020 +
2021 +#endif /* _NETFILTER_MIME_H */
2022 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/sysctl.h linux-2.6.7/include/linux/sysctl.h
2023 --- linux-2.6.7.org/include/linux/sysctl.h      2004-06-25 10:47:45.500884880 +0200
2024 +++ linux-2.6.7/include/linux/sysctl.h  2004-06-25 12:21:02.311040408 +0200
2025 @@ -410,6 +410,7 @@
2026         NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
2027         NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
2028         NET_IPV4_NF_CONNTRACK_BUCKETS=14,
2029 +       NET_IPV4_NF_CONNTRACK_LOG_INVALID=15,
2030  };
2031   
2032  /* /proc/sys/net/ipv6 */
2033 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/ip.h linux-2.6.7/include/net/ip.h
2034 --- linux-2.6.7.org/include/net/ip.h    2004-06-25 10:47:45.530880320 +0200
2035 +++ linux-2.6.7/include/net/ip.h        2004-06-25 12:21:36.157894904 +0200
2036 @@ -30,6 +30,8 @@
2037  #include <linux/netdevice.h>
2038  #include <linux/inetdevice.h>
2039  #include <linux/in_route.h>
2040 +#include <linux/netfilter.h>
2041 +#include <linux/netfilter_ipv4.h>
2042  #include <net/route.h>
2043  #include <net/arp.h>
2044  
2045 @@ -48,6 +50,7 @@
2046  #define IPSKB_TRANSLATED       2
2047  #define IPSKB_FORWARDED                4
2048  #define IPSKB_XFRM_TUNNEL_SIZE 8
2049 +#define IPSKB_XFRM_TRANSFORMED 16
2050  };
2051  
2052  struct ipcm_cookie
2053 @@ -212,6 +215,12 @@
2054                 __ip_select_ident(iph, dst, more);
2055  }
2056  
2057 +extern inline int ip_dst_output(struct sk_buff *skb)
2058 +{
2059 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2060 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2061 +}
2062 +
2063  /*
2064   *     Map a multicast IP onto multicast MAC for type ethernet.
2065   */
2066 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/protocol.h linux-2.6.7/include/net/protocol.h
2067 --- linux-2.6.7.org/include/net/protocol.h      2004-06-25 10:47:45.548877584 +0200
2068 +++ linux-2.6.7/include/net/protocol.h  2004-06-25 12:21:37.079754760 +0200
2069 @@ -38,6 +38,7 @@
2070         int                     (*handler)(struct sk_buff *skb);
2071         void                    (*err_handler)(struct sk_buff *skb, u32 info);
2072         int                     no_policy;
2073 +       int                     xfrm_prot;
2074  };
2075  
2076  #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2077 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/tcp.h linux-2.6.7/include/net/tcp.h
2078 --- linux-2.6.7.org/include/net/tcp.h   2004-06-25 10:47:45.569874392 +0200
2079 +++ linux-2.6.7/include/net/tcp.h       2004-06-25 12:23:15.996717096 +0200
2080 @@ -163,6 +163,7 @@
2081  extern void tcp_bucket_unlock(struct sock *sk);
2082  extern int tcp_port_rover;
2083  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2084 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2085  
2086  /* These are AF independent. */
2087  static __inline__ int tcp_bhashfn(__u16 lport)
2088 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/udp.h linux-2.6.7/include/net/udp.h
2089 --- linux-2.6.7.org/include/net/udp.h   2004-06-16 07:19:51.000000000 +0200
2090 +++ linux-2.6.7/include/net/udp.h       2004-06-25 12:23:15.998716792 +0200
2091 @@ -74,6 +74,8 @@
2092  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2093  extern int     udp_disconnect(struct sock *sk, int flags);
2094  
2095 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2096 +
2097  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2098  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
2099  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
2100 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/xfrm.h linux-2.6.7/include/net/xfrm.h
2101 --- linux-2.6.7.org/include/net/xfrm.h  2004-06-25 10:47:45.574873632 +0200
2102 +++ linux-2.6.7/include/net/xfrm.h      2004-06-25 12:21:37.084754000 +0200
2103 @@ -536,6 +536,9 @@
2104  {
2105         atomic_t                refcnt;
2106         int                     len;
2107 +#ifdef CONFIG_NETFILTER
2108 +       int                     decap_done;
2109 +#endif
2110         struct sec_decap_state  x[XFRM_MAX_DEPTH];
2111  };
2112  
2113 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/core/netfilter.c linux-2.6.7/net/core/netfilter.c
2114 --- linux-2.6.7.org/net/core/netfilter.c        2004-06-16 07:19:22.000000000 +0200
2115 +++ linux-2.6.7/net/core/netfilter.c    2004-06-25 12:21:38.699508520 +0200
2116 @@ -27,6 +27,8 @@
2117  #include <linux/icmp.h>
2118  #include <net/sock.h>
2119  #include <net/route.h>
2120 +#include <net/xfrm.h>
2121 +#include <net/ip.h>
2122  #include <linux/ip.h>
2123  
2124  /* In this code, we can be waiting indefinitely for userspace to
2125 @@ -630,7 +632,6 @@
2126  #ifdef CONFIG_IP_ROUTE_FWMARK
2127                 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2128  #endif
2129 -               fl.proto = iph->protocol;
2130                 if (ip_route_output_key(&rt, &fl) != 0)
2131                         return -1;
2132  
2133 @@ -657,6 +658,20 @@
2134         if ((*pskb)->dst->error)
2135                 return -1;
2136  
2137 +#ifdef CONFIG_XFRM
2138 +       if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2139 +               struct xfrm_policy_afinfo *afinfo;
2140 +
2141 +               afinfo = xfrm_policy_get_afinfo(AF_INET);
2142 +               if (afinfo != NULL) {
2143 +                       afinfo->decode_session(*pskb, &fl);
2144 +                       xfrm_policy_put_afinfo(afinfo);
2145 +                       if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2146 +                               return -1;
2147 +               }
2148 +       }
2149 +#endif
2150 +
2151         /* Change in oif may mean change in hh_len. */
2152         hh_len = (*pskb)->dst->dev->hard_header_len;
2153         if (skb_headroom(*pskb) < hh_len) {
2154 @@ -674,6 +689,71 @@
2155         return 0;
2156  }
2157  
2158 +#ifdef CONFIG_XFRM
2159 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2160 +{
2161 +       skb->sp->decap_done = 1;
2162 +       dst_release(skb->dst);
2163 +       skb->dst = NULL;
2164 +       nf_reset(skb);
2165 +       return netif_rx(skb);
2166 +}
2167 +
2168 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2169 +{
2170 +       __skb_push(skb, skb->data - skb->nh.raw);
2171 +       /* Fix header len and checksum if last xfrm was transport mode */
2172 +       if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2173 +               skb->nh.iph->tot_len = htons(skb->len);
2174 +               ip_send_check(skb->nh.iph);
2175 +       }
2176 +       return nf_rcv_postxfrm_nonlocal(skb);
2177 +}
2178 +
2179 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2180 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2181 +#include <linux/netfilter_ipv4/ip_nat.h>
2182 +
2183 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2184 +{
2185 +       struct ip_conntrack *ct;
2186 +       struct ip_conntrack_tuple *t;
2187 +       struct ip_nat_info_manip *m;
2188 +       unsigned int i;
2189 +
2190 +       if (skb->nfct == NULL)
2191 +               return;
2192 +       ct = (struct ip_conntrack *)skb->nfct->master;
2193 +
2194 +       for (i = 0; i < ct->nat.info.num_manips; i++) {
2195 +               m = &ct->nat.info.manips[i];
2196 +               t = &ct->tuplehash[m->direction].tuple;
2197 +
2198 +               switch (m->hooknum) {
2199 +               case NF_IP_PRE_ROUTING:
2200 +                       if (m->maniptype != IP_NAT_MANIP_DST)
2201 +                               break;
2202 +                       fl->fl4_dst = t->dst.ip;
2203 +                       if (t->dst.protonum == IPPROTO_TCP ||
2204 +                           t->dst.protonum == IPPROTO_UDP)
2205 +                               fl->fl_ip_dport = t->dst.u.tcp.port;
2206 +                       break;
2207 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2208 +               case NF_IP_LOCAL_IN:
2209 +                       if (m->maniptype != IP_NAT_MANIP_SRC)
2210 +                               break;
2211 +                       fl->fl4_src = t->src.ip;
2212 +                       if (t->dst.protonum == IPPROTO_TCP ||
2213 +                           t->dst.protonum == IPPROTO_UDP)
2214 +                               fl->fl_ip_sport = t->src.u.tcp.port;
2215 +                       break;
2216 +#endif
2217 +               }
2218 +       }
2219 +}
2220 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2221 +#endif
2222 +
2223  int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2224  {
2225         struct sk_buff *nskb;
2226 @@ -831,3 +911,4 @@
2227  EXPORT_SYMBOL(nf_unregister_hook);
2228  EXPORT_SYMBOL(nf_unregister_queue_handler);
2229  EXPORT_SYMBOL(nf_unregister_sockopt);
2230 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2231 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ah4.c linux-2.6.7/net/ipv4/ah4.c
2232 --- linux-2.6.7.org/net/ipv4/ah4.c      2004-06-25 10:47:45.935818760 +0200
2233 +++ linux-2.6.7/net/ipv4/ah4.c  2004-06-25 12:21:37.092752784 +0200
2234 @@ -149,6 +149,7 @@
2235                 err = -EHOSTUNREACH;
2236                 goto error_nolock;
2237         }
2238 +       IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
2239         return NET_XMIT_BYPASS;
2240  
2241  error:
2242 @@ -347,6 +348,7 @@
2243         .handler        =       xfrm4_rcv,
2244         .err_handler    =       ah4_err,
2245         .no_policy      =       1,
2246 +       .xfrm_prot      =       1,
2247  };
2248  
2249  static int __init ah4_init(void)
2250 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/esp4.c linux-2.6.7/net/ipv4/esp4.c
2251 --- linux-2.6.7.org/net/ipv4/esp4.c     2004-06-25 10:47:45.939818152 +0200
2252 +++ linux-2.6.7/net/ipv4/esp4.c 2004-06-25 12:21:37.095752328 +0200
2253 @@ -218,6 +218,7 @@
2254                 err = -EHOSTUNREACH;
2255                 goto error_nolock;
2256         }
2257 +       IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
2258         return NET_XMIT_BYPASS;
2259  
2260  error:
2261 @@ -599,6 +600,7 @@
2262         .handler        =       xfrm4_rcv,
2263         .err_handler    =       esp4_err,
2264         .no_policy      =       1,
2265 +       .xfrm_prot      =       1,
2266  };
2267  
2268  static int __init esp4_init(void)
2269 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/igmp.c linux-2.6.7/net/ipv4/igmp.c
2270 --- linux-2.6.7.org/net/ipv4/igmp.c     2004-06-16 07:20:22.000000000 +0200
2271 +++ linux-2.6.7/net/ipv4/igmp.c 2004-06-25 12:21:36.172892624 +0200
2272 @@ -343,7 +343,7 @@
2273         pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2274  
2275         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2276 -                      dst_output);
2277 +                      ip_dst_output);
2278  }
2279  
2280  static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2281 @@ -673,7 +673,7 @@
2282         ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2283  
2284         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2285 -                      dst_output);
2286 +                      ip_dst_output);
2287  }
2288  
2289  static void igmp_gq_timer_expire(unsigned long data)
2290 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ip_forward.c linux-2.6.7/net/ipv4/ip_forward.c
2291 --- linux-2.6.7.org/net/ipv4/ip_forward.c       2004-06-16 07:18:38.000000000 +0200
2292 +++ linux-2.6.7/net/ipv4/ip_forward.c   2004-06-25 12:21:36.173892472 +0200
2293 @@ -51,7 +51,7 @@
2294         if (unlikely(opt->optlen))
2295                 ip_forward_options(skb);
2296  
2297 -       return dst_output(skb);
2298 +       return ip_dst_output(skb);
2299  }
2300  
2301  int ip_forward(struct sk_buff *skb)
2302 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ip_input.c linux-2.6.7/net/ipv4/ip_input.c
2303 --- linux-2.6.7.org/net/ipv4/ip_input.c 2004-06-25 10:47:45.954815872 +0200
2304 +++ linux-2.6.7/net/ipv4/ip_input.c     2004-06-25 12:21:38.702508064 +0200
2305 @@ -206,10 +206,6 @@
2306  
2307         __skb_pull(skb, ihl);
2308  
2309 -       /* Free reference early: we don't need it any more, and it may
2310 -           hold ip_conntrack module loaded indefinitely. */
2311 -       nf_reset(skb);
2312 -
2313          /* Point into the IP datagram, just past the header. */
2314          skb->h.raw = skb->data;
2315  
2316 @@ -224,6 +220,13 @@
2317         resubmit:
2318                 hash = protocol & (MAX_INET_PROTOS - 1);
2319                 raw_sk = sk_head(&raw_v4_htable[hash]);
2320 +               ipprot = inet_protos[hash];
2321 +               smp_read_barrier_depends();
2322 +
2323 +               if (nf_xfrm_local_done(skb, ipprot)) {
2324 +                       nf_rcv_postxfrm_local(skb);
2325 +                       goto out;
2326 +               }
2327  
2328                 /* If there maybe a raw socket we must check - if not we
2329                  * don't care less
2330 @@ -231,14 +234,15 @@
2331                 if (raw_sk)
2332                         raw_v4_input(skb, skb->nh.iph, hash);
2333  
2334 -               if ((ipprot = inet_protos[hash]) != NULL) {
2335 +               if (ipprot != NULL) {
2336                         int ret;
2337  
2338 -                       smp_read_barrier_depends();
2339 -                       if (!ipprot->no_policy &&
2340 -                           !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2341 -                               kfree_skb(skb);
2342 -                               goto out;
2343 +                       if (!ipprot->no_policy) {
2344 +                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2345 +                                       kfree_skb(skb);
2346 +                                       goto out;
2347 +                               }
2348 +                               nf_reset(skb);
2349                         }
2350                         ret = ipprot->handler(skb);
2351                         if (ret < 0) {
2352 @@ -279,8 +283,8 @@
2353                         return 0;
2354         }
2355  
2356 -       return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2357 -                      ip_local_deliver_finish);
2358 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2359 +                           ip_local_deliver_finish, nf_hook_input_cond(skb));
2360  }
2361  
2362  static inline int ip_rcv_finish(struct sk_buff *skb)
2363 @@ -297,6 +301,9 @@
2364                         goto drop; 
2365         }
2366  
2367 +       if (nf_xfrm_nonlocal_done(skb))
2368 +               return nf_rcv_postxfrm_nonlocal(skb);
2369 +
2370  #ifdef CONFIG_NET_CLS_ROUTE
2371         if (skb->dst->tclassid) {
2372                 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2373 @@ -418,8 +425,8 @@
2374                 }
2375         }
2376  
2377 -       return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2378 -                      ip_rcv_finish);
2379 +       return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2380 +                           ip_rcv_finish, nf_hook_input_cond(skb));
2381  
2382  inhdr_error:
2383         IP_INC_STATS_BH(InHdrErrors);
2384 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ip_output.c linux-2.6.7/net/ipv4/ip_output.c
2385 --- linux-2.6.7.org/net/ipv4/ip_output.c        2004-06-25 10:47:45.959815112 +0200
2386 +++ linux-2.6.7/net/ipv4/ip_output.c    2004-06-25 12:21:36.181891256 +0200
2387 @@ -123,6 +123,15 @@
2388         return ttl;
2389  }
2390  
2391 +#ifdef CONFIG_NETFILTER
2392 +/* out-of-line copy is only required with netfilter */
2393 +int ip_dst_output(struct sk_buff *skb)
2394 +{
2395 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2396 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2397 +}
2398 +#endif
2399 +
2400  /* 
2401   *             Add an ip header to a skbuff and send it out.
2402   *
2403 @@ -165,7 +174,7 @@
2404  
2405         /* Send it out. */
2406         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2407 -                      dst_output);
2408 +                      ip_dst_output);
2409  }
2410  
2411  static inline int ip_finish_output2(struct sk_buff *skb)
2412 @@ -284,7 +293,7 @@
2413                 return ip_finish_output(skb);
2414  }
2415  
2416 -int ip_output(struct sk_buff **pskb)
2417 +static inline int ip_output2(struct sk_buff **pskb)
2418  {
2419         struct sk_buff *skb = *pskb;
2420  
2421 @@ -297,6 +306,16 @@
2422                 return ip_finish_output(skb);
2423  }
2424  
2425 +int ip_output(struct sk_buff *skb)
2426 +{
2427 +       int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2428 +
2429 +       if (transformed)
2430 +               nf_reset(skb);
2431 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2432 +                           skb->dst->dev, ip_output2, transformed);
2433 +}
2434 +
2435  int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2436  {
2437         struct sock *sk = skb->sk;
2438 @@ -390,7 +409,7 @@
2439         skb->priority = sk->sk_priority;
2440  
2441         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2442 -                      dst_output);
2443 +                      ip_dst_output);
2444  
2445  no_route:
2446         IP_INC_STATS(OutNoRoutes);
2447 @@ -1169,7 +1188,7 @@
2448  
2449         /* Netfilter gets whole the not fragmented skb. */
2450         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
2451 -                     skb->dst->dev, dst_output);
2452 +                     skb->dst->dev, ip_dst_output);
2453         if (err) {
2454                 if (err > 0)
2455                         err = inet->recverr ? net_xmit_errno(err) : 0;
2456 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ipcomp.c linux-2.6.7/net/ipv4/ipcomp.c
2457 --- linux-2.6.7.org/net/ipv4/ipcomp.c   2004-06-25 10:47:45.966814048 +0200
2458 +++ linux-2.6.7/net/ipv4/ipcomp.c       2004-06-25 12:21:37.102751264 +0200
2459 @@ -236,6 +236,7 @@
2460                 err = -EHOSTUNREACH;
2461                 goto error_nolock;
2462         }
2463 +       IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
2464         err = NET_XMIT_BYPASS;
2465  
2466  out_exit:
2467 @@ -413,6 +414,7 @@
2468         .handler        =       xfrm4_rcv,
2469         .err_handler    =       ipcomp4_err,
2470         .no_policy      =       1,
2471 +       .xfrm_prot      =       1,
2472  };
2473  
2474  static int __init ipcomp4_init(void)
2475 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ipip.c linux-2.6.7/net/ipv4/ipip.c
2476 --- linux-2.6.7.org/net/ipv4/ipip.c     2004-06-25 10:47:45.975812680 +0200
2477 +++ linux-2.6.7/net/ipv4/ipip.c 2004-06-25 12:21:37.107750504 +0200
2478 @@ -478,6 +478,11 @@
2479  
2480         read_lock(&ipip_lock);
2481         if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2482 +               /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2483 +               if (nf_xfrm_local_done(skb, NULL)) {
2484 +                       nf_rcv_postxfrm_local(skb);
2485 +                       return 0;
2486 +               }
2487                 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2488                         read_unlock(&ipip_lock);
2489                         kfree_skb(skb);
2490 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/ipmr.c linux-2.6.7/net/ipv4/ipmr.c
2491 --- linux-2.6.7.org/net/ipv4/ipmr.c     2004-06-25 10:47:45.982811616 +0200
2492 +++ linux-2.6.7/net/ipv4/ipmr.c 2004-06-25 12:21:36.190889888 +0200
2493 @@ -1117,7 +1117,7 @@
2494         if (unlikely(opt->optlen))
2495                 ip_forward_options(skb);
2496  
2497 -       return dst_output(skb);
2498 +       return ip_dst_output(skb);
2499  }
2500  
2501  /*
2502 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Kconfig linux-2.6.7/net/ipv4/netfilter/Kconfig
2503 --- linux-2.6.7.org/net/ipv4/netfilter/Kconfig  2004-06-25 10:47:45.000000000 +0200
2504 +++ linux-2.6.7/net/ipv4/netfilter/Kconfig      2004-06-25 12:28:43.699898640 +0200
2505 @@ -206,6 +206,11 @@
2506  
2507           To compile it as a module, choose M here.  If unsure, say N.
2508  
2509 +config IP_NF_MATCH_UNCLEAN
2510 +       tristate  'unclean match support (EXPERIMENTAL)'
2511 +       depends on EXPERIMENTAL && IP_NF_IPTABLES
2512 +         help
2513 +
2514  config IP_NF_MATCH_TTL
2515         tristate "TTL match support"
2516         depends on IP_NF_IPTABLES
2517 @@ -627,5 +632,459 @@
2518           If you want to compile it as a module, say M here and read
2519           Documentation/modules.txt.  If unsure, say `N'.
2520  
2521 +config IP_NF_TARGET_IPV4OPTSSTRIP
2522 +       tristate  'IPV4OPTSSTRIP target support'
2523 +       depends on IP_NF_MANGLE
2524 +       help
2525 +         This option adds an IPV4OPTSSTRIP target.
2526 +         This target allows you to strip all IP options in a packet.
2527 +        
2528 +         If you want to compile it as a module, say M here and read
2529 +         Documentation/modules.txt.  If unsure, say `N'.
2530 +
2531 +config IP_NF_TARGET_NETLINK
2532 +       tristate  'NETLINK target support'
2533 +       depends on IP_NF_FILTER
2534 +       help
2535 +         The NETLINK target allows you to recieve packets in userspace via
2536 +         the kernel firewall netlink socket. Apps such as fwmon
2537 +         (http://firestorm.geek-ware.co.uk) can then recieve and dislpay
2538 +         these packets. This option is basically a re-implementation of the
2539 +         ipchains -o option.
2540 +
2541 +config IP_NF_TARGET_TTL
2542 +       tristate  'TTL target support'
2543 +       depends on IP_NF_MANGLE
2544 +       help
2545 +         This option adds a `TTL' target, which enables the user to set
2546 +         the TTL value or increment / decrement the TTL value by a given
2547 +         amount.
2548 +       
2549 +         If you want to compile it as a module, say M here and read
2550 +         Documentation/modules.txt.  If unsure, say `N'.
2551 +
2552 +config IP_NF_MATCH_DSTLIMIT
2553 +       tristate  'dstlimit match support'
2554 +       depends on IP_NF_IPTABLES
2555 +
2556 +config IP_NF_MATCH_FUZZY
2557 +       tristate  'fuzzy match support'
2558 +       depends on IP_NF_IPTABLES
2559 +       help
2560 +         This option adds a `fuzzy' match, which allows you to match
2561 +         packets according to a fuzzy logic based law.
2562 +       
2563 +         If you want to compile it as a module, say M here and read
2564 +         Documentation/modules.txt.  If unsure, say `N'.
2565 +
2566 +config IP_NF_MATCH_IPV4OPTIONS
2567 +       tristate  'IPV4OPTIONS match support'
2568 +       depends on IP_NF_IPTABLES
2569 +       help
2570 +         This option adds a IPV4OPTIONS match.
2571 +         It allows you to filter options like source routing,
2572 +         record route, timestamp and router-altert.
2573 +       
2574 +         If you say Y here, try iptables -m ipv4options --help for more information.
2575 +        
2576 +         If you want to compile it as a module, say M here and read
2577 +         Documentation/modules.txt.  If unsure, say `N'.
2578 +
2579 +config IP_NF_MATCH_MPORT
2580 +       tristate  'Multiple port with ranges match support'
2581 +       depends on IP_NF_IPTABLES
2582 +       help
2583 +         This is an enhanced multiport match which supports port
2584 +         ranges as well as single ports.
2585 +       
2586 +         If you want to compile it as a module, say M here and read
2587 +         Documentation/modules.txt.  If unsure, say `N'.
2588 +
2589 +config IP_NF_MATCH_NTH
2590 +       tristate  'Nth match support'
2591 +       depends on IP_NF_IPTABLES
2592 +       help
2593 +         This option adds a `Nth' match, which allow you to make
2594 +         rules that match every Nth packet.  By default there are 
2595 +         16 different counters.
2596 +       
2597 +         [options]
2598 +          --every     Nth              Match every Nth packet
2599 +         [--counter]  num              Use counter 0-15 (default:0)
2600 +         [--start]    num              Initialize the counter at the number 'num'
2601 +                                       instead of 0. Must be between 0 and Nth-1
2602 +         [--packet]   num              Match on 'num' packet. Must be between 0
2603 +                                       and Nth-1.
2604 +       
2605 +                                       If --packet is used for a counter than
2606 +                                       there must be Nth number of --packet
2607 +                                       rules, covering all values between 0 and
2608 +                                       Nth-1 inclusively.
2609 +        
2610 +         If you want to compile it as a module, say M here and read
2611 +         Documentation/modules.txt.  If unsure, say `N'.
2612 +
2613 +config IP_NF_MATCH_OSF
2614 +       tristate  'OSF match support'
2615 +       depends on IP_NF_IPTABLES
2616 +       help
2617 +       
2618 +         The idea of passive OS fingerprint matching exists for quite a long time,
2619 +         but was created as extension fo OpenBSD pf only some weeks ago.
2620 +         Original idea was lurked in some OpenBSD mailing list (thanks
2621 +         grange@open...) and than adopted for Linux netfilter in form of this code.
2622 +       
2623 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
2624 +         his excellent p0f and than changed a bit for more convenience.
2625 +       
2626 +         This module compares some data(WS, MSS, options and it's order, ttl,
2627 +         df and others) from first SYN packet (actually from packets with SYN
2628 +         bit set) with hardcoded in fingers[] table ones.
2629 +       
2630 +         If you say Y here, try iptables -m osf --help for more information.
2631 +        
2632 +         If you want to compile it as a module, say M here and read
2633 +         Documentation/modules.txt.  If unsure, say `N'.
2634 +
2635 +config IP_POOL_STATISTICS
2636 +       bool  'enable statistics on pool usage'
2637 +       depends on IP_NF_POOL!=n
2638 +       help
2639 +         This option controls whether usage gathering code is compiled into the
2640 +         ip_pool module.  Disabling statistics may be substantially faster.
2641 +
2642 +config IP_NF_POOL
2643 +       tristate  'IP address pool support'
2644 +       depends on IP_NF_IPTABLES
2645 +       help
2646 +         Pool matching lets you use bitmaps with one bit per address from some
2647 +         range of IP addresses; the match depends on whether a checked source
2648 +         or destination address has its bit set in the pool.
2649 +       
2650 +         There is also a POOL netfilter target, which can be used to set or remove
2651 +         the addresses of a packet from a pool.
2652 +       
2653 +         To define and use pools, you need userlevel utilities: a patched iptables,
2654 +         and the program ippool(8), which defines the pools and their bounds.
2655 +         The current release of pool matching is ippool-0.0.2, and can be found
2656 +         in the archives of the netfilter mailing list at
2657 +         http://lists.samba.org/netfilter/.
2658 +       
2659 +         If you want to compile it as a module, say M here and read
2660 +         Documentation/modules.txt.  If unsure, say `N'.
2661 +
2662 +config IP_NF_MATCH_PSD
2663 +       tristate  'psd match support'
2664 +       depends on IP_NF_IPTABLES
2665 +       help
2666 +         This option adds a `psd' match, which allows you to create rules in
2667 +         any iptables table wich will detect TCP and UDP port scans.
2668 +        
2669 +         If you want to compile it as a module, say M here and read
2670 +         Documentation/modules.txt.  If unsure, say `N'.
2671 +
2672 +config IP_NF_MATCH_QUOTA
2673 +       tristate  'quota match support'
2674 +       depends on IP_NF_IPTABLES
2675 +       help
2676 +         This match implements network quotas.
2677 +       
2678 +         If you want to compile it as a module, say M here and read
2679 +         Documentation/modules.txt.  If unsure, say `N'.
2680 +       
2681 +
2682 +config IP_NF_MATCH_RANDOM
2683 +       tristate  'random match support'
2684 +       depends on IP_NF_IPTABLES
2685 +       help
2686 +         This option adds a `random' match,
2687 +         which allow you to match packets randomly
2688 +         following a given probability.
2689 +        
2690 +         If you want to compile it as a module, say M here and read
2691 +         Documentation/modules.txt.  If unsure, say `N'.
2692 +
2693 +config IP_NF_MATCH_SCTP
2694 +       tristate  'SCTP protocol match support'
2695 +       depends on IP_NF_IPTABLES
2696 +
2697 +config IP_NF_MATCH_TIME
2698 +       tristate  'TIME match support'
2699 +       depends on IP_NF_IPTABLES
2700 +       help
2701 +         This option adds a `time' match, which allows you
2702 +         to match based on the packet arrival time/date
2703 +         (arrival time/date at the machine which netfilter is running on) or
2704 +         departure time/date (for locally generated packets).
2705 +       
2706 +         If you say Y here, try iptables -m time --help for more information.
2707 +        
2708 +         If you want to compile it as a module, say M here and read
2709 +         Documentation/modules.txt.  If unsure, say `N'.
2710 +
2711 +config IP_NF_MATCH_U32
2712 +       tristate  'U32 match support'
2713 +       depends on IP_NF_IPTABLES
2714 +       help
2715 +         U32 allows you to extract quantities of up to 4 bytes from a packet,
2716 +         AND them with specified masks, shift them by specified amounts and
2717 +         test whether the results are in any of a set of specified ranges.
2718 +         The specification of what to extract is general enough to skip over
2719 +         headers with lengths stored in the packet, as in IP or TCP header
2720 +         lengths.
2721 +       
2722 +         Details and examples are in the kernel module source.
2723 +
2724 +config IP_NF_CONNTRACK_MARK
2725 +       bool  'Connection mark tracking support'
2726 +       help
2727 +         This option enables support for connection marks, used by the
2728 +         `CONNMARK' target and `connmark' match. Similar to the mark value
2729 +         of packets, but this mark value is kept in the conntrack session
2730 +         instead of the individual packets.
2731 +       
2732 +config IP_NF_TARGET_CONNMARK
2733 +       tristate  'CONNMARK target support'
2734 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
2735 +       help
2736 +         This option adds a `CONNMARK' target, which allows one to manipulate
2737 +         the connection mark value.  Similar to the MARK target, but
2738 +         affects the connection mark value rather than the packet mark value.
2739 +       
2740 +         If you want to compile it as a module, say M here and read
2741 +         Documentation/modules.txt.  The module will be called
2742 +         ipt_CONNMARK.o.  If unsure, say `N'.
2743 +       
2744 +config IP_NF_MATCH_CONNMARK
2745 +       tristate  ' Connection mark match support'
2746 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES
2747 +       help
2748 +         This option adds a `connmark' match, which allows you to match the
2749 +         connection mark value previously set for the session by `CONNMARK'. 
2750 +       
2751 +         If you want to compile it as a module, say M here and read
2752 +         Documentation/modules.txt.  The module will be called
2753 +         ipt_connmark.o.  If unsure, say `N'.
2754 +
2755 +config IP_NF_TARGET_IPMARK
2756 +       tristate  'IPMARK target support'
2757 +       depends on IP_NF_MANGLE
2758 +       help
2759 +         This option adds a `IPMARK' target, which allows you to create rules
2760 +         in the `mangle' table which alter the netfilter mark (nfmark) field
2761 +         basing on the source or destination ip address of the packet.
2762 +         This is very useful for very fast massive mangling and marking.
2763 +       
2764 +         If you want to compile it as a module, say M here and read
2765 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
2766 +
2767 +config IP_NF_TARGET_ROUTE
2768 +       tristate  'ROUTE target support'
2769 +       depends on IP_NF_MANGLE
2770 +       help
2771 +         This option adds a `ROUTE' target, which enables you to setup unusual
2772 +         routes. For example, the ROUTE lets you route a received packet through 
2773 +         an interface or towards a host, even if the regular destination of the 
2774 +         packet is the router itself. The ROUTE target is also able to change the 
2775 +         incoming interface of a packet.
2776 +       
2777 +         The target can be or not a final target. It has to be used inside the 
2778 +         mangle table.
2779 +         
2780 +         If you want to compile it as a module, say M here and read
2781 +         Documentation/modules.txt.  The module will be called ipt_ROUTE.o.
2782 +         If unsure, say `N'.
2783 +
2784 +config IP_NF_TARGET_TARPIT
2785 +       tristate 'TARPIT target support'
2786 +       depends on IP_NF_FILTER
2787 +       help
2788 +         Adds a TARPIT target to iptables, which captures and holds
2789 +         incoming TCP connections using no local per-connection resources.
2790 +         Connections are accepted, but immediately switched to the persist
2791 +         state (0 byte window), in which the remote side stops sending data
2792 +         and asks to continue every 60-240 seconds.  Attempts to close the
2793 +         connection are ignored, forcing the remote side to time out the
2794 +         connection in 12-24 minutes.
2795 +       
2796 +         This offers similar functionality to LaBrea
2797 +         <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
2798 +         hardware or IPs.  Any TCP port that you would normally DROP or REJECT
2799 +         can instead become a tarpit.
2800 +
2801 +config IP_NF_TARGET_TRACE
2802 +       tristate  'TRACE target support'
2803 +       depends on IP_NF_RAW
2804 +       help
2805 +         The TRACE target allows packets to be traced as those
2806 +         matches any subsequent rule in any table/rule. The matched
2807 +         rule and the packet is logged with the prefix
2808 +       
2809 +         TRACE: tablename/chainname/rulenum  
2810 +       
2811 +         If you want to compile it as a module, say M here and read
2812 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
2813 +
2814 +config IP_NF_TARGET_XOR
2815 +       tristate  'XOR target support'
2816 +       depends on IP_NF_MANGLE
2817 +       help
2818 +         This option adds a `XOR' target, which can encrypt TCP and 
2819 +         UDP traffic using a simple XOR encryption.
2820 +       
2821 +         If you want to compile it as a module, say M here and read
2822 +         Documentation/modules.txt.  If unsure, say `N'.
2823 +
2824 +config IP_NF_EGG
2825 +       tristate  'Eggdrop bot support'
2826 +       depends on IP_NF_CONNTRACK
2827 +       help
2828 +         If you are running an eggdrop hub bot on this machine, then you
2829 +         may want to enable this feature. This enables eggdrop bots to share
2830 +         their user file to other eggdrop bots.
2831 +       
2832 +         If you want to compile it as a module, say M here and read
2833 +         Documentation/modules.txt.  If unsure, say `N'.
2834 +
2835 +config IP_NF_NAT_H323
2836 +       tristate
2837 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2838 +       default IP_NF_NAT if IP_NF_H323=y
2839 +       default m if IP_NF_H323=m
2840 +
2841 +config IP_NF_H323
2842 +       tristate  'H.323 (netmeeting) support'
2843 +       depends on IP_NF_CONNTRACK
2844 +       help
2845 +         H.323 is a standard signalling protocol used by teleconferencing
2846 +         softwares like netmeeting. With the ip_conntrack_h323 and
2847 +         the ip_nat_h323 modules you can support the protocol on a connection
2848 +         tracking/NATing firewall.
2849 +       
2850 +         If you want to compile it as a module, say 'M' here and read
2851 +         Documentation/modules.txt.  If unsure, say 'N'.
2852 +
2853 +config IP_NF_NAT_MMS
2854 +       tristate
2855 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2856 +       default IP_NF_NAT if IP_NF_MMS=y
2857 +       default m if IP_NF_MMS=m
2858 +
2859 +config IP_NF_MMS
2860 +       tristate  'MMS protocol support'
2861 +       depends on IP_NF_CONNTRACK
2862 +       help
2863 +         Tracking MMS (Microsoft Windows Media Services) connections
2864 +         could be problematic if random ports are used to send the
2865 +         streaming content. This option allows users to track streaming
2866 +         connections over random UDP or TCP ports.
2867 +       
2868 +         If you want to compile it as a module, say M here and read
2869 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
2870 +
2871 +config IP_NF_NAT_QUAKE3
2872 +       tristate
2873 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
2874 +       default IP_NF_NAT if IP_NF_QUAKE3=y
2875 +       default m if IP_NF_QUAKE3=m
2876 +
2877 +config IP_NF_QUAKE3
2878 +       tristate "Quake3 protocol support"
2879 +       depends on IP_NF_CONNTRACK
2880 +       help
2881 +         Quake III Arena  connection tracking helper. This module allows for a
2882 +         stricter firewall rulebase if one only allows traffic to a master
2883 +         server. Connections to Quake III server IP addresses and ports returned
2884 +         by the master server will be tracked automatically.
2885 +       
2886 +         If you want to compile it as a module, say M here and read
2887 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
2888 +
2889 +config IP_NF_MATCH_POLICY
2890 +       tristate "IPsec policy match support"
2891 +       depends on IP_NF_IPTABLES && XFRM
2892 +       help
2893 +         Policy matching allows you to match packets based on the
2894 +         IPsec policy that was used during decapsulation/will
2895 +         be used during encapsulation.
2896 +
2897 +         To compile it as a module, choose M here.  If unsure, say N.
2898 +
2899 +config IP_NF_RSH
2900 +       tristate  'RSH protocol support'
2901 +       depends on IP_NF_CONNTRACK
2902 +       help
2903 +         The RSH connection tracker is required if the dynamic
2904 +         stderr "Server to Client" connection is to occur during a
2905 +         normal RSH session.  This typically operates as follows;
2906 +       
2907 +           Client 0:1023 --> Server 514    (stream 1 - stdin/stdout)
2908 +           Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
2909 +       
2910 +         This connection tracker will identify new RSH sessions,
2911 +         extract the outbound session details, and notify netfilter
2912 +         of pending "related" sessions.
2913 +       
2914 +         Warning: This module could be dangerous. It is not "best
2915 +                  practice" to use RSH, use SSH in all instances.
2916 +                  (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
2917 +       
2918 +       
2919 +         If you want to compile it as a module, say M here and read
2920 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
2921 +
2922 +config IP_NF_NAT_RTSP
2923 +       tristate
2924 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2925 +       default IP_NF_NAT if IP_NF_RTSP=y
2926 +       default m if IP_NF_RTSP=m
2927 +
2928 +config IP_NF_RTSP
2929 +       tristate  ' RTSP protocol support'
2930 +       depends on IP_NF_CONNTRACK
2931 +       help
2932 +         Support the RTSP protocol.  This allows UDP transports to be setup
2933 +         properly, including RTP and RDT.
2934 +       
2935 +         If you want to compile it as a module, say 'M' here and read
2936 +         Documentation/modules.txt.  If unsure, say 'Y'.
2937 +
2938 +config IP_NF_CT_PROTO_SCTP
2939 +       tristate  'SCTP protocol connection tracking support'
2940 +       depends on IP_NF_CONNTRACK
2941 +
2942 +config IP_NF_MATCH_STRING
2943 +       tristate  'String match support'
2944 +       depends on IP_NF_IPTABLES
2945 +       help
2946 +         String matching alows you to match packets which contain a
2947 +         specified string of characters.
2948 +       
2949 +         If you want to compile it as a module, say M here and read
2950 +         Documentation/modules.txt.  If unsure, say `N'.
2951 +
2952 +config IP_NF_NAT_TALK
2953 +       tristate
2954 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2955 +       default IP_NF_NAT if IP_NF_TALK=y
2956 +       default m if IP_NF_TALK=m
2957 +
2958 +config IP_NF_TALK
2959 +       tristate  'talk protocol support'
2960 +       depends on IP_NF_CONNTRACK
2961 +       help
2962 +         The talk protocols (both otalk/talk - or talk/ntalk, to confuse
2963 +         you by the different namings about which is old or which is new :-)
2964 +         use an additional channel to setup the talk session and a separated
2965 +         data channel for the actual conversation (like in FTP). Both the 
2966 +         initiating and the setup channels are over UDP, while the data channel 
2967 +         is over TCP, on a random port. The conntrack part of this extension
2968 +         will enable you to let in/out talk sessions easily by matching these
2969 +         connections as RELATED by the state match, while the NAT part helps
2970 +         you to let talk sessions trough a NAT machine.
2971 +       
2972 +         If you want to compile it as a module, say 'M' here and read
2973 +         Documentation/modules.txt.  If unsure, say 'N'.
2974 +
2975  endmenu
2976  
2977 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Makefile linux-2.6.7/net/ipv4/netfilter/Makefile
2978 --- linux-2.6.7.org/net/ipv4/netfilter/Makefile 2004-06-25 10:47:45.000000000 +0200
2979 +++ linux-2.6.7/net/ipv4/netfilter/Makefile     2004-06-25 12:28:43.706897576 +0200
2980 @@ -19,10 +19,49 @@
2981  # connection tracking
2982  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
2983  
2984 +# talk protocol support
2985 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
2986 +ifdef CONFIG_IP_NF_TALK
2987 +       export-objs += ip_conntrack_talk.o
2988 +endif
2989 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
2990 +
2991 +
2992 +# SCTP protocol connection tracking
2993 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
2994
2995 +# H.323 support
2996 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
2997 +ifdef CONFIG_IP_NF_H323
2998 +       export-objs += ip_conntrack_h323.o
2999 +endif
3000 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
3001 +
3002 +
3003  # connection tracking helpers
3004 +
3005 +# rtsp protocol support
3006 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
3007 +ifdef CONFIG_IP_NF_NAT_RTSP
3008 +       export-objs += ip_conntrack_rtsp.o
3009 +endif
3010 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
3011 +
3012 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
3013 +ifdef CONFIG_IP_NF_NAT_QUAKE3
3014 +       export-objs += ip_conntrack_quake3.o
3015 +endif
3016 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
3017 +ifdef CONFIG_IP_NF_MMS
3018 +       export-objs += ip_conntrack_mms.o
3019 +endif
3020  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
3021  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
3022  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
3023 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
3024 +
3025 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
3026 +
3027  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
3028  
3029  # NAT helpers 
3030 @@ -30,6 +69,8 @@
3031  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
3032  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
3033  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
3034 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
3035 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
3036  
3037  # generic IP tables 
3038  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
3039 @@ -43,14 +84,39 @@
3040  # matches
3041  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
3042  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
3043 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
3044 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
3045 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
3046  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
3047 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
3048  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
3049  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
3050  
3051  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
3052  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
3053 +
3054 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
3055 +
3056  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
3057  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
3058 +obj-$(CONFIG_IP_NF_MATCH_ACCOUNT) += ipt_account.o
3059 +
3060 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
3061 +
3062 +
3063 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
3064 +
3065 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
3066 +
3067 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
3068 +
3069 +
3070 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
3071 +
3072 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
3073 +
3074 +
3075 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
3076  
3077  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
3078  
3079 @@ -60,30 +126,46 @@
3080  
3081  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
3082  
3083 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
3084 +
3085 +
3086 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
3087 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
3088  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
3089  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
3090 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
3091  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
3092  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
3093  obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
3094  obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
3095  
3096  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
3097 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
3098  
3099  # targets
3100  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
3101 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
3102  obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
3103  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
3104  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
3105  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
3106 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
3107  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
3108  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
3109 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
3110  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
3111  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
3112  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
3113  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
3114  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
3115 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
3116 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
3117 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
3118 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
3119 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
3120  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
3121  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
3122 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
3123  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
3124  
3125  # generic ARP tables
3126 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c
3127 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c      2004-06-25 10:47:45.000000000 +0200
3128 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c  2004-06-25 12:21:25.558506256 +0200
3129 @@ -68,6 +68,7 @@
3130  static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
3131  struct list_head *ip_conntrack_hash;
3132  static kmem_cache_t *ip_conntrack_cachep;
3133 +static kmem_cache_t *ip_conntrack_expect_cachep;
3134  struct ip_conntrack ip_conntrack_untracked;
3135  
3136  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
3137 @@ -127,11 +128,11 @@
3138  }
3139  
3140  int
3141 -get_tuple(const struct iphdr *iph,
3142 -         const struct sk_buff *skb,
3143 -         unsigned int dataoff,
3144 -         struct ip_conntrack_tuple *tuple,
3145 -         const struct ip_conntrack_protocol *protocol)
3146 +ip_ct_get_tuple(const struct iphdr *iph,
3147 +               const struct sk_buff *skb,
3148 +               unsigned int dataoff,
3149 +               struct ip_conntrack_tuple *tuple,
3150 +               const struct ip_conntrack_protocol *protocol)
3151  {
3152         /* Never happen */
3153         if (iph->frag_off & htons(IP_OFFSET)) {
3154 @@ -147,10 +148,10 @@
3155         return protocol->pkt_to_tuple(skb, dataoff, tuple);
3156  }
3157  
3158 -static int
3159 -invert_tuple(struct ip_conntrack_tuple *inverse,
3160 -            const struct ip_conntrack_tuple *orig,
3161 -            const struct ip_conntrack_protocol *protocol)
3162 +int
3163 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
3164 +                  const struct ip_conntrack_tuple *orig,
3165 +                  const struct ip_conntrack_protocol *protocol)
3166  {
3167         inverse->src.ip = orig->dst.ip;
3168         inverse->dst.ip = orig->src.ip;
3169 @@ -177,7 +178,7 @@
3170         IP_NF_ASSERT(atomic_read(&exp->use) == 0);
3171         IP_NF_ASSERT(!timer_pending(&exp->timeout));
3172  
3173 -       kfree(exp);
3174 +       kmem_cache_free(ip_conntrack_expect_cachep, exp);
3175  }
3176  
3177  inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
3178 @@ -336,7 +337,7 @@
3179                         list_del(&ct->master->expected_list);
3180                         master = ct->master->expectant;
3181                 }
3182 -               kfree(ct->master);
3183 +               kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
3184         }
3185         WRITE_UNLOCK(&ip_conntrack_lock);
3186  
3187 @@ -496,83 +497,6 @@
3188         return h != NULL;
3189  }
3190  
3191 -/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
3192 -struct ip_conntrack *
3193 -icmp_error_track(struct sk_buff *skb,
3194 -                enum ip_conntrack_info *ctinfo,
3195 -                unsigned int hooknum)
3196 -{
3197 -       struct ip_conntrack_tuple innertuple, origtuple;
3198 -       struct {
3199 -               struct icmphdr icmp;
3200 -               struct iphdr ip;
3201 -       } inside;
3202 -       struct ip_conntrack_protocol *innerproto;
3203 -       struct ip_conntrack_tuple_hash *h;
3204 -       int dataoff;
3205 -
3206 -       IP_NF_ASSERT(skb->nfct == NULL);
3207 -
3208 -       /* Not enough header? */
3209 -       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
3210 -               return NULL;
3211 -
3212 -       if (inside.icmp.type != ICMP_DEST_UNREACH
3213 -           && inside.icmp.type != ICMP_SOURCE_QUENCH
3214 -           && inside.icmp.type != ICMP_TIME_EXCEEDED
3215 -           && inside.icmp.type != ICMP_PARAMETERPROB
3216 -           && inside.icmp.type != ICMP_REDIRECT)
3217 -               return NULL;
3218 -
3219 -       /* Ignore ICMP's containing fragments (shouldn't happen) */
3220 -       if (inside.ip.frag_off & htons(IP_OFFSET)) {
3221 -               DEBUGP("icmp_error_track: fragment of proto %u\n",
3222 -                      inside.ip.protocol);
3223 -               return NULL;
3224 -       }
3225 -
3226 -       innerproto = ip_ct_find_proto(inside.ip.protocol);
3227 -       dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
3228 -       /* Are they talking about one of our connections? */
3229 -       if (!get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
3230 -               DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
3231 -               return NULL;
3232 -       }
3233 -
3234 -       /* Ordinarily, we'd expect the inverted tupleproto, but it's
3235 -          been preserved inside the ICMP. */
3236 -       if (!invert_tuple(&innertuple, &origtuple, innerproto)) {
3237 -               DEBUGP("icmp_error_track: Can't invert tuple\n");
3238 -               return NULL;
3239 -       }
3240 -
3241 -       *ctinfo = IP_CT_RELATED;
3242 -
3243 -       h = ip_conntrack_find_get(&innertuple, NULL);
3244 -       if (!h) {
3245 -               /* Locally generated ICMPs will match inverted if they
3246 -                  haven't been SNAT'ed yet */
3247 -               /* FIXME: NAT code has to handle half-done double NAT --RR */
3248 -               if (hooknum == NF_IP_LOCAL_OUT)
3249 -                       h = ip_conntrack_find_get(&origtuple, NULL);
3250 -
3251 -               if (!h) {
3252 -                       DEBUGP("icmp_error_track: no match\n");
3253 -                       return NULL;
3254 -               }
3255 -               /* Reverse direction from that found */
3256 -               if (DIRECTION(h) != IP_CT_DIR_REPLY)
3257 -                       *ctinfo += IP_CT_IS_REPLY;
3258 -       } else {
3259 -               if (DIRECTION(h) == IP_CT_DIR_REPLY)
3260 -                       *ctinfo += IP_CT_IS_REPLY;
3261 -       }
3262 -
3263 -       /* Update skb to refer to this connection */
3264 -       skb->nfct = &h->ctrack->infos[*ctinfo];
3265 -       return h->ctrack;
3266 -}
3267 -
3268  /* There's a small race here where we may free a just-assured
3269     connection.  Too bad: we're in trouble anyway. */
3270  static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
3271 @@ -654,7 +578,7 @@
3272                 }
3273         }
3274  
3275 -       if (!invert_tuple(&repl_tuple, tuple, protocol)) {
3276 +       if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
3277                 DEBUGP("Can't invert tuple.\n");
3278                 return NULL;
3279         }
3280 @@ -693,41 +617,51 @@
3281                              struct ip_conntrack_expect *, tuple);
3282         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
3283  
3284 -       /* If master is not in hash table yet (ie. packet hasn't left
3285 -          this machine yet), how can other end know about expected?
3286 -          Hence these are not the droids you are looking for (if
3287 -          master ct never got confirmed, we'd hold a reference to it
3288 -          and weird things would happen to future packets). */
3289 -       if (expected && !is_confirmed(expected->expectant))
3290 -               expected = NULL;
3291 -
3292 -       /* Look up the conntrack helper for master connections only */
3293 -       if (!expected)
3294 -               conntrack->helper = ip_ct_find_helper(&repl_tuple);
3295 +       if (expected) {
3296 +               /* If master is not in hash table yet (ie. packet hasn't left
3297 +                  this machine yet), how can other end know about expected?
3298 +                  Hence these are not the droids you are looking for (if
3299 +                  master ct never got confirmed, we'd hold a reference to it
3300 +                  and weird things would happen to future packets). */
3301 +               if (!is_confirmed(expected->expectant)) {
3302 +                       conntrack->helper = ip_ct_find_helper(&repl_tuple);
3303 +                       goto end;
3304 +               }
3305  
3306 -       /* If the expectation is dying, then this is a loser. */
3307 -       if (expected
3308 -           && expected->expectant->helper->timeout
3309 -           && ! del_timer(&expected->timeout))
3310 -               expected = NULL;
3311 +               /* Expectation is dying... */
3312 +               if (expected->expectant->helper->timeout
3313 +                   && !del_timer(&expected->timeout))
3314 +                       goto end;       
3315  
3316 -       if (expected) {
3317                 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3318                         conntrack, expected);
3319                 /* Welcome, Mr. Bond.  We've been expecting you... */
3320 +               IP_NF_ASSERT(master_ct(conntrack));
3321                 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3322                 conntrack->master = expected;
3323                 expected->sibling = conntrack;
3324 +#if CONFIG_IP_NF_CONNTRACK_MARK
3325 +               conntrack->mark = expected->expectant->mark;
3326 +#endif
3327                 LIST_DELETE(&ip_conntrack_expect_list, expected);
3328                 expected->expectant->expecting--;
3329                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3330 -       }
3331 -       atomic_inc(&ip_conntrack_count);
3332 +
3333 +               /* this is a braindead... --pablo */
3334 +               atomic_inc(&ip_conntrack_count);
3335 +               WRITE_UNLOCK(&ip_conntrack_lock);
3336 +
3337 +               if (expected->expectfn)
3338 +                       expected->expectfn(conntrack);
3339 +
3340 +               goto ret;
3341 +       } else 
3342 +               conntrack->helper = ip_ct_find_helper(&repl_tuple);
3343 +
3344 +end:   atomic_inc(&ip_conntrack_count);
3345         WRITE_UNLOCK(&ip_conntrack_lock);
3346  
3347 -       if (expected && expected->expectfn)
3348 -               expected->expectfn(conntrack);
3349 -       return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3350 +ret:   return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3351  }
3352  
3353  /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3354 @@ -743,7 +677,8 @@
3355  
3356         IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
3357  
3358 -       if (!get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, &tuple, proto))
3359 +       if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, 
3360 +                               &tuple,proto))
3361                 return NULL;
3362  
3363         /* look for tuple match */
3364 @@ -828,10 +763,12 @@
3365  
3366         proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
3367  
3368 -       /* It may be an icmp error... */
3369 -       if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 
3370 -           && icmp_error_track(*pskb, &ctinfo, hooknum))
3371 -               return NF_ACCEPT;
3372 +       /* It may be an special packet, error, unclean...
3373 +        * inverse of the return code tells to the netfilter
3374 +        * core what to do with the packet. */
3375 +       if (proto->error != NULL 
3376 +           && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0)
3377 +               return -ret;
3378  
3379         if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
3380                 /* Not valid part of a connection */
3381 @@ -869,7 +806,8 @@
3382  int invert_tuplepr(struct ip_conntrack_tuple *inverse,
3383                    const struct ip_conntrack_tuple *orig)
3384  {
3385 -       return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
3386 +       return ip_ct_invert_tuple(inverse, orig, 
3387 +                                 ip_ct_find_proto(orig->dst.protonum));
3388  }
3389  
3390  static inline int resent_expect(const struct ip_conntrack_expect *i,
3391 @@ -923,9 +861,8 @@
3392  ip_conntrack_expect_alloc(void)
3393  {
3394         struct ip_conntrack_expect *new;
3395 -       
3396 -       new = (struct ip_conntrack_expect *)
3397 -               kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
3398 +
3399 +       new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
3400         if (!new) {
3401                 DEBUGP("expect_related: OOM allocating expect\n");
3402                 return NULL;
3403 @@ -933,6 +870,7 @@
3404  
3405         /* tuple_cmp compares whole union, we have to initialized cleanly */
3406         memset(new, 0, sizeof(struct ip_conntrack_expect));
3407 +       atomic_set(&new->use, 1);
3408  
3409         return new;
3410  }
3411 @@ -944,7 +882,6 @@
3412         DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
3413         new->expectant = related_to;
3414         new->sibling = NULL;
3415 -       atomic_set(&new->use, 1);
3416  
3417         /* add to expected list for this connection */
3418         list_add_tail(&new->expected_list, &related_to->sibling_list);
3419 @@ -997,7 +934,8 @@
3420                 }
3421  
3422                 WRITE_UNLOCK(&ip_conntrack_lock);
3423 -               kfree(expect);
3424 +               /* This expectation is not inserted so no need to lock */
3425 +               kmem_cache_free(ip_conntrack_expect_cachep, expect);
3426                 return -EEXIST;
3427  
3428         } else if (related_to->helper->max_expected && 
3429 @@ -1015,7 +953,7 @@
3430                                        related_to->helper->name,
3431                                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
3432                                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3433 -                       kfree(expect);
3434 +                       kmem_cache_free(ip_conntrack_expect_cachep, expect);
3435                         return -EPERM;
3436                 }
3437                 DEBUGP("ip_conntrack: max number of expected "
3438 @@ -1049,7 +987,7 @@
3439                 WRITE_UNLOCK(&ip_conntrack_lock);
3440                 DEBUGP("expect_related: busy!\n");
3441  
3442 -               kfree(expect);
3443 +               kmem_cache_free(ip_conntrack_expect_cachep, expect);
3444                 return -EBUSY;
3445         }
3446  
3447 @@ -1368,6 +1306,7 @@
3448         }
3449  
3450         kmem_cache_destroy(ip_conntrack_cachep);
3451 +       kmem_cache_destroy(ip_conntrack_expect_cachep);
3452         vfree(ip_conntrack_hash);
3453         nf_unregister_sockopt(&so_getorigdst);
3454  }
3455 @@ -1420,6 +1359,15 @@
3456                 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
3457                 goto err_free_hash;
3458         }
3459 +
3460 +       ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
3461 +                                       sizeof(struct ip_conntrack_expect),
3462 +                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
3463 +       if (!ip_conntrack_expect_cachep) {
3464 +               printk(KERN_ERR "Unable to create ip_expect slab cache\n");
3465 +               goto err_free_conntrack_slab;
3466 +       }
3467 +
3468         /* Don't NEED lock here, but good form anyway. */
3469         WRITE_LOCK(&ip_conntrack_lock);
3470         /* Sew in builtin protocols. */
3471 @@ -1447,6 +1395,8 @@
3472  
3473         return ret;
3474  
3475 +err_free_conntrack_slab:
3476 +       kmem_cache_destroy(ip_conntrack_cachep);
3477  err_free_hash:
3478         vfree(ip_conntrack_hash);
3479  err_unreg_sockopt:
3480 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_egg.c
3481 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_egg.c       1970-01-01 01:00:00.000000000 +0100
3482 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_egg.c   2004-06-25 12:21:33.570288280 +0200
3483 @@ -0,0 +1,237 @@
3484 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3485 + * based on ip_conntrack_irc.c 
3486 + *
3487 + *      This module only supports the share userfile-send command,
3488 + *      used by eggdrops to share it's userfile.
3489 + *
3490 + *      There are no support for NAT at the moment.
3491 + *
3492 + *      This program is free software; you can redistribute it and/or
3493 + *      modify it under the terms of the GNU General Public License
3494 + *      as published by the Free Software Foundation; either version
3495 + *      2 of the License, or (at your option) any later version.
3496 + *
3497 + *     Module load syntax:
3498 + *     
3499 + *     please give the ports of all Eggdrops You have running
3500 + *      on your system, the default port is 3333.
3501 + *
3502 + *      2001-04-19: Security update. IP addresses are now compared
3503 + *                  to prevent unauthorized "related" access.
3504 + *
3505 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
3506 + *                 Port to netfilter 'newnat' API.
3507 + */
3508 +
3509 +#include <linux/module.h>
3510 +#include <linux/netfilter.h>
3511 +#include <linux/ip.h>
3512 +#include <net/checksum.h>
3513 +#include <net/tcp.h>
3514 +
3515 +#include <linux/netfilter_ipv4/lockhelp.h>
3516 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3517 +
3518 +#define MAX_PORTS 8
3519 +static int ports[MAX_PORTS];
3520 +static int ports_c = 0;
3521 +static unsigned int egg_timeout = 300;
3522 +
3523 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3524 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3525 +MODULE_LICENSE("GPL");
3526 +#ifdef MODULE_PARM
3527 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3528 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3529 +#endif
3530 +
3531 +DECLARE_LOCK(ip_egg_lock);
3532 +struct module *ip_conntrack_egg = THIS_MODULE;
3533 +
3534 +#if 0
3535 +#define DEBUGP printk
3536 +#else
3537 +#define DEBUGP(format, args...)
3538 +#endif
3539 +
3540 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3541 +/* tries to get the ip_addr and port out of a eggdrop command
3542 +   return value: -1 on failure, 0 on success 
3543 +   data                pointer to first byte of DCC command data
3544 +   data_end    pointer to last byte of dcc command data
3545 +   ip          returns parsed ip of dcc command
3546 +   port                returns parsed port of dcc command */
3547 +{
3548 +       if (data > data_end)
3549 +               return -1;
3550 +       
3551 +       *ip = simple_strtoul(data, &data, 10);
3552 +
3553 +       /* skip blanks between ip and port */
3554 +       while (*data == ' ' && data < data_end)
3555 +               data++;
3556 +
3557 +       *port = simple_strtoul(data, &data, 10);
3558 +       return 0;
3559 +}
3560 +
3561 +
3562 +static int help(const struct iphdr *iph, size_t len,
3563 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3564 +{
3565 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3566 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3567 +       char *data = (char *) tcph + tcph->doff * 4;
3568 +       char *data_limit;
3569 +       u_int32_t tcplen = len - iph->ihl * 4;
3570 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3571 +       int dir = CTINFO2DIR(ctinfo);
3572 +       int bytes_scanned = 0;
3573 +       struct ip_conntrack_expect exp;
3574 +
3575 +       u_int32_t egg_ip;
3576 +       u_int16_t egg_port;
3577 +
3578 +       DEBUGP("entered\n");
3579 +
3580 +       /* If packet is coming from IRC server */
3581 +       if (dir != IP_CT_DIR_REPLY)
3582 +               return NF_ACCEPT;
3583 +
3584 +       /* Until there's been traffic both ways, don't look in packets. */
3585 +       if (ctinfo != IP_CT_ESTABLISHED
3586 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3587 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
3588 +               return NF_ACCEPT;
3589 +       }
3590 +
3591 +       /* Not whole TCP header? */
3592 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3593 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3594 +               return NF_ACCEPT;
3595 +       }
3596 +
3597 +       /* Checksum invalid?  Ignore. */
3598 +       /* FIXME: Source route IP option packets --RR */
3599 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3600 +                        csum_partial((char *) tcph, tcplen, 0))) {
3601 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3602 +                       tcph, tcplen, NIPQUAD(iph->saddr),
3603 +                       NIPQUAD(iph->daddr));
3604 +               return NF_ACCEPT;
3605 +       }
3606 +
3607 +       data_limit = (char *) data + datalen;
3608 +       while (datalen > 5 && bytes_scanned < 128) {
3609 +               if (memcmp(data, "s us ", 5)) {
3610 +                       data++;
3611 +                       datalen--;
3612 +                       bytes_scanned++;
3613 +                       continue;
3614 +               }
3615 +
3616 +               data += 5;
3617 +
3618 +               DEBUGP("Userfile-share found in connection "
3619 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3620 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3621 +
3622 +               if (parse_command((char *) data, data_limit, &egg_ip,
3623 +                                 &egg_port)) {
3624 +                       DEBUGP("no data in userfile-share pkt\n");
3625 +                       return NF_ACCEPT;
3626 +               }
3627 +
3628 +               memset(&exp, 0, sizeof(exp));
3629 +
3630 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3631 +                       if (net_ratelimit())
3632 +                               printk("Forged Eggdrop command from "
3633 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3634 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3635 +                                      HIPQUAD(egg_ip), egg_port);
3636 +                       return NF_ACCEPT;
3637 +               }
3638 +
3639 +               exp.tuple.src.ip = iph->daddr;
3640 +               exp.tuple.src.u.tcp.port = 0;
3641 +               exp.tuple.dst.ip = htonl(egg_ip);
3642 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
3643 +               exp.tuple.dst.protonum = IPPROTO_TCP;
3644 +
3645 +               exp.mask.dst.u.tcp.port = 0xffff;
3646 +               exp.mask.dst.protonum = 0xffff;
3647 +
3648 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3649 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3650 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3651 +
3652 +               ip_conntrack_expect_related(&exp, ct);
3653 +               break;
3654 +       }
3655 +       return NF_ACCEPT;
3656 +}
3657 +
3658 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3659 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3660 +
3661 +static void deregister_helpers(void) {
3662 +       int i;
3663 +       
3664 +       for (i = 0; i < ports_c; i++) {
3665 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
3666 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
3667 +       }
3668 +}
3669 +
3670 +static int __init init(void)
3671 +{
3672 +       int i, ret;
3673 +       char *tmpname;
3674 +
3675 +       /* If no port given, default to standard eggdrop port */
3676 +       if (ports[0] == 0)
3677 +               ports[0] = 3333;
3678 +
3679 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3680 +               memset(&egg_helpers[i], 0,
3681 +                      sizeof(struct ip_conntrack_helper));
3682 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3683 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3684 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3685 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
3686 +               egg_helpers[i].max_expected = 1;
3687 +               egg_helpers[i].timeout = egg_timeout;
3688 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3689 +               egg_helpers[i].me = THIS_MODULE;
3690 +               egg_helpers[i].help = help;
3691 +
3692 +               tmpname = &egg_names[i][0];
3693 +               if (ports[i] == 3333)
3694 +                       sprintf(tmpname, "eggdrop");
3695 +               else
3696 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
3697 +               egg_helpers[i].name = tmpname;
3698 +
3699 +               DEBUGP("port #%d: %d\n", i, ports[i]);
3700 +
3701 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
3702 +
3703 +               if (ret) {
3704 +                       printk("ip_conntrack_egg: ERROR registering helper "
3705 +                               "for port %d\n", ports[i]);
3706 +                       deregister_helpers();
3707 +                       return 1;
3708 +               }
3709 +               ports_c++;
3710 +       }
3711 +       return 0;
3712 +}
3713 +
3714 +static void __exit fini(void)
3715 +{
3716 +       deregister_helpers();
3717 +}
3718 +
3719 +module_init(init);
3720 +module_exit(fini);
3721 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_h323.c
3722 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_h323.c      1970-01-01 01:00:00.000000000 +0100
3723 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_h323.c  2004-06-25 12:21:34.916083688 +0200
3724 @@ -0,0 +1,308 @@
3725 +/* 
3726 + * H.323 'brute force' extension for H.323 connection tracking. 
3727 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3728 + *
3729 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3730 + * (http://www.coritel.it/projects/sofia/nat/)
3731 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3732 + * the unregistered helpers to the conntrack entries.
3733 + */
3734 +
3735 +
3736 +#include <linux/module.h>
3737 +#include <linux/netfilter.h>
3738 +#include <linux/ip.h>
3739 +#include <net/checksum.h>
3740 +#include <net/tcp.h>
3741 +
3742 +#include <linux/netfilter_ipv4/lockhelp.h>
3743 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3744 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3745 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3746 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3747 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3748 +
3749 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3750 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3751 +MODULE_LICENSE("GPL");
3752 +
3753 +DECLARE_LOCK(ip_h323_lock);
3754 +struct module *ip_conntrack_h323 = THIS_MODULE;
3755 +
3756 +#if 0
3757 +#define DEBUGP printk
3758 +#else
3759 +#define DEBUGP(format, args...)
3760 +#endif
3761 +
3762 +/* FIXME: This should be in userspace.  Later. */
3763 +static int h245_help(const struct iphdr *iph, size_t len,
3764 +                    struct ip_conntrack *ct,
3765 +                    enum ip_conntrack_info ctinfo)
3766 +{
3767 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3768 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3769 +       unsigned char *data_limit;
3770 +       u_int32_t tcplen = len - iph->ihl * 4;
3771 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3772 +       int dir = CTINFO2DIR(ctinfo);
3773 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3774 +       struct ip_conntrack_expect expect, *exp = &expect;
3775 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3776 +       u_int16_t data_port;
3777 +       u_int32_t data_ip;
3778 +       unsigned int i;
3779 +
3780 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3781 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3782 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3783 +
3784 +       /* Can't track connections formed before we registered */
3785 +       if (!info)
3786 +               return NF_ACCEPT;
3787 +               
3788 +       /* Until there's been traffic both ways, don't look in packets. */
3789 +       if (ctinfo != IP_CT_ESTABLISHED
3790 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3791 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3792 +               return NF_ACCEPT;
3793 +       }
3794 +
3795 +       /* Not whole TCP header or too short packet? */
3796 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3797 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3798 +               return NF_ACCEPT;
3799 +       }
3800 +
3801 +       /* Checksum invalid?  Ignore. */
3802 +       /* FIXME: Source route IP option packets --RR */
3803 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3804 +                             csum_partial((char *)tcph, tcplen, 0))) {
3805 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3806 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3807 +                      NIPQUAD(iph->daddr));
3808 +               return NF_ACCEPT;
3809 +       }
3810 +
3811 +       data_limit = (unsigned char *) data + datalen;
3812 +       /* bytes: 0123   45
3813 +                 ipadrr port */
3814 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3815 +               data_ip = *((u_int32_t *)data);
3816 +               if (data_ip == iph->saddr) {
3817 +                       data_port = *((u_int16_t *)(data + 4));
3818 +                       memset(&expect, 0, sizeof(expect));
3819 +                       /* update the H.225 info */
3820 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3821 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3822 +                               NIPQUAD(iph->saddr), ntohs(data_port));
3823 +                       LOCK_BH(&ip_h323_lock);
3824 +                       info->is_h225 = H225_PORT + 1;
3825 +                       exp_info->port = data_port;
3826 +                       exp_info->dir = dir;
3827 +                       exp_info->offset = i;
3828 +
3829 +                       exp->seq = ntohl(tcph->seq) + i;
3830 +                   
3831 +                       exp->tuple = ((struct ip_conntrack_tuple)
3832 +                               { { ct->tuplehash[!dir].tuple.src.ip,
3833 +                                   { 0 } },
3834 +                                 { data_ip,
3835 +                                   { .tcp = { data_port } },
3836 +                                   IPPROTO_UDP }});
3837 +                       exp->mask = ((struct ip_conntrack_tuple)
3838 +                               { { 0xFFFFFFFF, { 0 } },
3839 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3840 +       
3841 +                       exp->expectfn = NULL;
3842 +                       
3843 +                       /* Ignore failure; should only happen with NAT */
3844 +                       ip_conntrack_expect_related(exp, ct);
3845 +
3846 +                       UNLOCK_BH(&ip_h323_lock);
3847 +               }
3848 +       }
3849 +
3850 +       return NF_ACCEPT;
3851 +
3852 +}
3853 +
3854 +/* H.245 helper is not registered! */
3855 +static struct ip_conntrack_helper h245 = 
3856 +       { { NULL, NULL },
3857 +          "H.245",                             /* name */
3858 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
3859 +          NULL,                                        /* module */
3860 +          8,                                   /* max_ expected */
3861 +          240,                                 /* timeout */
3862 +          { { 0, { 0 } },                      /* tuple */
3863 +            { 0, { 0 }, IPPROTO_TCP } },
3864 +          { { 0, { 0xFFFF } },                 /* mask */
3865 +            { 0, { 0 }, 0xFFFF } },
3866 +          h245_help                            /* helper */
3867 +       };
3868 +
3869 +static int h225_expect(struct ip_conntrack *ct)
3870 +{
3871 +       WRITE_LOCK(&ip_conntrack_lock);
3872 +       ct->helper = &h245;
3873 +       DEBUGP("h225_expect: helper for %p added\n", ct);
3874 +       WRITE_UNLOCK(&ip_conntrack_lock);
3875 +       
3876 +       return NF_ACCEPT;       /* unused */
3877 +}
3878 +
3879 +/* FIXME: This should be in userspace.  Later. */
3880 +static int h225_help(const struct iphdr *iph, size_t len,
3881 +                    struct ip_conntrack *ct,
3882 +                    enum ip_conntrack_info ctinfo)
3883 +{
3884 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3885 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3886 +       unsigned char *data_limit;
3887 +       u_int32_t tcplen = len - iph->ihl * 4;
3888 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3889 +       int dir = CTINFO2DIR(ctinfo);
3890 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3891 +       struct ip_conntrack_expect expect, *exp = &expect;
3892 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3893 +       u_int16_t data_port;
3894 +       u_int32_t data_ip;
3895 +       unsigned int i;
3896 +       
3897 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3898 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3899 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3900 +
3901 +       /* Can't track connections formed before we registered */
3902 +       if (!info)
3903 +               return NF_ACCEPT;
3904 +
3905 +       /* Until there's been traffic both ways, don't look in packets. */
3906 +       if (ctinfo != IP_CT_ESTABLISHED
3907 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3908 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3909 +               return NF_ACCEPT;
3910 +       }
3911 +
3912 +       /* Not whole TCP header or too short packet? */
3913 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3914 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3915 +               return NF_ACCEPT;
3916 +       }
3917 +
3918 +       /* Checksum invalid?  Ignore. */
3919 +       /* FIXME: Source route IP option packets --RR */
3920 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3921 +                             csum_partial((char *)tcph, tcplen, 0))) {
3922 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3923 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3924 +                      NIPQUAD(iph->daddr));
3925 +               return NF_ACCEPT;
3926 +       }
3927 +       
3928 +       data_limit = (unsigned char *) data + datalen;
3929 +       /* bytes: 0123   45
3930 +                 ipadrr port */
3931 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3932 +               data_ip = *((u_int32_t *)data);
3933 +               if (data_ip == iph->saddr) {
3934 +                       data_port = *((u_int16_t *)(data + 4));
3935 +                       if (data_port == tcph->source) {
3936 +                               /* Signal address */
3937 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3938 +                                       NIPQUAD(iph->saddr));
3939 +                               /* Update the H.225 info so that NAT can mangle the address/port
3940 +                                  even when we have no expected connection! */
3941 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3942 +                               LOCK_BH(&ip_h323_lock);
3943 +                               info->dir = dir;
3944 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3945 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
3946 +                               UNLOCK_BH(&ip_h323_lock);
3947 +#endif
3948 +                       } else {
3949 +                               memset(&expect, 0, sizeof(expect));
3950 +
3951 +                               /* update the H.225 info */
3952 +                               LOCK_BH(&ip_h323_lock);
3953 +                               info->is_h225 = H225_PORT;
3954 +                               exp_info->port = data_port;
3955 +                               exp_info->dir = dir;
3956 +                               exp_info->offset = i;
3957 +
3958 +                               exp->seq = ntohl(tcph->seq) + i;
3959 +
3960 +                               exp->tuple = ((struct ip_conntrack_tuple)
3961 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
3962 +                                           { 0 } },
3963 +                                         { data_ip,
3964 +                                           { .tcp = { data_port } },
3965 +                                           IPPROTO_TCP }});
3966 +                               exp->mask = ((struct ip_conntrack_tuple)
3967 +                                       { { 0xFFFFFFFF, { 0 } },
3968 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3969 +       
3970 +                               exp->expectfn = h225_expect;
3971 +                               
3972 +                               /* Ignore failure */
3973 +                               ip_conntrack_expect_related(exp, ct);
3974 +
3975 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3976 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3977 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
3978 +
3979 +                               UNLOCK_BH(&ip_h323_lock);
3980 +                       }  
3981 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3982 +               } else if (data_ip == iph->daddr) {
3983 +                       data_port = *((u_int16_t *)(data + 4));
3984 +                       if (data_port == tcph->dest) {
3985 +                               /* Signal address */
3986 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3987 +                                       NIPQUAD(iph->daddr));
3988 +                               /* Update the H.225 info so that NAT can mangle the address/port
3989 +                                  even when we have no expected connection! */
3990 +                               LOCK_BH(&ip_h323_lock);
3991 +                               info->dir = dir;
3992 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3993 +                               info->offset[IP_CT_DIR_REPLY] = i;
3994 +                               UNLOCK_BH(&ip_h323_lock);
3995 +                       }
3996 +#endif
3997 +               }
3998 +       }
3999 +
4000 +       return NF_ACCEPT;
4001 +
4002 +}
4003 +
4004 +static struct ip_conntrack_helper h225 = 
4005 +       { { NULL, NULL },
4006 +         "H.225",                                      /* name */
4007 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
4008 +         THIS_MODULE,                                  /* module */
4009 +         2,                                            /* max_expected */
4010 +         240,                                          /* timeout */
4011 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
4012 +           { 0, { 0 }, IPPROTO_TCP } },
4013 +         { { 0, { 0xFFFF } },                          /* mask */
4014 +           { 0, { 0 }, 0xFFFF } },
4015 +         h225_help                                     /* helper */
4016 +       };
4017 +
4018 +static int __init init(void)
4019 +{
4020 +       return ip_conntrack_helper_register(&h225);
4021 +}
4022 +
4023 +static void __exit fini(void)
4024 +{
4025 +       /* Unregister H.225 helper */   
4026 +       ip_conntrack_helper_unregister(&h225);
4027 +}
4028 +
4029 +EXPORT_SYMBOL(ip_h323_lock);
4030 +
4031 +module_init(init);
4032 +module_exit(fini);
4033 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_mms.c
4034 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_mms.c       1970-01-01 01:00:00.000000000 +0100
4035 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_mms.c   2004-06-25 12:23:10.835501720 +0200
4036 @@ -0,0 +1,308 @@
4037 +/* MMS extension for IP connection tracking
4038 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4039 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
4040 + *
4041 + * ip_conntrack_mms.c v0.3 2002-09-22
4042 + *
4043 + *      This program is free software; you can redistribute it and/or
4044 + *      modify it under the terms of the GNU General Public License
4045 + *      as published by the Free Software Foundation; either version
4046 + *      2 of the License, or (at your option) any later version.
4047 + *
4048 + *      Module load syntax:
4049 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
4050 + *
4051 + *      Please give the ports of all MMS servers You wish to connect to.
4052 + *      If you don't specify ports, the default will be TCP port 1755.
4053 + *
4054 + *      More info on MMS protocol, firewalls and NAT:
4055 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
4056 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
4057 + *
4058 + *      The SDP project people are reverse-engineering MMS:
4059 + *      http://get.to/sdp
4060 + */
4061 +
4062 +#include <linux/config.h>
4063 +#include <linux/module.h>
4064 +#include <linux/netfilter.h>
4065 +#include <linux/ip.h>
4066 +#include <linux/ctype.h>
4067 +#include <net/checksum.h>
4068 +#include <net/tcp.h>
4069 +
4070 +#include <linux/netfilter_ipv4/lockhelp.h>
4071 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4072 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
4073 +
4074 +DECLARE_LOCK(ip_mms_lock);
4075 +struct module *ip_conntrack_mms = THIS_MODULE;
4076 +
4077 +#define MAX_PORTS 8
4078 +static int ports[MAX_PORTS];
4079 +static int ports_c;
4080 +#ifdef MODULE_PARM
4081 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4082 +#endif
4083 +
4084 +#if 0 
4085 +#define DEBUGP printk
4086 +#else
4087 +#define DEBUGP(format, args...)
4088 +#endif
4089 +
4090 +EXPORT_SYMBOL(ip_mms_lock);
4091 +
4092 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4093 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
4094 +MODULE_LICENSE("GPL");
4095 +
4096 +/* #define isdigit(c) (c >= '0' && c <= '9') */
4097 +
4098 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
4099 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
4100 +{
4101 +       int i;
4102 +       for (i = 0; i < unicode_size; ++i) {
4103 +               string[i] = (char)(unicode[i]);
4104 +       }
4105 +       string[unicode_size] = 0x00;
4106 +}
4107 +
4108 +__inline static int atoi(char *s) 
4109 +{
4110 +       int i=0;
4111 +       while (isdigit(*s)) {
4112 +               i = i*10 + *(s++) - '0';
4113 +       }
4114 +       return i;
4115 +}
4116 +
4117 +/* convert ip address string like "192.168.0.10" to unsigned int */
4118 +__inline static u_int32_t asciiiptoi(char *s)
4119 +{
4120 +       unsigned int i, j, k;
4121 +
4122 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
4123 +               i+=atoi(s);
4124 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
4125 +                       ;
4126 +       }
4127 +       i+=atoi(s);
4128 +       return ntohl(i);
4129 +}
4130 +
4131 +int parse_mms(const char *data, 
4132 +             const unsigned int datalen,
4133 +             u_int32_t *mms_ip,
4134 +             u_int16_t *mms_proto,
4135 +             u_int16_t *mms_port,
4136 +             char **mms_string_b,
4137 +             char **mms_string_e,
4138 +             char **mms_padding_e)
4139 +{
4140 +       int unicode_size, i;
4141 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
4142 +       char getlengthstring[28];
4143 +       
4144 +       for(unicode_size=0; 
4145 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
4146 +           unicode_size++)
4147 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
4148 +                       return -1; /* out of bounds - incomplete packet */
4149 +       
4150 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
4151 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
4152 +       
4153 +       /* IP address ? */
4154 +       *mms_ip = asciiiptoi(tempstring+2);
4155 +       
4156 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
4157 +               
4158 +       /* protocol ? */
4159 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
4160 +               *mms_proto = IPPROTO_TCP;
4161 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
4162 +               *mms_proto = IPPROTO_UDP;
4163 +
4164 +       /* port ? */
4165 +       *mms_port = atoi(tempstring+7+i);
4166 +
4167 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
4168 +          unicode string, one to the end of the string, and one to the end 
4169 +          of the packet, since we must keep track of the number of bytes 
4170 +          between end of the unicode string and the end of packet (padding) */
4171 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
4172 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
4173 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
4174 +       return 0;
4175 +}
4176 +
4177 +
4178 +/* FIXME: This should be in userspace.  Later. */
4179 +static int help(const struct iphdr *iph, size_t len,
4180 +               struct ip_conntrack *ct,
4181 +               enum ip_conntrack_info ctinfo)
4182 +{
4183 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
4184 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4185 +       const char *data = (const char *)tcph + tcph->doff * 4;
4186 +       unsigned int tcplen = len - iph->ihl * 4;
4187 +       unsigned int datalen = tcplen - tcph->doff * 4;
4188 +       int dir = CTINFO2DIR(ctinfo);
4189 +       struct ip_conntrack_expect expect, *exp = &expect; 
4190 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
4191 +       
4192 +       u_int32_t mms_ip;
4193 +       u_int16_t mms_proto;
4194 +       char mms_proto_string[8];
4195 +       u_int16_t mms_port;
4196 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
4197 +            
4198 +       /* Until there's been traffic both ways, don't look in packets. */
4199 +       if (ctinfo != IP_CT_ESTABLISHED
4200 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4201 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
4202 +               return NF_ACCEPT;
4203 +       }
4204 +
4205 +       /* Not whole TCP header? */
4206 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
4207 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
4208 +               return NF_ACCEPT;
4209 +       }
4210 +
4211 +       /* Checksum invalid?  Ignore. */
4212 +       /* FIXME: Source route IP option packets --RR */
4213 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4214 +           csum_partial((char *)tcph, tcplen, 0))) {
4215 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4216 +                      tcph, tcplen, NIPQUAD(iph->saddr),
4217 +                      NIPQUAD(iph->daddr));
4218 +               return NF_ACCEPT;
4219 +       }
4220 +       
4221 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
4222 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
4223 +          the client has already sent a packet to the server with the server's hostname 
4224 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
4225 +          server will break the connection if this doesn't correspond to its own host 
4226 +          header. The client can also connect to an IP address; if it's the server's IP
4227 +          address, it will not break the connection. When doing DNAT on a connection 
4228 +          where the client uses a server's IP address, the nat module should detect
4229 +          this and change this string accordingly to the DNATed address. This should
4230 +          probably be done by checking for an IP address, then storing it as a member
4231 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
4232 +          */
4233 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
4234 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
4235 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
4236 +                      (u8)*(data+36), (u8)*(data+37), 
4237 +                      (u8)*(data+38), (u8)*(data+39),
4238 +                      datalen);
4239 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
4240 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
4241 +                       if(net_ratelimit())
4242 +                               /* FIXME: more verbose debugging ? */
4243 +                               printk(KERN_WARNING
4244 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
4245 +
4246 +               memset(&expect, 0, sizeof(expect));
4247 +
4248 +               sprintf(mms_proto_string, "(%u)", mms_proto);
4249 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
4250 +                      mms_proto == IPPROTO_TCP ? "TCP"
4251 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
4252 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4253 +                      NIPQUAD(mms_ip),
4254 +                      mms_port);
4255 +               
4256 +               /* it's possible that the client will just ask the server to tunnel
4257 +                  the stream over the same TCP session (from port 1755): there's 
4258 +                  shouldn't be a need to add an expectation in that case, but it
4259 +                  makes NAT packet mangling so much easier */
4260 +               LOCK_BH(&ip_mms_lock);
4261 +
4262 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
4263 +               
4264 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
4265 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
4266 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
4267 +               exp_mms_info->port    = mms_port;
4268 +               
4269 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
4270 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
4271 +               
4272 +               exp->tuple = ((struct ip_conntrack_tuple)
4273 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4274 +                             { mms_ip,
4275 +                               { .tcp = { (__u16) ntohs(mms_port) } },
4276 +                               mms_proto } }
4277 +                            );
4278 +               exp->mask  = ((struct ip_conntrack_tuple)
4279 +                            { { 0xFFFFFFFF, { 0 } },
4280 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4281 +               exp->expectfn = NULL;
4282 +               ip_conntrack_expect_related(&expect, ct);
4283 +               UNLOCK_BH(&ip_mms_lock);
4284 +       }
4285 +
4286 +       return NF_ACCEPT;
4287 +}
4288 +
4289 +static struct ip_conntrack_helper mms[MAX_PORTS];
4290 +static char mms_names[MAX_PORTS][10];
4291 +
4292 +/* Not __exit: called from init() */
4293 +static void fini(void)
4294 +{
4295 +       int i;
4296 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4297 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
4298 +                               ports[i]);
4299 +               ip_conntrack_helper_unregister(&mms[i]);
4300 +       }
4301 +}
4302 +
4303 +static int __init init(void)
4304 +{
4305 +       int i, ret;
4306 +       char *tmpname;
4307 +
4308 +       if (ports[0] == 0)
4309 +               ports[0] = MMS_PORT;
4310 +
4311 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4312 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
4313 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
4314 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
4315 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
4316 +               mms[i].mask.dst.protonum = 0xFFFF;
4317 +               mms[i].max_expected = 1;
4318 +               mms[i].timeout = 0;
4319 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4320 +               mms[i].me = THIS_MODULE;
4321 +               mms[i].help = help;
4322 +
4323 +               tmpname = &mms_names[i][0];
4324 +               if (ports[i] == MMS_PORT)
4325 +                       sprintf(tmpname, "mms");
4326 +               else
4327 +                       sprintf(tmpname, "mms-%d", ports[i]);
4328 +               mms[i].name = tmpname;
4329 +
4330 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
4331 +                               ports[i]);
4332 +               ret = ip_conntrack_helper_register(&mms[i]);
4333 +
4334 +               if (ret) {
4335 +                       fini();
4336 +                       return ret;
4337 +               }
4338 +               ports_c++;
4339 +       }
4340 +       return 0;
4341 +}
4342 +
4343 +module_init(init);
4344 +module_exit(fini);
4345 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c
4346 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c     2004-06-16 07:19:13.000000000 +0200
4347 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-06-25 12:21:02.322038736 +0200
4348 @@ -62,8 +62,14 @@
4349         return 1;
4350  }
4351  
4352 -struct ip_conntrack_protocol ip_conntrack_generic_protocol
4353 -= { { NULL, NULL }, 0, "unknown",
4354 -    generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
4355 -    generic_print_conntrack, packet, new, NULL, NULL, NULL };
4356 -
4357 +struct ip_conntrack_protocol ip_conntrack_generic_protocol =
4358 +{
4359 +       .proto                  = 0,
4360 +       .name                   = "unknown",
4361 +       .pkt_to_tuple           = generic_pkt_to_tuple,
4362 +       .invert_tuple           = generic_invert_tuple,
4363 +       .print_tuple            = generic_print_tuple,
4364 +       .print_conntrack        = generic_print_conntrack,
4365 +       .packet                 = packet,
4366 +       .new                    = new,
4367 +};
4368 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
4369 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c        2004-06-16 07:18:52.000000000 +0200
4370 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c    2004-06-25 12:21:02.370031440 +0200
4371 @@ -12,6 +12,11 @@
4372  #include <linux/netfilter.h>
4373  #include <linux/in.h>
4374  #include <linux/icmp.h>
4375 +#include <net/ip.h>
4376 +#include <net/checksum.h>
4377 +#include <linux/netfilter.h>
4378 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4379 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4380  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4381  
4382  unsigned long ip_ct_icmp_timeout = 30*HZ;
4383 @@ -122,7 +127,147 @@
4384         return 1;
4385  }
4386  
4387 -struct ip_conntrack_protocol ip_conntrack_protocol_icmp
4388 -= { { NULL, NULL }, IPPROTO_ICMP, "icmp",
4389 -    icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
4390 -    icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
4391 +static int
4392 +icmp_error_message(struct sk_buff *skb,
4393 +                  enum ip_conntrack_info *ctinfo,
4394 +                  unsigned int hooknum)
4395 +{
4396 +       struct ip_conntrack_tuple innertuple, origtuple;
4397 +       struct {
4398 +               struct icmphdr icmp;
4399 +               struct iphdr ip;
4400 +       } inside;
4401 +       struct ip_conntrack_protocol *innerproto;
4402 +       struct ip_conntrack_tuple_hash *h;
4403 +       int dataoff;
4404 +
4405 +       IP_NF_ASSERT(skb->nfct == NULL);
4406 +
4407 +       /* Not enough header? */
4408 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
4409 +               return NF_ACCEPT;
4410 +
4411 +       /* Ignore ICMP's containing fragments (shouldn't happen) */
4412 +       if (inside.ip.frag_off & htons(IP_OFFSET)) {
4413 +               DEBUGP("icmp_error_track: fragment of proto %u\n",
4414 +                      inside.ip.protocol);
4415 +               return NF_ACCEPT;
4416 +       }
4417 +
4418 +       innerproto = ip_ct_find_proto(inside.ip.protocol);
4419 +       dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
4420 +       /* Are they talking about one of our connections? */
4421 +       if (!ip_ct_get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
4422 +               DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
4423 +               return NF_ACCEPT;
4424 +       }
4425 +
4426 +       /* Ordinarily, we'd expect the inverted tupleproto, but it's
4427 +          been preserved inside the ICMP. */
4428 +       if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
4429 +               DEBUGP("icmp_error_track: Can't invert tuple\n");
4430 +               return NF_ACCEPT;
4431 +       }
4432 +
4433 +       *ctinfo = IP_CT_RELATED;
4434 +
4435 +       h = ip_conntrack_find_get(&innertuple, NULL);
4436 +       if (!h) {
4437 +               /* Locally generated ICMPs will match inverted if they
4438 +                  haven't been SNAT'ed yet */
4439 +               /* FIXME: NAT code has to handle half-done double NAT --RR */
4440 +               if (hooknum == NF_IP_LOCAL_OUT)
4441 +                       h = ip_conntrack_find_get(&origtuple, NULL);
4442 +
4443 +               if (!h) {
4444 +                       DEBUGP("icmp_error_track: no match\n");
4445 +                       return NF_ACCEPT;
4446 +               }
4447 +               /* Reverse direction from that found */
4448 +               if (DIRECTION(h) != IP_CT_DIR_REPLY)
4449 +                       *ctinfo += IP_CT_IS_REPLY;
4450 +       } else {
4451 +               if (DIRECTION(h) == IP_CT_DIR_REPLY)
4452 +                       *ctinfo += IP_CT_IS_REPLY;
4453 +       }
4454 +
4455 +       /* Update skb to refer to this connection */
4456 +       skb->nfct = &h->ctrack->infos[*ctinfo];
4457 +       return -NF_ACCEPT;
4458 +}
4459 +
4460 +/* Small and modified version of icmp_rcv */
4461 +static int
4462 +icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
4463 +          unsigned int hooknum)
4464 +{
4465 +       struct icmphdr icmph;
4466 +
4467 +       /* Not enough header? */
4468 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph))!=0) {
4469 +               if (LOG_INVALID(IPPROTO_ICMP))
4470 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL,
4471 +                                     "ip_ct_icmp: short packet ");
4472 +               return -NF_ACCEPT;
4473 +       }
4474 +
4475 +       /* See ip_conntrack_proto_tcp.c */
4476 +       if (hooknum != NF_IP_PRE_ROUTING)
4477 +               goto checksum_skipped;
4478 +
4479 +       switch (skb->ip_summed) {
4480 +       case CHECKSUM_HW:
4481 +               if (!(u16)csum_fold(skb->csum)) 
4482 +                       break;
4483 +               if (LOG_INVALID(IPPROTO_ICMP))
4484 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
4485 +                                     "ip_ct_icmp: bad HW ICMP checksum ");
4486 +               return -NF_ACCEPT;
4487 +       case CHECKSUM_NONE:
4488 +               if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
4489 +                       if (LOG_INVALID(IPPROTO_ICMP))
4490 +                               nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
4491 +                                             "ip_ct_icmp: bad ICMP checksum ");
4492 +                       return -NF_ACCEPT;
4493 +               }
4494 +       default:
4495 +               break;
4496 +       }
4497 +
4498 +checksum_skipped:
4499 +       /*
4500 +        *      18 is the highest 'known' ICMP type. Anything else is a mystery
4501 +        *
4502 +        *      RFC 1122: 3.2.2  Unknown ICMP messages types MUST be silently
4503 +        *                discarded.
4504 +        */
4505 +       if (icmph.type > NR_ICMP_TYPES) {
4506 +               if (LOG_INVALID(IPPROTO_ICMP))
4507 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL,
4508 +                                     "ip_ct_icmp: invalid ICMP type ");
4509 +               return -NF_ACCEPT;
4510 +       }
4511 +
4512 +       /* Need to track icmp error message? */
4513 +       if (icmph.type != ICMP_DEST_UNREACH
4514 +           && icmph.type != ICMP_SOURCE_QUENCH
4515 +           && icmph.type != ICMP_TIME_EXCEEDED
4516 +           && icmph.type != ICMP_PARAMETERPROB
4517 +           && icmph.type != ICMP_REDIRECT)
4518 +               return NF_ACCEPT;
4519 +
4520 +       return icmp_error_message(skb, ctinfo, hooknum);
4521 +}
4522 +
4523 +struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
4524 +{
4525 +       .proto                  = IPPROTO_ICMP,
4526 +       .name                   = "icmp",
4527 +       .pkt_to_tuple           = icmp_pkt_to_tuple,
4528 +       .invert_tuple           = icmp_invert_tuple,
4529 +       .print_tuple            = icmp_print_tuple,
4530 +       .print_conntrack        = icmp_print_conntrack,
4531 +       .packet                 = icmp_packet,
4532 +       .new                    = icmp_new,
4533 +       .error                  = icmp_error,
4534 +};
4535 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
4536 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c        1970-01-01 01:00:00.000000000 +0100
4537 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_sctp.c    2004-06-25 12:24:51.924133912 +0200
4538 @@ -0,0 +1,529 @@
4539 +/*
4540 + * Connection tracking protocol helper module for SCTP.
4541 + * 
4542 + * SCTP is defined in RFC 2960. References to various sections in this code 
4543 + * are to this RFC.
4544 + * 
4545 + * This program is free software; you can redistribute it and/or modify
4546 + * it under the terms of the GNU General Public License version 2 as
4547 + * published by the Free Software Foundation.
4548 + */
4549 +
4550 +#include <linux/types.h>
4551 +#include <linux/sched.h>
4552 +#include <linux/timer.h>
4553 +#include <linux/netfilter.h>
4554 +#include <linux/module.h>
4555 +#include <linux/in.h>
4556 +#include <linux/ip.h>
4557 +#include <linux/sctp.h>
4558 +#include <linux/string.h>
4559 +
4560 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4561 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4562 +#include <linux/netfilter_ipv4/lockhelp.h>
4563 +
4564 +#if 0
4565 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4566 +#else
4567 +#define DEBUGP(format, args...)
4568 +#endif
4569 +
4570 +/* Protects conntrack->proto.sctp */
4571 +static DECLARE_RWLOCK(sctp_lock);
4572 +
4573 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4574 +   closely.  They're more complex. --RR 
4575 +
4576 +   And so for me for SCTP :D -Kiran */
4577 +
4578 +static const char *sctp_conntrack_names[] = {
4579 +       "NONE",
4580 +       "CLOSED",
4581 +       "COOKIE_WAIT",
4582 +       "COOKIE_ECHOED",
4583 +       "ESTABLISHED",
4584 +       "SHUTDOWN_SENT",
4585 +       "SHUTDOWN_RECD",
4586 +       "SHUTDOWN_ACK_SENT",
4587 +};
4588 +
4589 +#define SECS  * HZ
4590 +#define MINS  * 60 SECS
4591 +#define HOURS * 60 MINS
4592 +#define DAYS  * 24 HOURS
4593 +
4594 +unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
4595 +unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
4596 +unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
4597 +unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
4598 +unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
4599 +unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
4600 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
4601 +
4602 +static unsigned long * sctp_timeouts[]
4603 += { 0,                                     /* SCTP_CONNTRACK_NONE  */
4604 +    &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
4605 +    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
4606 +    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
4607 +    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
4608 +    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4609 +    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4610 +    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4611 + };
4612 +
4613 +#define sNO SCTP_CONNTRACK_NONE
4614 +#define        sCL SCTP_CONNTRACK_CLOSED
4615 +#define        sCW SCTP_CONNTRACK_COOKIE_WAIT
4616 +#define        sCE SCTP_CONNTRACK_COOKIE_ECHOED
4617 +#define        sES SCTP_CONNTRACK_ESTABLISHED
4618 +#define        sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4619 +#define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4620 +#define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4621 +#define        sIV SCTP_CONNTRACK_MAX
4622 +
4623 +/* 
4624 +       These are the descriptions of the states:
4625 +
4626 +NOTE: These state names are tantalizingly similar to the states of an 
4627 +SCTP endpoint. But the interpretation of the states is a little different,
4628 +considering that these are the states of the connection and not of an end 
4629 +point. Please note the subtleties. -Kiran
4630 +
4631 +NONE              - Nothing so far.
4632 +COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
4633 +                    an INIT_ACK chunk in the reply direction.
4634 +COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
4635 +ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
4636 +SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
4637 +SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
4638 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4639 +                    to that of the SHUTDOWN chunk.
4640 +CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
4641 +                    the SHUTDOWN chunk. Connection is closed.
4642 +*/
4643 +
4644 +/* TODO
4645 + - I have assumed that the first INIT is in the original direction. 
4646 + This messes things when an INIT comes in the reply direction in CLOSED
4647 + state.
4648 + - Check the error type in the reply dir before transitioning from 
4649 +cookie echoed to closed.
4650 + - Sec 5.2.4 of RFC 2960
4651 + - Multi Homing support.
4652 +*/
4653 +
4654 +/* SCTP conntrack state transitions */
4655 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4656 +       {
4657 +/*     ORIGINAL        */
4658 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4659 +/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4660 +/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4661 +/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4662 +/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4663 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4664 +/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4665 +/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4666 +/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4667 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4668 +       },
4669 +       {
4670 +/*     REPLY   */
4671 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4672 +/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4673 +/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4674 +/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4675 +/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4676 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4677 +/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4678 +/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4679 +/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4680 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4681 +       }
4682 +};
4683 +
4684 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4685 +                            unsigned int dataoff,
4686 +                            struct ip_conntrack_tuple *tuple)
4687 +{
4688 +       sctp_sctphdr_t hdr;
4689 +
4690 +       DEBUGP(__FUNCTION__);
4691 +       DEBUGP("\n");
4692 +
4693 +       /* Actually only need first 8 bytes. */
4694 +       if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4695 +               return 0;
4696 +
4697 +       tuple->src.u.sctp.port = hdr.source;
4698 +       tuple->dst.u.sctp.port = hdr.dest;
4699 +
4700 +       return 1;
4701 +}
4702 +
4703 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4704 +                            const struct ip_conntrack_tuple *orig)
4705 +{
4706 +       DEBUGP(__FUNCTION__);
4707 +       DEBUGP("\n");
4708 +
4709 +       tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4710 +       tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4711 +       return 1;
4712 +}
4713 +
4714 +/* Print out the per-protocol part of the tuple. */
4715 +static unsigned int sctp_print_tuple(char *buffer,
4716 +                                    const struct ip_conntrack_tuple *tuple)
4717 +{
4718 +       DEBUGP(__FUNCTION__);
4719 +       DEBUGP("\n");
4720 +
4721 +       return sprintf(buffer, "sport=%hu dport=%hu ",
4722 +                      ntohs(tuple->src.u.sctp.port),
4723 +                      ntohs(tuple->dst.u.sctp.port));
4724 +}
4725 +
4726 +/* Print out the private part of the conntrack. */
4727 +static unsigned int sctp_print_conntrack(char *buffer,
4728 +                                        const struct ip_conntrack *conntrack)
4729 +{
4730 +       enum sctp_conntrack state;
4731 +
4732 +       DEBUGP(__FUNCTION__);
4733 +       DEBUGP("\n");
4734 +
4735 +       READ_LOCK(&sctp_lock);
4736 +       state = conntrack->proto.sctp.state;
4737 +       READ_UNLOCK(&sctp_lock);
4738 +
4739 +       return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4740 +}
4741 +
4742 +#define for_each_sctp_chunk(skb, sch, offset, count)   \
4743 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0;       \
4744 +       offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch));    \
4745 +       offset += (htons(sch.length) + 3) & ~3, count++)
4746 +
4747 +/* Some validity checks to make sure the chunks are fine */
4748 +static int do_basic_checks(struct ip_conntrack *conntrack,
4749 +                          const struct sk_buff *skb,
4750 +                          char *map)
4751 +{
4752 +       u_int32_t offset, count;
4753 +       sctp_chunkhdr_t sch;
4754 +       int flag;
4755 +
4756 +       DEBUGP(__FUNCTION__);
4757 +       DEBUGP("\n");
4758 +
4759 +       flag = 0;
4760 +
4761 +       for_each_sctp_chunk (skb, sch, offset, count) {
4762 +               DEBUGP("Chunk Num: %d  Type: %d\n", count, sch.type);
4763 +
4764 +               if (sch.type == SCTP_CID_INIT 
4765 +                       || sch.type == SCTP_CID_INIT_ACK
4766 +                       || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4767 +                       flag = 1;
4768 +               }
4769 +
4770 +               /* Cookie Ack/Echo chunks not the first OR 
4771 +                  Init / Init Ack / Shutdown compl chunks not the only chunks */
4772 +               if ((sch.type == SCTP_CID_COOKIE_ACK 
4773 +                       || sch.type == SCTP_CID_COOKIE_ECHO
4774 +                       || flag)
4775 +                    && count !=0 ) {
4776 +                       DEBUGP("Basic checks failed\n");
4777 +                       return 1;
4778 +               }
4779 +
4780 +               if (map) {
4781 +                       set_bit (sch.type, (void *)map);
4782 +               }
4783 +       }
4784 +
4785 +       DEBUGP("Basic checks passed\n");
4786 +       return 0;
4787 +}
4788 +
4789 +static int new_state(enum ip_conntrack_dir dir,
4790 +                    enum sctp_conntrack cur_state,
4791 +                    int chunk_type)
4792 +{
4793 +       int i;
4794 +
4795 +       DEBUGP(__FUNCTION__);
4796 +       DEBUGP("\n");
4797 +
4798 +       DEBUGP("Chunk type: %d\n", chunk_type);
4799 +
4800 +       switch (chunk_type) {
4801 +               case SCTP_CID_INIT: 
4802 +                       DEBUGP("SCTP_CID_INIT\n");
4803 +                       i = 0; break;
4804 +               case SCTP_CID_INIT_ACK: 
4805 +                       DEBUGP("SCTP_CID_INIT_ACK\n");
4806 +                       i = 1; break;
4807 +               case SCTP_CID_ABORT: 
4808 +                       DEBUGP("SCTP_CID_ABORT\n");
4809 +                       i = 2; break;
4810 +               case SCTP_CID_SHUTDOWN: 
4811 +                       DEBUGP("SCTP_CID_SHUTDOWN\n");
4812 +                       i = 3; break;
4813 +               case SCTP_CID_SHUTDOWN_ACK: 
4814 +                       DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4815 +                       i = 4; break;
4816 +               case SCTP_CID_ERROR: 
4817 +                       DEBUGP("SCTP_CID_ERROR\n");
4818 +                       i = 5; break;
4819 +               case SCTP_CID_COOKIE_ECHO: 
4820 +                       DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4821 +                       i = 6; break;
4822 +               case SCTP_CID_COOKIE_ACK: 
4823 +                       DEBUGP("SCTP_CID_COOKIE_ACK\n");
4824 +                       i = 7; break;
4825 +               case SCTP_CID_SHUTDOWN_COMPLETE: 
4826 +                       DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4827 +                       i = 8; break;
4828 +               default:
4829 +                       /* Other chunks like DATA, SACK, HEARTBEAT and
4830 +                       its ACK do not cause a change in state */
4831 +                       DEBUGP("Unknown chunk type, Will stay in %s\n", 
4832 +                                               sctp_conntrack_names[cur_state]);
4833 +                       return cur_state;
4834 +       }
4835 +
4836 +       DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
4837 +                       dir, sctp_conntrack_names[cur_state], chunk_type,
4838 +                       sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4839 +
4840 +       return sctp_conntracks[dir][i][cur_state];
4841 +}
4842 +
4843 +/* Returns verdict for packet, or -1 for invalid. */
4844 +static int sctp_packet(struct ip_conntrack *conntrack,
4845 +                      const struct sk_buff *skb,
4846 +                      enum ip_conntrack_info ctinfo)
4847 +{
4848 +       enum sctp_conntrack newconntrack, oldsctpstate;
4849 +       sctp_sctphdr_t sctph;
4850 +       sctp_chunkhdr_t sch;
4851 +       u_int32_t offset, count;
4852 +       char map[256 / sizeof (char)] = {0};
4853 +
4854 +       DEBUGP(__FUNCTION__);
4855 +       DEBUGP("\n");
4856 +
4857 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4858 +               return -1;
4859 +
4860 +       if (do_basic_checks(conntrack, skb, map) != 0)
4861 +               return -1;
4862 +
4863 +       /* Check the verification tag (Sec 8.5) */
4864 +       if (!test_bit(SCTP_CID_INIT, (void *)map)
4865 +               && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4866 +               && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4867 +               && !test_bit(SCTP_CID_ABORT, (void *)map)
4868 +               && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4869 +               && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4870 +               DEBUGP("Verification tag check failed\n");
4871 +               return -1;
4872 +       }
4873 +
4874 +       oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4875 +       for_each_sctp_chunk (skb, sch, offset, count) {
4876 +               WRITE_LOCK(&sctp_lock);
4877 +
4878 +               /* Special cases of Verification tag check (Sec 8.5.1) */
4879 +               if (sch.type == SCTP_CID_INIT) {
4880 +                       /* Sec 8.5.1 (A) */
4881 +                       if (sctph.vtag != 0) {
4882 +                               WRITE_UNLOCK(&sctp_lock);
4883 +                               return -1;
4884 +                       }
4885 +               } else if (sch.type == SCTP_CID_ABORT) {
4886 +                       /* Sec 8.5.1 (B) */
4887 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4888 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4889 +                                                       [1 - CTINFO2DIR(ctinfo)])) {
4890 +                               WRITE_UNLOCK(&sctp_lock);
4891 +                               return -1;
4892 +                       }
4893 +               } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4894 +                       /* Sec 8.5.1 (C) */
4895 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4896 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4897 +                                                       [1 - CTINFO2DIR(ctinfo)] 
4898 +                                       && (sch.flags & 1))) {
4899 +                               WRITE_UNLOCK(&sctp_lock);
4900 +                               return -1;
4901 +                       }
4902 +               } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4903 +                       /* Sec 8.5.1 (D) */
4904 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4905 +                               WRITE_UNLOCK(&sctp_lock);
4906 +                               return -1;
4907 +                       }
4908 +               }
4909 +
4910 +               oldsctpstate = conntrack->proto.sctp.state;
4911 +               newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4912 +
4913 +               /* Invalid */
4914 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4915 +                       DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4916 +                              CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4917 +                       WRITE_UNLOCK(&sctp_lock);
4918 +                       return -1;
4919 +               }
4920 +
4921 +               /* If it is an INIT or an INIT ACK note down the vtag */
4922 +               if (sch.type == SCTP_CID_INIT 
4923 +                       || sch.type == SCTP_CID_INIT_ACK) {
4924 +                       sctp_inithdr_t inithdr;
4925 +
4926 +                       if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4927 +                               &inithdr, sizeof(inithdr)) != 0) {
4928 +                                       WRITE_UNLOCK(&sctp_lock);
4929 +                                       return -1;
4930 +                       }
4931 +                       DEBUGP("Setting vtag %x for dir %d\n", 
4932 +                                       inithdr.init_tag, CTINFO2DIR(ctinfo));
4933 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4934 +               }
4935 +
4936 +               conntrack->proto.sctp.state = newconntrack;
4937 +               WRITE_UNLOCK(&sctp_lock);
4938 +       }
4939 +
4940 +       ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4941 +
4942 +       if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4943 +               && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4944 +               && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4945 +               DEBUGP("Setting assured bit\n");
4946 +               set_bit(IPS_ASSURED_BIT, &conntrack->status);
4947 +       }
4948 +
4949 +       return NF_ACCEPT;
4950 +}
4951 +
4952 +/* Called when a new connection for this protocol found. */
4953 +static int sctp_new(struct ip_conntrack *conntrack, 
4954 +                   const struct sk_buff *skb)
4955 +{
4956 +       enum sctp_conntrack newconntrack;
4957 +       sctp_sctphdr_t sctph;
4958 +       sctp_chunkhdr_t sch;
4959 +       u_int32_t offset, count;
4960 +       char map[256 / sizeof (char)] = {0};
4961 +
4962 +       DEBUGP(__FUNCTION__);
4963 +       DEBUGP("\n");
4964 +
4965 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4966 +               return -1;
4967 +
4968 +       if (do_basic_checks(conntrack, skb, map) != 0)
4969 +               return -1;
4970 +
4971 +       /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4972 +       if ((test_bit (SCTP_CID_ABORT, (void *)map))
4973 +               || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4974 +               || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4975 +               return -1;
4976 +       }
4977 +
4978 +       newconntrack = SCTP_CONNTRACK_MAX;
4979 +       for_each_sctp_chunk (skb, sch, offset, count) {
4980 +               /* Don't need lock here: this conntrack not in circulation yet */
4981 +               newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
4982 +                                               SCTP_CONNTRACK_NONE, sch.type);
4983 +
4984 +               /* Invalid: delete conntrack */
4985 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4986 +                       DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4987 +                       return 0;
4988 +               }
4989 +
4990 +               /* Copy the vtag into the state info */
4991 +               if (sch.type == SCTP_CID_INIT) {
4992 +                       if (sctph.vtag == 0) {
4993 +                               sctp_inithdr_t inithdr;
4994 +
4995 +                               if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t), 
4996 +                                       &inithdr, sizeof(inithdr)) != 0) {
4997 +                                               return -1;
4998 +                               }
4999 +
5000 +                               DEBUGP("Setting vtag %x for new conn\n", 
5001 +                                       inithdr.init_tag);
5002 +
5003 +                               conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
5004 +                                                               inithdr.init_tag;
5005 +                       } else {
5006 +                               /* Sec 8.5.1 (A) */
5007 +                               return -1;
5008 +                       }
5009 +               }
5010 +               /* If it is a shutdown ack OOTB packet, we expect a return
5011 +                  shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
5012 +               else {
5013 +                       DEBUGP("Setting vtag %x for new conn OOTB\n", 
5014 +                               sctph.vtag);
5015 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
5016 +               }
5017 +
5018 +               conntrack->proto.sctp.state = newconntrack;
5019 +       }
5020 +
5021 +       return 1;
5022 +}
5023 +
5024 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
5025 +                               const struct sk_buff *skb)
5026 +{
5027 +       /* To be implemented */
5028 +       return 0;
5029 +}
5030 +
5031 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
5032 +       .list            = { NULL, NULL }, 
5033 +       .proto           = IPPROTO_SCTP, 
5034 +       .name            = "sctp",
5035 +       .pkt_to_tuple    = sctp_pkt_to_tuple, 
5036 +       .invert_tuple    = sctp_invert_tuple, 
5037 +       .print_tuple     = sctp_print_tuple, 
5038 +       .print_conntrack = sctp_print_conntrack,
5039 +       .packet          = sctp_packet, 
5040 +       .new             = sctp_new, 
5041 +       .destroy         = NULL, 
5042 +       .exp_matches_pkt = sctp_exp_matches_pkt, 
5043 +       .me              = THIS_MODULE 
5044 +};
5045 +
5046 +int __init init(void)
5047 +{
5048 +       int ret;
5049 +
5050 +       ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
5051 +       DEBUGP("SCTP conntrack module loading %s\n", 
5052 +                                       ret ? "failed": "succeeded");
5053 +       return ret;
5054 +}
5055 +
5056 +void __exit fini(void)
5057 +{
5058 +       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
5059 +       DEBUGP("SCTP conntrack module unloaded\n");
5060 +}
5061 +
5062 +module_init(init);
5063 +module_exit(fini);
5064 +
5065 +MODULE_LICENSE("GPL");
5066 +MODULE_AUTHOR("Kiran Kumar Immidi");
5067 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
5068 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
5069 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-06-16 07:20:25.000000000 +0200
5070 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c     2004-06-25 12:21:02.329037672 +0200
5071 @@ -268,7 +268,15 @@
5072         return between(exp->seq, ntohl(tcph.seq), ntohl(tcph.seq) + datalen);
5073  }
5074  
5075 -struct ip_conntrack_protocol ip_conntrack_protocol_tcp
5076 -= { { NULL, NULL }, IPPROTO_TCP, "tcp",
5077 -    tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
5078 -    tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
5079 +struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
5080 +{
5081 +       .proto                  = IPPROTO_TCP,
5082 +       .name                   = "tcp",
5083 +       .pkt_to_tuple           = tcp_pkt_to_tuple,
5084 +       .invert_tuple           = tcp_invert_tuple,
5085 +       .print_tuple            = tcp_print_tuple,
5086 +       .print_conntrack        = tcp_print_conntrack,
5087 +       .packet                 = tcp_packet,
5088 +       .new                    = tcp_new,
5089 +       .exp_matches_pkt        = tcp_exp_matches_pkt,
5090 +};
5091 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c
5092 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-06-16 07:18:37.000000000 +0200
5093 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c     2004-06-25 12:21:02.373030984 +0200
5094 @@ -12,6 +12,8 @@
5095  #include <linux/netfilter.h>
5096  #include <linux/in.h>
5097  #include <linux/udp.h>
5098 +#include <net/checksum.h>
5099 +#include <linux/netfilter.h>
5100  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
5101  
5102  unsigned long ip_ct_udp_timeout = 30*HZ;
5103 @@ -80,7 +82,60 @@
5104         return 1;
5105  }
5106  
5107 -struct ip_conntrack_protocol ip_conntrack_protocol_udp
5108 -= { { NULL, NULL }, IPPROTO_UDP, "udp",
5109 -    udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
5110 -    udp_packet, udp_new, NULL, NULL, NULL };
5111 +static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
5112 +                    unsigned int hooknum)
5113 +{
5114 +       struct iphdr *iph = skb->nh.iph;
5115 +       unsigned int udplen = skb->len - iph->ihl * 4;
5116 +       struct udphdr hdr;
5117 +
5118 +       /* Header is too small? */
5119 +       if (skb_copy_bits(skb, iph->ihl*4, &hdr, sizeof(hdr)) != 0) {
5120 +               if (LOG_INVALID(IPPROTO_UDP))
5121 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
5122 +                                 "ip_ct_udp: short packet ");
5123 +               return -NF_ACCEPT;
5124 +       }
5125 +       
5126 +       /* Truncated/malformed packets */
5127 +       if (ntohs(hdr.len) > udplen || ntohs(hdr.len) < sizeof(hdr)) {
5128 +               if (LOG_INVALID(IPPROTO_UDP))
5129 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
5130 +                                 "ip_ct_udp: truncated/malformed packet ");
5131 +               return -NF_ACCEPT;
5132 +       }
5133 +       
5134 +       /* Packet with no checksum */
5135 +       if (!hdr.check)
5136 +               return NF_ACCEPT;
5137 +
5138 +       /* Checksum invalid? Ignore.
5139 +        * We skip checking packets on the outgoing path
5140 +        * because the semantic of CHECKSUM_HW is different there 
5141 +        * and moreover root might send raw packets.
5142 +        * FIXME: Source route IP option packets --RR */
5143 +       if (hooknum == NF_IP_PRE_ROUTING
5144 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5145 +                                skb->ip_summed == CHECKSUM_HW ? skb->csum
5146 +                                : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
5147 +               if (LOG_INVALID(IPPROTO_UDP))
5148 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
5149 +                                 "ip_ct_udp: bad UDP checksum ");
5150 +               return -NF_ACCEPT;
5151 +       }
5152 +       
5153 +       return NF_ACCEPT;
5154 +}
5155 +
5156 +struct ip_conntrack_protocol ip_conntrack_protocol_udp =
5157 +{
5158 +       .proto                  = IPPROTO_UDP,
5159 +       .name                   = "udp",
5160 +       .pkt_to_tuple           = udp_pkt_to_tuple,
5161 +       .invert_tuple           = udp_invert_tuple,
5162 +       .print_tuple            = udp_print_tuple,
5163 +       .print_conntrack        = udp_print_conntrack,
5164 +       .packet                 = udp_packet,
5165 +       .new                    = udp_new,
5166 +       .error                  = udp_error,
5167 +};
5168 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_quake3.c
5169 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_quake3.c    1970-01-01 01:00:00.000000000 +0100
5170 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_quake3.c        2004-06-25 12:24:42.549559064 +0200
5171 @@ -0,0 +1,156 @@
5172 +/* Quake3 extension for IP connection tracking
5173 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5174 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5175 + *
5176 + * ip_conntrack_quake3.c v0.04 2002-08-31
5177 + *
5178 + *      This program is free software; you can redistribute it and/or
5179 + *      modify it under the terms of the GNU General Public License
5180 + *      as published by the Free Software Foundation; either version
5181 + *      2 of the License, or (at your option) any later version.
5182 + *
5183 + *      Module load syntax:
5184 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5185 + *
5186 + *      please give the ports of all Quake3 master servers You wish to 
5187 + *      connect to. If you don't specify ports, the default will be UDP 
5188 + *      port 27950.
5189 + *
5190 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5191 + */
5192 +
5193 +#include <linux/module.h>
5194 +#include <linux/ip.h>
5195 +#include <linux/udp.h>
5196 +
5197 +#include <linux/netfilter.h>
5198 +#include <linux/netfilter_ipv4/ip_tables.h>
5199 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5200 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5201 +
5202 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5203 +
5204 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5205 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5206 +MODULE_LICENSE("GPL");
5207 +
5208 +#define MAX_PORTS 8
5209 +static int ports[MAX_PORTS];
5210 +static int ports_c = 0;
5211 +#ifdef MODULE_PARM
5212 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5213 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5214 +#endif
5215 +
5216 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5217 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5218 +#if 0 
5219 +#define DEBUGP printk
5220 +#else
5221 +#define DEBUGP(format, args...)
5222 +#endif
5223 +
5224 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5225 +
5226 +static int quake3_help(const struct iphdr *iph, size_t len,
5227 +       struct ip_conntrack *ct,
5228 +       enum ip_conntrack_info ctinfo)
5229 +{
5230 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5231 +       int dir = CTINFO2DIR(ctinfo);
5232 +       struct ip_conntrack_expect exp;
5233 +       int i;
5234 +       
5235 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5236 +       if (ctinfo != IP_CT_ESTABLISHED
5237 +           && ctinfo != IP_CT_IS_REPLY) {
5238 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5239 +               return NF_ACCEPT;
5240 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5241 +       
5242 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5243 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5244 +                   i+6 < ntohs(udph->len);
5245 +                   i+=7) {
5246 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5247 +                              i, ntohs(udph->len),
5248 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
5249 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5250 +
5251 +                       memset(&exp, 0, sizeof(exp));
5252 +
5253 +                       exp.tuple = ((struct ip_conntrack_tuple)
5254 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5255 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
5256 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
5257 +                                        IPPROTO_UDP } }
5258 +                                   );
5259 +                       exp.mask  = ((struct ip_conntrack_tuple)
5260 +                                    { { 0xFFFFFFFF, { 0 } },
5261 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5262 +                       exp.expectfn = NULL;
5263 +
5264 +                       ip_conntrack_expect_related(&exp, ct);
5265 +               }
5266 +
5267 +       }
5268 +       
5269 +       return(NF_ACCEPT);
5270 +}
5271 +
5272 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5273 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
5274 +
5275 +static void fini(void)
5276 +{
5277 +       int i;
5278 +
5279 +       for(i = 0 ; (i < ports_c); i++) {
5280 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5281 +                                       ports[i]);
5282 +               ip_conntrack_helper_unregister(&quake3[i]);
5283 +       } 
5284 +}
5285 +
5286 +static int __init init(void)
5287 +{
5288 +       int i, ret;
5289 +       char *tmpname;
5290 +
5291 +       if(!ports[0])
5292 +               ports[0]=QUAKE3_MASTER_PORT;
5293 +
5294 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5295 +               /* Create helper structure */
5296 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5297 +
5298 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5299 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5300 +               quake3[i].mask.dst.protonum = 0xFFFF;
5301 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
5302 +               quake3[i].help = quake3_help;
5303 +               quake3[i].me = THIS_MODULE;
5304 +
5305 +               tmpname = &quake3_names[i][0];
5306 +               if (ports[i] == QUAKE3_MASTER_PORT)
5307 +                       sprintf(tmpname, "quake3");
5308 +               else
5309 +                       sprintf(tmpname, "quake3-%d", i);
5310 +               quake3[i].name = tmpname;
5311 +               
5312 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5313 +                      ports[i]);
5314 +
5315 +               ret=ip_conntrack_helper_register(&quake3[i]);
5316 +               if(ret) {
5317 +                       fini();
5318 +                       return(ret);
5319 +               }
5320 +               ports_c++;
5321 +       }
5322 +
5323 +       return(0);
5324 +}
5325 +
5326 +module_init(init);
5327 +module_exit(fini);
5328 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rsh.c
5329 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rsh.c       1970-01-01 01:00:00.000000000 +0100
5330 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rsh.c   2004-06-25 12:24:48.841602528 +0200
5331 @@ -0,0 +1,331 @@
5332 +/* RSH extension for IP connection tracking, Version 1.0
5333 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5334 + * based on HW's ip_conntrack_irc.c    
5335 + *
5336 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
5337 + *
5338 + *      This program is free software; you can redistribute it and/or
5339 + *      modify it under the terms of the GNU General Public License
5340 + *      as published by the Free Software Foundation; either version
5341 + *      2 of the License, or (at your option) any later version.
5342 + **
5343 + *     Module load syntax:
5344 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
5345 + *     
5346 + *     please give the ports of all RSH servers You wish to connect to.
5347 + *     If You don't specify ports, the default will be port 514
5348 + **
5349 + *      Note to all:
5350 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
5351 + *        unfortunately I babysit some sysadmins that won't migrate
5352 + *       their legacy crap, in our second tier.
5353 + */
5354 +
5355 +
5356 +/*
5357 + *  Some docco ripped from the net to teach me all there is to know about
5358 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
5359 + *  this module).
5360 + *
5361 + *  I have no idea what "unix rshd man pages" these guys have .. but that
5362 + *  is some pretty detailed docco!
5363 + **
5364 + *
5365 + *  4. Of the rsh protocol.
5366 + *  -----------------------
5367 + * 
5368 + *   The rshd listens on TCP port #514. The following info is from the unix
5369 + *   rshd man pages :
5370 + * 
5371 + *   "Service Request Protocol
5372 + * 
5373 + *    When the rshd daemon receives a service request, it initiates the
5374 + *    following protocol:
5375 + * 
5376 + *     1. The rshd daemon checks the source port number for the request.
5377 + *        If the port number is not in the range 0 through 1023, the rshd daemon
5378 + *        terminates the connection.
5379 + * 
5380 + *     2. The rshd daemon reads characters from the socket up to a null byte.
5381 + *        The string read is interpreted as an ASCII number (base 10). If this
5382 + *        number is nonzero, the rshd daemon interprets it as the port number
5383 + *        of a secondary stream to be used as standard error. A second connection
5384 + *        is created to the specified port on the client host. The source port
5385 + *        on the local host is in the range 0 through 1023.
5386 + * 
5387 + *     3. The rshd daemon uses the source address of the initial connection
5388 + *        request to determine the name of the client host. If the name cannot
5389 + *        be determined, the rshd daemon uses the dotted decimal representation
5390 + *        of the client host's address.
5391 + * 
5392 + *     4. The rshd daemon retrieves the following information from the initial
5393 + *        socket:
5394 + * 
5395 + *         * A null-terminated string of at most 16 bytes interpreted as
5396 + *           the user name of the user on the client host.
5397 + * 
5398 + *         * A null-terminated string of at most 16 bytes interpreted as
5399 + *           the user name to be used on the local server host.
5400 + * 
5401 + *         * Another null-terminated string interpreted as a command line
5402 + *           to be passed to a shell on the local server host.
5403 + * 
5404 + *     5. The rshd daemon attempts to validate the user using the following steps:
5405 + * 
5406 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
5407 + *            file and tries to switch to the home directory (using the chdir
5408 + *            subroutine). If either the lookup or the directory change fails,
5409 + *            the rshd daemon terminates the connection.
5410 + * 
5411 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
5412 + *            the /etc/hosts.equiv file to see if the name of the client
5413 + *            workstation is listed. If the client workstation is listed as an
5414 + *            equivalent host, the rshd daemon validates the user.
5415 + * 
5416 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
5417 + *            authenticate the user by checking the .rhosts file.
5418 + * 
5419 + *         d. If either the $HOME/.rhosts authentication fails or the
5420 + *            client host is not an equivalent host, the rshd daemon
5421 + *            terminates the connection.
5422 + * 
5423 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
5424 + *        on the initial connection and passes the command line to the user's
5425 + *        local login shell. The shell then inherits the network connections
5426 + *        established by the rshd daemon."
5427 + * 
5428 + */
5429 +
5430 +
5431 +#include <linux/module.h>
5432 +#include <linux/netfilter.h>
5433 +#include <linux/ip.h>
5434 +#include <net/checksum.h>
5435 +#include <net/tcp.h>
5436 +
5437 +#include <linux/netfilter_ipv4/lockhelp.h>
5438 +#include <linux/netfilter_ipv4/ip_tables.h>
5439 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5440 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
5441 +
5442 +#define MAX_PORTS 8
5443 +static int ports[MAX_PORTS];
5444 +static int ports_n_c = 0;
5445 +
5446 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
5447 +MODULE_DESCRIPTION("RSH connection tracking module");
5448 +MODULE_LICENSE("GPL");
5449 +#ifdef MODULE_PARM
5450 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5451 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
5452 +#endif
5453 +
5454 +DECLARE_LOCK(ip_rsh_lock);
5455 +struct module *ip_conntrack_rsh = THIS_MODULE;
5456 +
5457 +#if 0
5458 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
5459 +                                       format, ## args)
5460 +#else
5461 +#define DEBUGP(format, args...)
5462 +#endif
5463 +
5464 +
5465 +
5466 +/* FIXME: This should be in userspace.  Later. */
5467 +static int help(const struct iphdr *iph, size_t len,
5468 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5469 +{
5470 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5471 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5472 +       const char *data = (const char *) tcph + tcph->doff * 4;
5473 +       u_int32_t tcplen = len - iph->ihl * 4;
5474 +       int dir = CTINFO2DIR(ctinfo);
5475 +        struct ip_conntrack_expect expect, *exp = &expect;
5476 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
5477 +       u_int16_t port;
5478 +       int maxoctet;
5479 +
5480 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
5481 +        *  original array size used in rshd/glibc) -- is there a
5482 +        *  vulnerability in rshd.c in the looped port *= 10?
5483 +        */
5484 +
5485 +
5486 +       DEBUGP("entered\n");
5487 +
5488 +       /* bail if packet is not from RSH client */
5489 +       if (dir == IP_CT_DIR_REPLY)
5490 +               return NF_ACCEPT;
5491 +
5492 +       /* Until there's been traffic both ways, don't look in packets. */
5493 +       if (ctinfo != IP_CT_ESTABLISHED
5494 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5495 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
5496 +               return NF_ACCEPT;
5497 +       }
5498 +
5499 +       /* Not whole TCP header? */
5500 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5501 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
5502 +               return NF_ACCEPT;
5503 +       }
5504 +
5505 +       /* Checksum invalid?  Ignore. */
5506 +       /* FIXME: Source route IP option packets --RR */
5507 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5508 +                        csum_partial((char *) tcph, tcplen, 0))) {
5509 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5510 +                    tcph, tcplen, NIPQUAD(iph->saddr),
5511 +                    NIPQUAD(iph->daddr));
5512 +               return NF_ACCEPT;
5513 +       }
5514 +
5515 +       /* find the rsh stderr port */
5516 +       maxoctet = 4;
5517 +       port = 0;
5518 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
5519 +               if (*data < 0)
5520 +                       return(1);
5521 +               if (*data == 0)
5522 +                       break;
5523 +               if (*data < 48 || *data > 57) {
5524 +                       DEBUGP("these aren't the packets you're looking for ..\n");
5525 +                       return NF_ACCEPT;
5526 +               }
5527 +               port = port * 10 + ( *data - 48 );
5528 +       }
5529 +
5530 +       /* dont relate sessions that try to expose the client */
5531 +       DEBUGP("found port %u\n", port);
5532 +       if (port > 1023) {
5533 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
5534 +               return NF_ACCEPT;
5535 +       }
5536 +
5537 +
5538 +       LOCK_BH(&ip_rsh_lock);
5539 +
5540 +       /*  new(,related) connection is;
5541 +        *          reply + dst (uint)port + src port (0:1023)
5542 +        */
5543 +       memset(&expect, 0, sizeof(expect));
5544 +
5545 +       /*  save some discovered data, in case someone ever wants to write
5546 +        *  a NAT module for this bastard ..
5547 +        */
5548 +       exp_rsh_info->port = port;
5549 +
5550 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
5551 +
5552 +
5553 +       /* Watch out, Radioactive-Man! */
5554 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5555 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5556 +       exp->tuple.src.u.tcp.port = 0;
5557 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
5558 +       exp->tuple.dst.protonum = IPPROTO_TCP;
5559 +
5560 +       exp->mask.src.ip = 0xffffffff;
5561 +       exp->mask.dst.ip = 0xffffffff;
5562 +
5563 +       exp->mask.src.u.tcp.port = htons(0xfc00);
5564 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
5565 +       exp->mask.dst.protonum = 0xffff;
5566 +
5567 +       exp->expectfn = NULL;
5568 +
5569 +       ip_conntrack_expect_related(&expect, ct);
5570 +
5571 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5572 +               NIPQUAD(exp->tuple.src.ip),
5573 +               ntohs(exp->tuple.src.u.tcp.port),
5574 +               NIPQUAD(exp->tuple.dst.ip),
5575 +               ntohs(exp->tuple.dst.u.tcp.port));
5576 +
5577 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5578 +               NIPQUAD(exp->mask.src.ip),
5579 +               ntohs(exp->mask.src.u.tcp.port),
5580 +               NIPQUAD(exp->mask.dst.ip),
5581 +               ntohs(exp->mask.dst.u.tcp.port));
5582 +       UNLOCK_BH(&ip_rsh_lock);
5583 +
5584 +       return NF_ACCEPT;
5585 +}
5586 +
5587 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
5588 +
5589 +static void fini(void);
5590 +
5591 +static int __init init(void)
5592 +{
5593 +       int port, ret;
5594 +       static char name[10];
5595 +
5596 +
5597 +       /* If no port given, default to standard RSH port */
5598 +       if (ports[0] == 0)
5599 +               ports[0] = RSH_PORT;
5600 +
5601 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5602 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5603 +
5604 +                if (ports[port] == RSH_PORT)
5605 +                        sprintf(name, "rsh");
5606 +                else
5607 +                        sprintf(name, "rsh-%d", port);
5608 +
5609 +               rsh_helpers[port].name = name;
5610 +               rsh_helpers[port].me = THIS_MODULE;
5611 +               rsh_helpers[port].max_expected = 1;
5612 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5613 +               rsh_helpers[port].timeout = 0;
5614 +
5615 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5616 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
5617 +
5618 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
5619 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
5620 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
5621 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
5622 +
5623 +               rsh_helpers[port].help = help;
5624 +
5625 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5626 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5627 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
5628 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
5629 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
5630 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
5631 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5632 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
5633 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
5634 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
5635 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
5636 +
5637 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
5638 +
5639 +               if (ret) {
5640 +                       printk("ERROR registering port %d\n",
5641 +                               ports[port]);
5642 +                       fini();
5643 +                       return -EBUSY;
5644 +               }
5645 +               ports_n_c++;
5646 +       }
5647 +       return 0;
5648 +}
5649 +
5650 +/* This function is intentionally _NOT_ defined as __exit, because 
5651 + * it is needed by the init function */
5652 +static void fini(void)
5653 +{
5654 +       int port;
5655 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5656 +               DEBUGP("unregistering port %d\n", ports[port]);
5657 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
5658 +       }
5659 +}
5660 +
5661 +module_init(init);
5662 +module_exit(fini);
5663 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rtsp.c
5664 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_rtsp.c      1970-01-01 01:00:00.000000000 +0100
5665 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_rtsp.c  2004-06-25 12:24:50.032421496 +0200
5666 @@ -0,0 +1,507 @@
5667 +/*
5668 + * RTSP extension for IP connection tracking
5669 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5670 + * based on ip_conntrack_irc.c
5671 + *
5672 + *      This program is free software; you can redistribute it and/or
5673 + *      modify it under the terms of the GNU General Public License
5674 + *      as published by the Free Software Foundation; either version
5675 + *      2 of the License, or (at your option) any later version.
5676 + *
5677 + * Module load syntax:
5678 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5679 + *                              max_outstanding=n setup_timeout=secs
5680 + *
5681 + * If no ports are specified, the default will be port 554.
5682 + *
5683 + * With max_outstanding you can define the maximum number of not yet
5684 + * answered SETUP requests per RTSP session (default 8).
5685 + * With setup_timeout you can specify how long the system waits for
5686 + * an expected data channel (default 300 seconds).
5687 + */
5688 +
5689 +#include <linux/config.h>
5690 +#include <linux/module.h>
5691 +#include <linux/netfilter.h>
5692 +#include <linux/ip.h>
5693 +#include <net/checksum.h>
5694 +#include <net/tcp.h>
5695 +
5696 +#include <linux/netfilter_ipv4/lockhelp.h>
5697 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5698 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5699 +
5700 +#include <linux/ctype.h>
5701 +#define NF_NEED_STRNCASECMP
5702 +#define NF_NEED_STRTOU16
5703 +#define NF_NEED_STRTOU32
5704 +#define NF_NEED_NEXTLINE
5705 +#include <linux/netfilter_helpers.h>
5706 +#define NF_NEED_MIME_NEXTLINE
5707 +#include <linux/netfilter_mime.h>
5708 +
5709 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5710 +
5711 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5712 +#ifdef IP_NF_RTSP_DEBUG
5713 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5714 +#else
5715 +#define DEBUGP(fmt, args...)
5716 +#endif
5717 +
5718 +#define MAX_PORTS 8
5719 +static int ports[MAX_PORTS];
5720 +static int num_ports = 0;
5721 +static int max_outstanding = 8;
5722 +static unsigned int setup_timeout = 300;
5723 +
5724 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5725 +MODULE_DESCRIPTION("RTSP connection tracking module");
5726 +MODULE_LICENSE("GPL");
5727 +#ifdef MODULE_PARM
5728 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5729 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5730 +MODULE_PARM(max_outstanding, "i");
5731 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5732 +MODULE_PARM(setup_timeout, "i");
5733 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5734 +#endif
5735 +
5736 +DECLARE_LOCK(ip_rtsp_lock);
5737 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5738 +
5739 +/*
5740 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5741 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
5742 + * ports so keep this reasonably high.  If this is too low, you will see a
5743 + * lot of "no free client map entries" messages.
5744 + */
5745 +#define MAX_PORT_MAPS 16
5746 +
5747 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5748 +
5749 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5750 +
5751 +/*
5752 + * Parse an RTSP packet.
5753 + *
5754 + * Returns zero if parsing failed.
5755 + *
5756 + * Parameters:
5757 + *  IN      ptcp        tcp data pointer
5758 + *  IN      tcplen      tcp data len
5759 + *  IN/OUT  ptcpoff     points to current tcp offset
5760 + *  OUT     phdrsoff    set to offset of rtsp headers
5761 + *  OUT     phdrslen    set to length of rtsp headers
5762 + *  OUT     pcseqoff    set to offset of CSeq header
5763 + *  OUT     pcseqlen    set to length of CSeq header
5764 + */
5765 +static int
5766 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5767 +                   uint* phdrsoff, uint* phdrslen,
5768 +                   uint* pcseqoff, uint* pcseqlen)
5769 +{
5770 +    uint    entitylen = 0;
5771 +    uint    lineoff;
5772 +    uint    linelen;
5773 +
5774 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5775 +    {
5776 +        return 0;
5777 +    }
5778 +
5779 +    *phdrsoff = *ptcpoff;
5780 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5781 +    {
5782 +        if (linelen == 0)
5783 +        {
5784 +            if (entitylen > 0)
5785 +            {
5786 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5787 +            }
5788 +            break;
5789 +        }
5790 +        if (lineoff+linelen > tcplen)
5791 +        {
5792 +            INFOP("!! overrun !!\n");
5793 +            break;
5794 +        }
5795 +
5796 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5797 +        {
5798 +            *pcseqoff = lineoff;
5799 +            *pcseqlen = linelen;
5800 +        }
5801 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5802 +        {
5803 +            uint off = lineoff+15;
5804 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
5805 +            nf_strtou32(ptcp+off, &entitylen);
5806 +        }
5807 +    }
5808 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
5809 +
5810 +    return 1;
5811 +}
5812 +
5813 +/*
5814 + * Find lo/hi client ports (if any) in transport header
5815 + * In:
5816 + *   ptcp, tcplen = packet
5817 + *   tranoff, tranlen = buffer to search
5818 + *
5819 + * Out:
5820 + *   pport_lo, pport_hi = lo/hi ports (host endian)
5821 + *
5822 + * Returns nonzero if any client ports found
5823 + *
5824 + * Note: it is valid (and expected) for the client to request multiple
5825 + * transports, so we need to parse the entire line.
5826 + */
5827 +static int
5828 +rtsp_parse_transport(char* ptran, uint tranlen,
5829 +                     struct ip_ct_rtsp_expect* prtspexp)
5830 +{
5831 +    int     rc = 0;
5832 +    uint    off = 0;
5833 +
5834 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5835 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
5836 +    {
5837 +        INFOP("sanity check failed\n");
5838 +        return 0;
5839 +    }
5840 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5841 +    off += 10;
5842 +    SKIP_WSPACE(ptran, tranlen, off);
5843 +
5844 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
5845 +    while (off < tranlen)
5846 +    {
5847 +        const char* pparamend;
5848 +        uint        nextparamoff;
5849 +
5850 +        pparamend = memchr(ptran+off, ',', tranlen-off);
5851 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5852 +        nextparamoff = pparamend-ptran;
5853 +
5854 +        while (off < nextparamoff)
5855 +        {
5856 +            const char* pfieldend;
5857 +            uint        nextfieldoff;
5858 +
5859 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5860 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5861 +
5862 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
5863 +            {
5864 +                u_int16_t   port;
5865 +                uint        numlen;
5866 +
5867 +                off += 12;
5868 +                numlen = nf_strtou16(ptran+off, &port);
5869 +                off += numlen;
5870 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
5871 +                {
5872 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
5873 +                }
5874 +                else
5875 +                {
5876 +                    prtspexp->loport = prtspexp->hiport = port;
5877 +                    if (ptran[off] == '-')
5878 +                    {
5879 +                        off++;
5880 +                        numlen = nf_strtou16(ptran+off, &port);
5881 +                        off += numlen;
5882 +                        prtspexp->pbtype = pb_range;
5883 +                        prtspexp->hiport = port;
5884 +
5885 +                        // If we have a range, assume rtp:
5886 +                        // loport must be even, hiport must be loport+1
5887 +                        if ((prtspexp->loport & 0x0001) != 0 ||
5888 +                            prtspexp->hiport != prtspexp->loport+1)
5889 +                        {
5890 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
5891 +                                   prtspexp->loport, prtspexp->hiport);
5892 +                            prtspexp->loport &= 0xfffe;
5893 +                            prtspexp->hiport = prtspexp->loport+1;
5894 +                        }
5895 +                    }
5896 +                    else if (ptran[off] == '/')
5897 +                    {
5898 +                        off++;
5899 +                        numlen = nf_strtou16(ptran+off, &port);
5900 +                        off += numlen;
5901 +                        prtspexp->pbtype = pb_discon;
5902 +                        prtspexp->hiport = port;
5903 +                    }
5904 +                    rc = 1;
5905 +                }
5906 +            }
5907 +
5908 +            /*
5909 +             * Note we don't look for the destination parameter here.
5910 +             * If we are using NAT, the NAT module will handle it.  If not,
5911 +             * and the client is sending packets elsewhere, the expectation
5912 +             * will quietly time out.
5913 +             */
5914 +
5915 +            off = nextfieldoff;
5916 +        }
5917 +
5918 +        off = nextparamoff;
5919 +    }
5920 +
5921 +    return rc;
5922 +}
5923 +
5924 +/*** conntrack functions ***/
5925 +
5926 +/* outbound packet: client->server */
5927 +static int
5928 +help_out(const struct iphdr* iph, size_t pktlen,
5929 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5930 +{
5931 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
5932 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
5933 +    uint    tcplen = pktlen - iph->ihl * 4;
5934 +    char*   pdata = (char*)tcph + tcph->doff * 4;
5935 +    uint    datalen = tcplen - tcph->doff * 4;
5936 +    uint    dataoff = 0;
5937 +
5938 +    struct ip_conntrack_expect exp;
5939 +
5940 +    while (dataoff < datalen)
5941 +    {
5942 +        uint    cmdoff = dataoff;
5943 +        uint    hdrsoff = 0;
5944 +        uint    hdrslen = 0;
5945 +        uint    cseqoff = 0;
5946 +        uint    cseqlen = 0;
5947 +        uint    lineoff = 0;
5948 +        uint    linelen = 0;
5949 +        uint    off;
5950 +        int     rc;
5951 +
5952 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
5953 +                                &hdrsoff, &hdrslen,
5954 +                                &cseqoff, &cseqlen))
5955 +        {
5956 +            break;      /* not a valid message */
5957 +        }
5958 +
5959 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5960 +        {
5961 +            continue;   /* not a SETUP message */
5962 +        }
5963 +        DEBUGP("found a setup message\n");
5964 +
5965 +        memset(&exp, 0, sizeof(exp));
5966 +
5967 +        off = 0;
5968 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5969 +                                &lineoff, &linelen))
5970 +        {
5971 +            if (linelen == 0)
5972 +            {
5973 +                break;
5974 +            }
5975 +            if (off > hdrsoff+hdrslen)
5976 +            {
5977 +                INFOP("!! overrun !!");
5978 +                break;
5979 +            }
5980 +
5981 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5982 +            {
5983 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5984 +                                     &exp.help.exp_rtsp_info);
5985 +            }
5986 +        }
5987 +
5988 +        if (exp.help.exp_rtsp_info.loport == 0)
5989 +        {
5990 +            DEBUGP("no udp transports found\n");
5991 +            continue;   /* no udp transports found */
5992 +        }
5993 +
5994 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5995 +              (int)exp.help.exp_rtsp_info.pbtype,
5996 +              exp.help.exp_rtsp_info.loport,
5997 +              exp.help.exp_rtsp_info.hiport);
5998 +
5999 +        LOCK_BH(&ip_rtsp_lock);
6000 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
6001 +        exp.help.exp_rtsp_info.len = hdrslen;
6002 +
6003 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6004 +        exp.mask.src.ip  = 0xffffffff;
6005 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
6006 +        exp.mask.dst.ip  = 0xffffffff;
6007 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
6008 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
6009 +        exp.tuple.dst.protonum = IPPROTO_UDP;
6010 +        exp.mask.dst.protonum  = 0xffff;
6011 +
6012 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6013 +                NIPQUAD(exp.tuple.src.ip),
6014 +                ntohs(exp.tuple.src.u.tcp.port),
6015 +                NIPQUAD(exp.tuple.dst.ip),
6016 +                ntohs(exp.tuple.dst.u.tcp.port));
6017 +
6018 +        /* pass the request off to the nat helper */
6019 +        rc = ip_conntrack_expect_related(&exp, ct);
6020 +        UNLOCK_BH(&ip_rtsp_lock);
6021 +        if (rc == 0)
6022 +        {
6023 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
6024 +        }
6025 +        else
6026 +        {
6027 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
6028 +        }
6029 +    }
6030 +
6031 +    return NF_ACCEPT;
6032 +}
6033 +
6034 +/* inbound packet: server->client */
6035 +static int
6036 +help_in(const struct iphdr* iph, size_t pktlen,
6037 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6038 +{
6039 +    return NF_ACCEPT;
6040 +}
6041 +
6042 +static int
6043 +help(const struct iphdr* iph, size_t pktlen,
6044 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6045 +{
6046 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6047 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6048 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
6049 +
6050 +    /* Until there's been traffic both ways, don't look in packets. */
6051 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
6052 +    {
6053 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
6054 +        return NF_ACCEPT;
6055 +    }
6056 +
6057 +    /* Not whole TCP header? */
6058 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
6059 +    {
6060 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
6061 +        return NF_ACCEPT;
6062 +    }
6063 +
6064 +    /* Checksum invalid?  Ignore. */
6065 +    /* FIXME: Source route IP option packets --RR */
6066 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6067 +                     csum_partial((char*)tcph, tcplen, 0)))
6068 +    {
6069 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6070 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6071 +        return NF_ACCEPT;
6072 +    }
6073 +
6074 +    switch (CTINFO2DIR(ctinfo))
6075 +    {
6076 +    case IP_CT_DIR_ORIGINAL:
6077 +        help_out(iph, pktlen, ct, ctinfo);
6078 +        break;
6079 +    case IP_CT_DIR_REPLY:
6080 +        help_in(iph, pktlen, ct, ctinfo);
6081 +        break;
6082 +    }
6083 +
6084 +    return NF_ACCEPT;
6085 +}
6086 +
6087 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
6088 +static char rtsp_names[MAX_PORTS][10];
6089 +
6090 +/* This function is intentionally _NOT_ defined as __exit */
6091 +static void
6092 +fini(void)
6093 +{
6094 +    int i;
6095 +    for (i = 0; i < num_ports; i++)
6096 +    {
6097 +        DEBUGP("unregistering port %d\n", ports[i]);
6098 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
6099 +    }
6100 +}
6101 +
6102 +static int __init
6103 +init(void)
6104 +{
6105 +    int i, ret;
6106 +    struct ip_conntrack_helper *hlpr;
6107 +    char *tmpname;
6108 +
6109 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
6110 +
6111 +    if (max_outstanding < 1)
6112 +    {
6113 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
6114 +        return -EBUSY;
6115 +    }
6116 +    if (setup_timeout < 0)
6117 +    {
6118 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
6119 +        return -EBUSY;
6120 +    }
6121 +
6122 +    /* If no port given, default to standard rtsp port */
6123 +    if (ports[0] == 0)
6124 +    {
6125 +        ports[0] = RTSP_PORT;
6126 +    }
6127 +
6128 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
6129 +    {
6130 +        hlpr = &rtsp_helpers[i];
6131 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
6132 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
6133 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
6134 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
6135 +        hlpr->mask.dst.protonum = 0xFFFF;
6136 +        hlpr->max_expected = max_outstanding;
6137 +        hlpr->timeout = setup_timeout;
6138 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
6139 +        hlpr->me = ip_conntrack_rtsp;
6140 +        hlpr->help = help;
6141 +
6142 +        tmpname = &rtsp_names[i][0];
6143 +        if (ports[i] == RTSP_PORT)
6144 +        {
6145 +            sprintf(tmpname, "rtsp");
6146 +        }
6147 +        else
6148 +        {
6149 +            sprintf(tmpname, "rtsp-%d", i);
6150 +        }
6151 +        hlpr->name = tmpname;
6152 +
6153 +        DEBUGP("port #%d: %d\n", i, ports[i]);
6154 +
6155 +        ret = ip_conntrack_helper_register(hlpr);
6156 +
6157 +        if (ret)
6158 +        {
6159 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
6160 +            fini();
6161 +            return -EBUSY;
6162 +        }
6163 +        num_ports++;
6164 +    }
6165 +    return 0;
6166 +}
6167 +
6168 +#ifdef CONFIG_IP_NF_NAT_NEEDED
6169 +EXPORT_SYMBOL(ip_rtsp_lock);
6170 +#endif
6171 +
6172 +module_init(init);
6173 +module_exit(fini);
6174 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c
6175 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-06-25 10:47:46.000000000 +0200
6176 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-06-25 12:21:37.872634224 +0200
6177 @@ -111,6 +111,9 @@
6178                 len += sprintf(buffer + len, "[ASSURED] ");
6179         len += sprintf(buffer + len, "use=%u ",
6180                        atomic_read(&conntrack->ct_general.use));
6181 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
6182 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
6183 +#endif
6184         len += sprintf(buffer + len, "\n");
6185  
6186         return len;
6187 @@ -334,6 +337,11 @@
6188  /* From ip_conntrack_proto_icmp.c */
6189  extern unsigned long ip_ct_generic_timeout;
6190  
6191 +/* Log invalid packets of a given protocol */
6192 +unsigned int ip_ct_log_invalid = 0;
6193 +static int log_invalid_proto_min = 0;
6194 +static int log_invalid_proto_max = 255;
6195 +
6196  static struct ctl_table_header *ip_ct_sysctl_header;
6197  
6198  static ctl_table ip_ct_sysctl_table[] = {
6199 @@ -449,6 +457,17 @@
6200                 .mode           = 0644,
6201                 .proc_handler   = &proc_dointvec_jiffies,
6202         },
6203 +       {
6204 +               .ctl_name       = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
6205 +               .procname       = "ip_conntrack_log_invalid",
6206 +               .data           = &ip_ct_log_invalid,
6207 +               .maxlen         = sizeof(unsigned int),
6208 +               .mode           = 0644,
6209 +               .proc_handler   = &proc_dointvec_minmax,
6210 +               .strategy       = &sysctl_intvec,
6211 +               .extra1         = &log_invalid_proto_min,
6212 +               .extra2         = &log_invalid_proto_max,
6213 +       },
6214         { .ctl_name = 0 }
6215  };
6216  
6217 @@ -634,6 +653,7 @@
6218  EXPORT_SYMBOL(ip_conntrack_alter_reply);
6219  EXPORT_SYMBOL(ip_conntrack_destroyed);
6220  EXPORT_SYMBOL(ip_conntrack_get);
6221 +EXPORT_SYMBOL(__ip_conntrack_confirm);
6222  EXPORT_SYMBOL(need_ip_conntrack);
6223  EXPORT_SYMBOL(ip_conntrack_helper_register);
6224  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
6225 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_talk.c
6226 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_talk.c      1970-01-01 01:00:00.000000000 +0100
6227 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_talk.c  2004-06-25 12:28:43.650906088 +0200
6228 @@ -0,0 +1,360 @@
6229 +/* 
6230 + * talk extension for IP connection tracking. 
6231 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6232 + *
6233 + *      This program is free software; you can redistribute it and/or
6234 + *      modify it under the terms of the GNU General Public License
6235 + *      as published by the Free Software Foundation; either version
6236 + *      2 of the License, or (at your option) any later version.
6237 + **
6238 + *     Module load syntax:
6239 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
6240 + *
6241 + *             talk=[0|1]      disable|enable old talk support
6242 + *            ntalk=[0|1]      disable|enable ntalk support
6243 + *           ntalk2=[0|1]      disable|enable ntalk2 support
6244 + *
6245 + *     The default is talk=1 ntalk=1 ntalk2=1
6246 + *
6247 + *     The helper does not support simultaneous talk requests.
6248 + **
6249 + *
6250 + *             ASCII art on talk protocols
6251 + *     
6252 + *     
6253 + *     caller server               callee server
6254 + *             |     \           /
6255 + *             |       \       /
6256 + *             |         \   /
6257 + *             |           /  
6258 + *             |         /   \
6259 + *           2 |     1 /       \ 3
6260 + *     caller client  ----------- callee client
6261 + *                              4
6262 + *
6263 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
6264 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
6265 + *     3. callee client <-> caller server: LOOK_UP invitation
6266 + *     4. callee client <-> caller client: talk data channel
6267 + *
6268 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
6269 + *      draft-hunter-talk-00.txt
6270 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
6271 + */
6272 +#include <linux/config.h>
6273 +#include <linux/module.h>
6274 +#include <linux/netfilter.h>
6275 +#include <linux/ip.h>
6276 +#include <net/checksum.h>
6277 +#include <net/udp.h>
6278 +
6279 +#include <linux/netfilter_ipv4/lockhelp.h>
6280 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6281 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
6282 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6283 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
6284 +
6285 +/* Default all talk protocols are supported */
6286 +static int talk = 1;
6287 +static int ntalk = 1;
6288 +static int ntalk2 = 1;
6289 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6290 +MODULE_DESCRIPTION("talk connection tracking module");
6291 +MODULE_LICENSE("GPL");
6292 +#ifdef MODULE_PARM
6293 +MODULE_PARM(talk, "i");
6294 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
6295 +MODULE_PARM(ntalk, "i");
6296 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
6297 +MODULE_PARM(ntalk2, "i");
6298 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
6299 +#endif
6300 +
6301 +DECLARE_LOCK(ip_talk_lock);
6302 +struct module *ip_conntrack_talk = THIS_MODULE;
6303 +
6304 +#if 0
6305 +#define DEBUGP printk
6306 +#else
6307 +#define DEBUGP(format, args...)
6308 +#endif
6309 +
6310 +static int talk_expect(struct ip_conntrack *ct);
6311 +static int ntalk_expect(struct ip_conntrack *ct);
6312 +
6313 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
6314 +
6315 +static int talk_help_response(const struct iphdr *iph, size_t len,
6316 +                             struct ip_conntrack *ct,
6317 +                             enum ip_conntrack_info ctinfo,
6318 +                             int talk_port,
6319 +                             u_char mode,
6320 +                             u_char type,
6321 +                             u_char answer,
6322 +                             struct talk_addr *addr)
6323 +{
6324 +       int dir = CTINFO2DIR(ctinfo);
6325 +       struct ip_conntrack_expect expect, *exp = &expect;
6326 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
6327 +
6328 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
6329 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
6330 +               type, answer);
6331 +
6332 +       if (!(answer == SUCCESS && type == mode))
6333 +               return NF_ACCEPT;
6334 +       
6335 +       memset(&expect, 0, sizeof(expect));
6336 +       
6337 +       if (type == ANNOUNCE) {
6338 +
6339 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
6340 +
6341 +               /* update the talk info */
6342 +               LOCK_BH(&ip_talk_lock);
6343 +               exp_talk_info->port = htons(talk_port);
6344 +
6345 +               /* expect callee client -> caller server message */
6346 +               exp->tuple = ((struct ip_conntrack_tuple)
6347 +                       { { ct->tuplehash[dir].tuple.src.ip,
6348 +                           { 0 } },
6349 +                         { ct->tuplehash[dir].tuple.dst.ip,
6350 +                           { .tcp = { htons(talk_port) } },
6351 +                           IPPROTO_UDP }});
6352 +               exp->mask = ((struct ip_conntrack_tuple)
6353 +                       { { 0xFFFFFFFF, { 0 } },
6354 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6355 +               
6356 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
6357 +
6358 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
6359 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
6360 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
6361 +
6362 +               /* Ignore failure; should only happen with NAT */
6363 +               ip_conntrack_expect_related(&expect, ct);
6364 +               UNLOCK_BH(&ip_talk_lock);
6365 +       }
6366 +       if (type == LOOK_UP) {
6367 +
6368 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
6369 +
6370 +               /* update the talk info */
6371 +               LOCK_BH(&ip_talk_lock);
6372 +               exp_talk_info->port = addr->ta_port;
6373 +
6374 +               /* expect callee client -> caller client connection */
6375 +               exp->tuple = ((struct ip_conntrack_tuple)
6376 +                       { { ct->tuplehash[!dir].tuple.src.ip,
6377 +                           { 0 } },
6378 +                         { addr->ta_addr,
6379 +                           { addr->ta_port },
6380 +                           IPPROTO_TCP }});
6381 +               exp->mask = ((struct ip_conntrack_tuple)
6382 +                       { { 0xFFFFFFFF, { 0 } },
6383 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6384 +               
6385 +               exp->expectfn = NULL;
6386 +               
6387 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
6388 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
6389 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
6390 +
6391 +               /* Ignore failure; should only happen with NAT */
6392 +               ip_conntrack_expect_related(&expect, ct);
6393 +               UNLOCK_BH(&ip_talk_lock);
6394 +       }
6395 +                   
6396 +       return NF_ACCEPT;
6397 +}
6398 +
6399 +/* FIXME: This should be in userspace.  Later. */
6400 +static int talk_help(const struct iphdr *iph, size_t len,
6401 +                    struct ip_conntrack *ct,
6402 +                    enum ip_conntrack_info ctinfo,
6403 +                    int talk_port,
6404 +                    u_char mode)
6405 +{
6406 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
6407 +       const char *data = (const char *)udph + sizeof(struct udphdr);
6408 +       int dir = CTINFO2DIR(ctinfo);
6409 +       size_t udplen;
6410 +
6411 +       DEBUGP("ip_ct_talk_help: help entered\n");
6412 +
6413 +       /* Until there's been traffic both ways, don't look in packets. */
6414 +       if (ctinfo != IP_CT_ESTABLISHED
6415 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6416 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
6417 +               return NF_ACCEPT;
6418 +       }
6419 +
6420 +       /* Not whole UDP header? */
6421 +       udplen = len - iph->ihl * 4;
6422 +       if (udplen < sizeof(struct udphdr)) {
6423 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
6424 +               return NF_ACCEPT;
6425 +       }
6426 +
6427 +       /* Checksum invalid?  Ignore. */
6428 +       /* FIXME: Source route IP option packets --RR */
6429 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6430 +                             csum_partial((char *)udph, udplen, 0))) {
6431 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6432 +                      udph, udplen, NIPQUAD(iph->saddr),
6433 +                      NIPQUAD(iph->daddr));
6434 +               return NF_ACCEPT;
6435 +       }
6436 +       
6437 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6438 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
6439 +
6440 +       if (dir == IP_CT_DIR_ORIGINAL)
6441 +               return NF_ACCEPT;
6442 +               
6443 +       if (talk_port == TALK_PORT
6444 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6445 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6446 +                                         ((struct talk_response *)data)->type, 
6447 +                                         ((struct talk_response *)data)->answer,
6448 +                                         &(((struct talk_response *)data)->addr));
6449 +       else if (talk_port == NTALK_PORT
6450 +                 && ntalk
6451 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6452 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6453 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6454 +                                         ((struct ntalk_response *)data)->type, 
6455 +                                         ((struct ntalk_response *)data)->answer,
6456 +                                         &(((struct ntalk_response *)data)->addr));
6457 +       else if (talk_port == NTALK_PORT
6458 +                && ntalk2
6459 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6460 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6461 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6462 +                                         ((struct ntalk2_response *)data)->type, 
6463 +                                         ((struct ntalk2_response *)data)->answer,
6464 +                                         &(((struct ntalk2_response *)data)->addr));
6465 +       else {
6466 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
6467 +                      (unsigned)udplen - sizeof(struct udphdr), 
6468 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6469 +               return NF_ACCEPT;
6470 +       }
6471 +}
6472 +
6473 +static int lookup_help(const struct iphdr *iph, size_t len,
6474 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6475 +{
6476 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
6477 +}
6478 +
6479 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
6480 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6481 +{
6482 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
6483 +}
6484 +
6485 +static struct ip_conntrack_helper lookup_helpers[2] = 
6486 +       { { { NULL, NULL },
6487 +           "talk",                                     /* name */
6488 +           0,                                          /* flags */
6489 +           NULL,                                       /* module */
6490 +           1,                                          /* max_expected */
6491 +           240,                                        /* timeout */
6492 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
6493 +             { 0, { 0 }, IPPROTO_UDP } },
6494 +           { { 0, { 0xFFFF } },                        /* mask */
6495 +             { 0, { 0 }, 0xFFFF } },
6496 +           lookup_help },                              /* helper */
6497 +          { { NULL, NULL },
6498 +            "ntalk",                                   /* name */
6499 +           0,                                          /* flags */
6500 +           NULL,                                       /* module */
6501 +           1,                                          /* max_expected */
6502 +           240,                                        /* timeout */
6503 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
6504 +             { 0, { 0 }, IPPROTO_UDP } },
6505 +           { { 0, { 0xFFFF } },                        /* mask */
6506 +             { 0, { 0 }, 0xFFFF } },
6507 +           lookup_nhelp }                              /* helper */
6508 +        };
6509 +
6510 +static int talk_expect(struct ip_conntrack *ct)
6511 +{
6512 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
6513 +       WRITE_LOCK(&ip_conntrack_lock);
6514 +       ct->helper = &lookup_helpers[0];
6515 +       WRITE_UNLOCK(&ip_conntrack_lock);
6516 +        
6517 +       return NF_ACCEPT;       /* unused */
6518 +}
6519 +
6520 +static int ntalk_expect(struct ip_conntrack *ct)
6521 +{
6522 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
6523 +       WRITE_LOCK(&ip_conntrack_lock);
6524 +       ct->helper = &lookup_helpers[1];
6525 +       WRITE_UNLOCK(&ip_conntrack_lock);
6526 +        
6527 +       return NF_ACCEPT;       /* unused */
6528 +}
6529 +
6530 +static int help(const struct iphdr *iph, size_t len,
6531 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6532 +{
6533 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
6534 +}
6535 +
6536 +static int nhelp(const struct iphdr *iph, size_t len,
6537 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6538 +{
6539 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
6540 +}
6541 +
6542 +static struct ip_conntrack_helper talk_helpers[2] = 
6543 +       { { { NULL, NULL },
6544 +           "talk",                                     /* name */
6545 +           0,                                          /* flags */
6546 +           THIS_MODULE,                                /* module */
6547 +           1,                                          /* max_expected */
6548 +           240,                                        /* timeout */
6549 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
6550 +             { 0, { 0 }, IPPROTO_UDP } },
6551 +           { { 0, { 0xFFFF } },                        /* mask */
6552 +             { 0, { 0 }, 0xFFFF } },
6553 +           help },                                     /* helper */
6554 +          { { NULL, NULL },
6555 +           "ntalk",                                    /* name */
6556 +           0,                                          /* flags */
6557 +           THIS_MODULE,                                /* module */
6558 +           1,                                          /* max_expected */
6559 +           240,                                        /* timeout */
6560 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
6561 +             { 0, { 0 }, IPPROTO_UDP } },
6562 +           { { 0, { 0xFFFF } },                        /* mask */
6563 +             { 0, { 0 }, 0xFFFF } },
6564 +           nhelp }                                     /* helper */
6565 +       };
6566 +
6567 +static int __init init(void)
6568 +{
6569 +       if (talk > 0)
6570 +               ip_conntrack_helper_register(&talk_helpers[0]);
6571 +       if (ntalk > 0 || ntalk2 > 0)
6572 +               ip_conntrack_helper_register(&talk_helpers[1]);
6573 +               
6574 +       return 0;
6575 +}
6576 +
6577 +static void __exit fini(void)
6578 +{
6579 +       if (talk > 0)
6580 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
6581 +       if (ntalk > 0 || ntalk2 > 0)
6582 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
6583 +}
6584 +
6585 +EXPORT_SYMBOL(ip_talk_lock);
6586 +
6587 +module_init(init);
6588 +module_exit(fini);
6589 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c
6590 --- linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c      2004-06-25 10:47:46.000000000 +0200
6591 +++ linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c  2004-06-25 12:21:02.340036000 +0200
6592 @@ -31,6 +31,7 @@
6593  
6594  #include <linux/netfilter_ipv4/ip_conntrack.h>
6595  #include <linux/netfilter_ipv4/ip_conntrack_core.h>
6596 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
6597  #include <linux/netfilter_ipv4/ip_nat.h>
6598  #include <linux/netfilter_ipv4/ip_nat_core.h>
6599  #include <linux/netfilter_ipv4/listhelp.h>
6600 @@ -144,7 +145,8 @@
6601         switch ((*pskb)->nh.iph->protocol) {
6602         case IPPROTO_ICMP:
6603                 /* ICMP errors. */
6604 -               ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
6605 +               protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
6606 +               ct = (struct ip_conntrack *)(*pskb)->nfct->master;
6607                 if (ct) {
6608                         /* We only do SNAT in the compatibility layer.
6609                            So we can manipulate ICMP errors from
6610 @@ -165,7 +167,8 @@
6611         case IPPROTO_UDP:
6612                 IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
6613  
6614 -               if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
6615 +               if (!ip_ct_get_tuple((*pskb)->nh.iph, *pskb,
6616 +                                    (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
6617                         if (net_ratelimit())
6618                                 printk("ip_fw_compat_masq: Can't get tuple\n");
6619                         return NF_ACCEPT;
6620 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.7/net/ipv4/netfilter/ip_nat_h323.c
6621 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_h323.c    1970-01-01 01:00:00.000000000 +0100
6622 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_h323.c        2004-06-25 12:21:34.918083384 +0200
6623 @@ -0,0 +1,419 @@
6624 +/* 
6625 + * H.323 'brute force' extension for NAT alteration. 
6626 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6627 + *
6628 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6629 + * (http://www.coritel.it/projects/sofia/nat.html)
6630 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6631 + * the unregistered helpers to the conntrack entries.
6632 + */
6633 +
6634 +
6635 +#include <linux/module.h>
6636 +#include <linux/netfilter.h>
6637 +#include <linux/ip.h>
6638 +#include <net/checksum.h>
6639 +#include <net/tcp.h>
6640 +
6641 +#include <linux/netfilter_ipv4/lockhelp.h>
6642 +#include <linux/netfilter_ipv4/ip_nat.h>
6643 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6644 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6645 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6646 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6647 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6648 +
6649 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6650 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6651 +MODULE_LICENSE("GPL");
6652 +
6653 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6654 +struct module *ip_nat_h323 = THIS_MODULE;
6655 +
6656 +#if 0
6657 +#define DEBUGP printk
6658 +#else
6659 +#define DEBUGP(format, args...)
6660 +#endif
6661 +
6662 +/* FIXME: Time out? --RR */
6663 +
6664 +static unsigned int 
6665 +h225_nat_expected(struct sk_buff **pskb,
6666 +                 unsigned int hooknum,
6667 +                 struct ip_conntrack *ct,
6668 +                 struct ip_nat_info *info);
6669 +
6670 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6671 +                                 struct ip_conntrack_expect *exp,
6672 +                                 struct ip_nat_info *info,
6673 +                                 enum ip_conntrack_info ctinfo,
6674 +                                 unsigned int hooknum,
6675 +                                 struct sk_buff **pskb);
6676 +                 
6677 +static struct ip_nat_helper h245 = 
6678 +       { { NULL, NULL },
6679 +          "H.245",                             /* name */
6680 +         0,                                    /* flags */
6681 +         NULL,                                 /* module */
6682 +         { { 0, { 0 } },                       /* tuple */
6683 +           { 0, { 0 }, IPPROTO_TCP } },
6684 +         { { 0, { 0xFFFF } },                  /* mask */
6685 +           { 0, { 0 }, 0xFFFF } },
6686 +         h225_nat_help,                        /* helper */
6687 +         h225_nat_expected                     /* expectfn */
6688 +       };
6689 +
6690 +static unsigned int
6691 +h225_nat_expected(struct sk_buff **pskb,
6692 +                 unsigned int hooknum,
6693 +                 struct ip_conntrack *ct,
6694 +                 struct ip_nat_info *info)
6695 +{
6696 +       struct ip_nat_multi_range mr;
6697 +       u_int32_t newdstip, newsrcip, newip;
6698 +       u_int16_t port;
6699 +       struct ip_ct_h225_expect *exp_info;
6700 +       struct ip_ct_h225_master *master_info;
6701 +       struct ip_conntrack *master = master_ct(ct);
6702 +       unsigned int is_h225, ret;
6703 +       
6704 +       IP_NF_ASSERT(info);
6705 +       IP_NF_ASSERT(master);
6706 +
6707 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6708 +
6709 +       DEBUGP("h225_nat_expected: We have a connection!\n");
6710 +       master_info = &ct->master->expectant->help.ct_h225_info;
6711 +       exp_info = &ct->master->help.exp_h225_info;
6712 +
6713 +       LOCK_BH(&ip_h323_lock);
6714 +
6715 +       DEBUGP("master: ");
6716 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6717 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6718 +       DEBUGP("conntrack: ");
6719 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6720 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6721 +               /* Make connection go to the client. */
6722 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6723 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6724 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6725 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6726 +       } else {
6727 +               /* Make the connection go to the server */
6728 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6729 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6730 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6731 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6732 +       }
6733 +       port = exp_info->port;
6734 +       is_h225 = master_info->is_h225 == H225_PORT;
6735 +       UNLOCK_BH(&ip_h323_lock);
6736 +       
6737 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6738 +               newip = newsrcip;
6739 +       else
6740 +               newip = newdstip;
6741 +
6742 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6743 +
6744 +       mr.rangesize = 1;
6745 +       /* We don't want to manip the per-protocol, just the IPs... */
6746 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6747 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6748 +
6749 +       /* ... unless we're doing a MANIP_DST, in which case, make
6750 +          sure we map to the correct port */
6751 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6752 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6753 +               mr.range[0].min = mr.range[0].max
6754 +                       = ((union ip_conntrack_manip_proto)
6755 +                               { .tcp = { port } });
6756 +       }
6757 +
6758 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
6759 +       
6760 +       if (is_h225) {
6761 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6762 +               /* NAT expectfn called with ip_nat_lock write-locked */
6763 +               info->helper = &h245;
6764 +       }
6765 +       return ret;
6766 +}
6767 +
6768 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6769 +                                    struct sk_buff **pskb,
6770 +                                    enum ip_conntrack_info ctinfo)
6771 +{
6772 +       struct iphdr *iph = (*pskb)->nh.iph;
6773 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6774 +       char *data = (char *) tcph + tcph->doff * 4;
6775 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6776 +       u_int32_t datalen = tcplen - tcph->doff*4;
6777 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
6778 +       u_int32_t newip;
6779 +       u_int16_t port;
6780 +       int i;
6781 +
6782 +       MUST_BE_LOCKED(&ip_h323_lock);
6783 +
6784 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
6785 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6786 +                       ? "yes" : "no",
6787 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6788 +                       ? "yes" : "no");
6789 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6790 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6791 +               return 1;
6792 +
6793 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
6794 +               info->offset[IP_CT_DIR_ORIGINAL], 
6795 +               info->offset[IP_CT_DIR_REPLY],
6796 +               tcplen);
6797 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6798 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6799 +
6800 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
6801 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
6802 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6803 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6804 +               if (!between(info->seq[i], ntohl(tcph->seq), 
6805 +                            ntohl(tcph->seq) + datalen))
6806 +                       continue;
6807 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6808 +                            ntohl(tcph->seq) + datalen)) {
6809 +                       /* Partial retransmisison. It's a cracker being funky. */
6810 +                       if (net_ratelimit()) {
6811 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6812 +                                    info->seq[i],
6813 +                                    ntohl(tcph->seq),
6814 +                                    ntohl(tcph->seq) + datalen);
6815 +                       }
6816 +                       return 0;
6817 +               }
6818 +
6819 +               /* Change address inside packet to match way we're mapping
6820 +                  this connection. */
6821 +               if (i == IP_CT_DIR_ORIGINAL) {
6822 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6823 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6824 +               } else {
6825 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
6826 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6827 +               }
6828 +
6829 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
6830 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6831 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6832 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6833 +
6834 +               /* Modify the packet */
6835 +               *(u_int32_t *)(data + info->offset[i]) = newip;
6836 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
6837 +       
6838 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
6839 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6840 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6841 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6842 +       }
6843 +
6844 +       /* fix checksum information */
6845 +
6846 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6847 +                                    datalen, 0);
6848 +
6849 +       tcph->check = 0;
6850 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6851 +                                  csum_partial((char *)tcph, tcph->doff*4,
6852 +                                          (*pskb)->csum));
6853 +       ip_send_check(iph);
6854 +
6855 +       return 1;
6856 +}
6857 +
6858 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6859 +                          struct ip_conntrack *ct,
6860 +                          struct sk_buff **pskb,
6861 +                          enum ip_conntrack_info ctinfo,
6862 +                          struct ip_conntrack_expect *expect)
6863 +{
6864 +       u_int32_t newip;
6865 +       u_int16_t port;
6866 +       struct ip_conntrack_tuple newtuple;
6867 +       struct iphdr *iph = (*pskb)->nh.iph;
6868 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6869 +       char *data = (char *) tcph + tcph->doff * 4;
6870 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6871 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6872 +       int is_h225;
6873 +
6874 +       MUST_BE_LOCKED(&ip_h323_lock);
6875 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6876 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6877 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6878 +
6879 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
6880 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6881 +               /* Partial retransmisison. It's a cracker being funky. */
6882 +               if (net_ratelimit()) {
6883 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6884 +                            expect->seq,
6885 +                            ntohl(tcph->seq),
6886 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6887 +               }
6888 +               return 0;
6889 +       }
6890 +
6891 +       /* Change address inside packet to match way we're mapping
6892 +          this connection. */
6893 +       if (info->dir == IP_CT_DIR_REPLY) {
6894 +               /* Must be where client thinks server is */
6895 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6896 +               /* Expect something from client->server */
6897 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6898 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6899 +       } else {
6900 +               /* Must be where server thinks client is */
6901 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6902 +               /* Expect something from server->client */
6903 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6904 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6905 +       }
6906 +
6907 +       is_h225 = (master_info->is_h225 == H225_PORT);
6908 +
6909 +       if (is_h225) {
6910 +               newtuple.dst.protonum = IPPROTO_TCP;
6911 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6912 +       } else {
6913 +               newtuple.dst.protonum = IPPROTO_UDP;
6914 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6915 +       }
6916 +       
6917 +       /* Try to get same port: if not, try to change it. */
6918 +       for (port = ntohs(info->port); port != 0; port++) {
6919 +               if (is_h225)
6920 +                       newtuple.dst.u.tcp.port = htons(port);
6921 +               else
6922 +                       newtuple.dst.u.udp.port = htons(port);
6923 +
6924 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6925 +                       break;
6926 +       }
6927 +       if (port == 0) {
6928 +               DEBUGP("h323_data_fixup: no free port found!\n");
6929 +               return 0;
6930 +       }
6931 +
6932 +       port = htons(port);
6933 +
6934 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
6935 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6936 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6937 +
6938 +       /* Modify the packet */
6939 +       *(u_int32_t *)(data + info->offset) = newip;
6940 +       *(u_int16_t *)(data + info->offset + 4) = port;
6941 +       
6942 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
6943 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6944 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6945 +
6946 +       /* fix checksum information  */
6947 +       /* FIXME: usually repeated multiple times in the case of H.245! */
6948 +
6949 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6950 +                                    tcplen - tcph->doff*4, 0);
6951 +
6952 +       tcph->check = 0;
6953 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6954 +                                  csum_partial((char *)tcph, tcph->doff*4,
6955 +                                          (*pskb)->csum));
6956 +       ip_send_check(iph);
6957 +
6958 +       return 1;
6959 +}
6960 +
6961 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6962 +                                 struct ip_conntrack_expect *exp,
6963 +                                 struct ip_nat_info *info,
6964 +                                 enum ip_conntrack_info ctinfo,
6965 +                                 unsigned int hooknum,
6966 +                                 struct sk_buff **pskb)
6967 +{
6968 +       int dir;
6969 +       struct ip_ct_h225_expect *exp_info;
6970 +       
6971 +       /* Only mangle things once: original direction in POST_ROUTING
6972 +          and reply direction on PRE_ROUTING. */
6973 +       dir = CTINFO2DIR(ctinfo);
6974 +       DEBUGP("nat_h323: dir %s at hook %s\n",
6975 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6976 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6977 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6978 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6979 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6980 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6981 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6982 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6983 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6984 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6985 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6986 +               return NF_ACCEPT;
6987 +       }
6988 +
6989 +       if (!exp) {
6990 +               LOCK_BH(&ip_h323_lock);
6991 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6992 +                       UNLOCK_BH(&ip_h323_lock);
6993 +                       return NF_DROP;
6994 +               }
6995 +               UNLOCK_BH(&ip_h323_lock);
6996 +               return NF_ACCEPT;
6997 +       }
6998 +               
6999 +       exp_info = &exp->help.exp_h225_info;
7000 +
7001 +       LOCK_BH(&ip_h323_lock);
7002 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
7003 +               UNLOCK_BH(&ip_h323_lock);
7004 +               return NF_DROP;
7005 +       }
7006 +       UNLOCK_BH(&ip_h323_lock);
7007 +
7008 +       return NF_ACCEPT;
7009 +}
7010 +
7011 +static struct ip_nat_helper h225 = 
7012 +       { { NULL, NULL },
7013 +         "H.225",                                      /* name */
7014 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
7015 +         THIS_MODULE,                                  /* module */
7016 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
7017 +           { 0, { 0 }, IPPROTO_TCP } },
7018 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
7019 +           { 0, { 0 }, 0xFFFF } },
7020 +         h225_nat_help,                                /* helper */
7021 +         h225_nat_expected                             /* expectfn */
7022 +       };
7023 +
7024 +static int __init init(void)
7025 +{
7026 +       int ret;
7027 +       
7028 +       ret = ip_nat_helper_register(&h225);
7029 +
7030 +       if (ret != 0)
7031 +               printk("ip_nat_h323: cannot initialize the module!\n");
7032 +
7033 +       return ret;
7034 +}
7035 +
7036 +static void __exit fini(void)
7037 +{
7038 +       ip_nat_helper_unregister(&h225);
7039 +}
7040 +
7041 +module_init(init);
7042 +module_exit(fini);
7043 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.7/net/ipv4/netfilter/ip_nat_mms.c
7044 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_mms.c     1970-01-01 01:00:00.000000000 +0100
7045 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_mms.c 2004-06-25 12:23:10.837501416 +0200
7046 @@ -0,0 +1,350 @@
7047 +/* MMS extension for TCP NAT alteration.
7048 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7049 + * based on ip_nat_ftp.c and ip_nat_irc.c
7050 + *
7051 + * ip_nat_mms.c v0.3 2002-09-22
7052 + *
7053 + *      This program is free software; you can redistribute it and/or
7054 + *      modify it under the terms of the GNU General Public License
7055 + *      as published by the Free Software Foundation; either version
7056 + *      2 of the License, or (at your option) any later version.
7057 + *
7058 + *      Module load syntax:
7059 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
7060 + *
7061 + *      Please give the ports of all MMS servers You wish to connect to.
7062 + *      If you don't specify ports, the default will be TCP port 1755.
7063 + *
7064 + *      More info on MMS protocol, firewalls and NAT:
7065 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
7066 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
7067 + *
7068 + *      The SDP project people are reverse-engineering MMS:
7069 + *      http://get.to/sdp
7070 + */
7071 +
7072 +/* FIXME: issue with UDP & fragmentation with this URL: 
7073 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
7074 +   may be related to out-of-order first packets:
7075 +   basically the expectation is set up correctly, then the server sends
7076 +   a first UDP packet which is fragmented plus arrives out-of-order.
7077 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
7078 +   an ICMP unreachable back to the server */
7079 +
7080 +#include <linux/module.h>
7081 +#include <linux/netfilter_ipv4.h>
7082 +#include <linux/ip.h>
7083 +#include <linux/tcp.h>
7084 +#include <net/tcp.h>
7085 +#include <linux/netfilter_ipv4/ip_nat.h>
7086 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7087 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7088 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
7089 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7090 +
7091 +#if 0 
7092 +#define DEBUGP printk
7093 +#define DUMP_BYTES(address, counter)                                \
7094 +({                                                                  \
7095 +       int temp_counter;                                           \
7096 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
7097 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
7098 +       };                                                          \
7099 +       DEBUGP("\n");                                               \
7100 +})
7101 +#else
7102 +#define DEBUGP(format, args...)
7103 +#define DUMP_BYTES(address, counter)
7104 +#endif
7105 +
7106 +#define MAX_PORTS 8
7107 +static int ports[MAX_PORTS];
7108 +static int ports_c = 0;
7109 +
7110 +#ifdef MODULE_PARM
7111 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7112 +#endif
7113 +
7114 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7115 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
7116 +MODULE_LICENSE("GPL");
7117 +
7118 +DECLARE_LOCK_EXTERN(ip_mms_lock);
7119 +
7120 +/* FIXME: Time out? --RR */
7121 +
7122 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
7123 +                          struct ip_conntrack *ct,
7124 +                          struct sk_buff **pskb,
7125 +                          enum ip_conntrack_info ctinfo,
7126 +                          struct ip_conntrack_expect *expect)
7127 +{
7128 +       u_int32_t newip;
7129 +       struct ip_conntrack_tuple t;
7130 +       struct iphdr *iph = (*pskb)->nh.iph;
7131 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
7132 +       char *data = (char *)tcph + tcph->doff * 4;
7133 +       int i, j, k, port;
7134 +       u_int16_t mms_proto;
7135 +
7136 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
7137 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
7138 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
7139 +
7140 +       int zero_padding;
7141 +
7142 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
7143 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
7144 +       char proto_string[6];
7145 +       
7146 +       MUST_BE_LOCKED(&ip_mms_lock);
7147 +
7148 +       /* what was the protocol again ? */
7149 +       mms_proto = expect->tuple.dst.protonum;
7150 +       sprintf(proto_string, "%u", mms_proto);
7151 +       
7152 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
7153 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
7154 +              mms_proto == IPPROTO_UDP ? "UDP"
7155 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
7156 +       
7157 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7158 +
7159 +       /* Alter conntrack's expectations. */
7160 +       t = expect->tuple;
7161 +       t.dst.ip = newip;
7162 +       for (port = ct_mms_info->port; port != 0; port++) {
7163 +               t.dst.u.tcp.port = htons(port);
7164 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
7165 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
7166 +                       break;
7167 +               }
7168 +       }
7169 +       
7170 +       if(port == 0)
7171 +               return 0;
7172 +
7173 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
7174 +               NIPQUAD(newip),
7175 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
7176 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
7177 +               port);
7178 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
7179 +       
7180 +       memset(unicode_buffer, 0, sizeof(char)*75);
7181 +
7182 +       for (i=0; i<strlen(buffer); ++i)
7183 +               *(unicode_buffer+i*2)=*(buffer+i);
7184 +       
7185 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
7186 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
7187 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
7188 +       
7189 +       /* add end of packet to it */
7190 +       for (j=0; j<ct_mms_info->padding; ++j) {
7191 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
7192 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
7193 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
7194 +       }
7195 +
7196 +       /* pad with zeroes at the end ? see explanation of weird math below */
7197 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
7198 +       for (k=0; k<zero_padding; ++k)
7199 +               *(unicode_buffer+i*2+j+k)= (char)0;
7200 +       
7201 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
7202 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
7203 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
7204 +       
7205 +       /* explanation, before I forget what I did:
7206 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
7207 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
7208 +          but note that things may have to be padded with zeroes to align by 8 
7209 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
7210 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
7211 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
7212 +       *mms_messageLength = *mms_chunkLenLV*8;
7213 +       
7214 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
7215 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
7216 +       
7217 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
7218 +                                expect->seq - ntohl(tcph->seq),
7219 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
7220 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
7221 +       DUMP_BYTES(unicode_buffer, 60);
7222 +       
7223 +       return 1;
7224 +}
7225 +
7226 +static unsigned int
7227 +mms_nat_expected(struct sk_buff **pskb,
7228 +                 unsigned int hooknum,
7229 +                 struct ip_conntrack *ct,
7230 +                 struct ip_nat_info *info)
7231 +{
7232 +       struct ip_nat_multi_range mr;
7233 +       u_int32_t newdstip, newsrcip, newip;
7234 +
7235 +       struct ip_conntrack *master = master_ct(ct);
7236 +
7237 +       IP_NF_ASSERT(info);
7238 +       IP_NF_ASSERT(master);
7239 +
7240 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7241 +
7242 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
7243 +
7244 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7245 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7246 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
7247 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7248 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7249 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7250 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
7251 +
7252 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7253 +               newip = newsrcip;
7254 +       else
7255 +               newip = newdstip;
7256 +
7257 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
7258 +
7259 +       mr.rangesize = 1;
7260 +       /* We don't want to manip the per-protocol, just the IPs. */
7261 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7262 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
7263 +
7264 +       return ip_nat_setup_info(ct, &mr, hooknum);
7265 +}
7266 +
7267 +
7268 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
7269 +                        struct ip_conntrack_expect *exp,
7270 +                        struct ip_nat_info *info,
7271 +                        enum ip_conntrack_info ctinfo,
7272 +                        unsigned int hooknum,
7273 +                        struct sk_buff **pskb)
7274 +{
7275 +       struct iphdr *iph = (*pskb)->nh.iph;
7276 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
7277 +       unsigned int datalen;
7278 +       int dir;
7279 +       struct ip_ct_mms_expect *ct_mms_info;
7280 +
7281 +       if (!exp)
7282 +               DEBUGP("ip_nat_mms: no exp!!");
7283 +
7284 +       ct_mms_info = &exp->help.exp_mms_info;
7285 +       
7286 +       /* Only mangle things once: original direction in POST_ROUTING
7287 +          and reply direction on PRE_ROUTING. */
7288 +       dir = CTINFO2DIR(ctinfo);
7289 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7290 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7291 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
7292 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7293 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7294 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7295 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7296 +               return NF_ACCEPT;
7297 +       }
7298 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
7299 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7300 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7301 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7302 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7303 +       
7304 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7305 +       
7306 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
7307 +              exp->seq + ct_mms_info->len,
7308 +              ntohl(tcph->seq),
7309 +              ntohl(tcph->seq) + datalen);
7310 +       
7311 +       LOCK_BH(&ip_mms_lock);
7312 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
7313 +       if (between(exp->seq + ct_mms_info->len,
7314 +           ntohl(tcph->seq),
7315 +           ntohl(tcph->seq) + datalen)) {
7316 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
7317 +                       UNLOCK_BH(&ip_mms_lock);
7318 +                       return NF_DROP;
7319 +               }
7320 +       } else {
7321 +               /* Half a match?  This means a partial retransmisison.
7322 +                  It's a cracker being funky. */
7323 +               if (net_ratelimit()) {
7324 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
7325 +                              exp->seq, ct_mms_info->len,
7326 +                              ntohl(tcph->seq),
7327 +                              ntohl(tcph->seq) + datalen);
7328 +               }
7329 +               UNLOCK_BH(&ip_mms_lock);
7330 +               return NF_DROP;
7331 +       }
7332 +       UNLOCK_BH(&ip_mms_lock);
7333 +       
7334 +       return NF_ACCEPT;
7335 +}
7336 +
7337 +static struct ip_nat_helper mms[MAX_PORTS];
7338 +static char mms_names[MAX_PORTS][10];
7339 +
7340 +/* Not __exit: called from init() */
7341 +static void fini(void)
7342 +{
7343 +       int i;
7344 +
7345 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7346 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
7347 +               ip_nat_helper_unregister(&mms[i]);
7348 +       }
7349 +}
7350 +
7351 +static int __init init(void)
7352 +{
7353 +       int i, ret = 0;
7354 +       char *tmpname;
7355 +
7356 +       if (ports[0] == 0)
7357 +               ports[0] = MMS_PORT;
7358 +
7359 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7360 +
7361 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
7362 +
7363 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
7364 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
7365 +               mms[i].mask.dst.protonum = 0xFFFF;
7366 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
7367 +               mms[i].help = mms_nat_help;
7368 +               mms[i].me = THIS_MODULE;
7369 +               mms[i].flags = 0;
7370 +               mms[i].expect = mms_nat_expected;
7371 +
7372 +               tmpname = &mms_names[i][0];
7373 +               if (ports[i] == MMS_PORT)
7374 +                       sprintf(tmpname, "mms");
7375 +               else
7376 +                       sprintf(tmpname, "mms-%d", i);
7377 +               mms[i].name = tmpname;
7378 +
7379 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
7380 +                               ports[i]);
7381 +               ret = ip_nat_helper_register(&mms[i]);
7382 +
7383 +               if (ret) {
7384 +                       printk("ip_nat_mms: error registering "
7385 +                              "helper for port %d\n", ports[i]);
7386 +                       fini();
7387 +                       return ret;
7388 +               }
7389 +               ports_c++;
7390 +       }
7391 +
7392 +       return ret;
7393 +}
7394 +
7395 +module_init(init);
7396 +module_exit(fini);
7397 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.7/net/ipv4/netfilter/ip_nat_quake3.c
7398 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_quake3.c  1970-01-01 01:00:00.000000000 +0100
7399 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_quake3.c      2004-06-25 12:24:42.551558760 +0200
7400 @@ -0,0 +1,249 @@
7401 +/* Quake3 extension for UDP NAT alteration.
7402 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7403 + * based on ip_nat_ftp.c and ip_nat_tftp.c
7404 + *
7405 + * ip_nat_quake3.c v0.0.3 2002-08-31
7406 + *
7407 + *      This program is free software; you can redistribute it and/or
7408 + *      modify it under the terms of the GNU General Public License
7409 + *      as published by the Free Software Foundation; either version
7410 + *      2 of the License, or (at your option) any later version.
7411 + *
7412 + *      Module load syntax:
7413 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
7414 + *
7415 + *      please give the ports of all Quake3 master servers You wish to
7416 + *      connect to. If you don't specify ports, the default will be UDP
7417 + *      port 27950.
7418 + *
7419 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
7420 + *
7421 + *      Notes: 
7422 + *      - If you're one of those people who would try anything to lower
7423 + *        latency while playing Quake (and who isn't :-) ), you may want to
7424 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
7425 + *        outgoing UDP traffic.
7426 + *        This will make ip_conntrack_quake3 add the necessary expectations,
7427 + *        but there will be no overhead for client->server UDP streams. If
7428 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
7429 + *        hook for every packet in the client->server UDP stream.
7430 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
7431 + *        The IP addresses in the master connection payload (=IP addresses
7432 + *        of Quake servers) have no relation with the master server so
7433 + *        DNAT'ing the master connection to a server should not change the
7434 + *        expected connections.
7435 + *      - Not tested due to lack of equipment:
7436 + *        - multiple Quake3 clients behind one MASQUERADE gateway
7437 + *        - what if Quake3 client is running on router too
7438 + */
7439 +
7440 +#include <linux/module.h>
7441 +#include <linux/netfilter_ipv4.h>
7442 +#include <linux/ip.h>
7443 +#include <linux/udp.h>
7444 +
7445 +#include <linux/netfilter.h>
7446 +#include <linux/netfilter_ipv4/ip_tables.h>
7447 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7448 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
7449 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7450 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7451 +
7452 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7453 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
7454 +MODULE_LICENSE("GPL");
7455 +
7456 +#define MAX_PORTS 8
7457 +
7458 +static int ports[MAX_PORTS];
7459 +static int ports_c = 0;
7460 +#ifdef MODULE_PARM
7461 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7462 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7463 +#endif
7464 +
7465 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7466 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7467 +#if 0 
7468 +#define DEBUGP printk
7469 +#else
7470 +#define DEBUGP(format, args...)
7471 +#endif
7472 +
7473 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7474 +
7475 +static unsigned int 
7476 +quake3_nat_help(struct ip_conntrack *ct,
7477 +                struct ip_conntrack_expect *exp,
7478 +                struct ip_nat_info *info,
7479 +                enum ip_conntrack_info ctinfo,
7480 +                unsigned int hooknum,
7481 +                struct sk_buff **pskb)
7482 +{
7483 +       struct iphdr *iph = (*pskb)->nh.iph;
7484 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7485 +       struct ip_conntrack_tuple repl;
7486 +       int dir = CTINFO2DIR(ctinfo);
7487 +       int i;
7488 +       
7489 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7490 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7491 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7492 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7493 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7494 +             );
7495 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7496 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7497 +       
7498 +       /* Only mangle things once: original direction in POST_ROUTING
7499 +          and reply direction on PRE_ROUTING. */
7500 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7501 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7502 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7503 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7504 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7505 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7506 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7507 +               return NF_ACCEPT;
7508 +       }
7509 +
7510 +       if (!exp) {
7511 +               DEBUGP("no conntrack expectation to modify\n");
7512 +               return NF_ACCEPT;
7513 +       }
7514 +
7515 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7516 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7517 +                   i+6 < ntohs(udph->len);
7518 +                   i+=7) {
7519 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
7520 +                              i, ntohs(udph->len),
7521 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7522 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7523 +                       
7524 +                       memset(&repl, 0, sizeof(repl));
7525 +
7526 +                       repl.dst.protonum = IPPROTO_UDP;
7527 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7528 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7529 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
7530 +                       
7531 +                       ip_conntrack_change_expect(exp, &repl);
7532 +               }
7533 +       }
7534 +       return NF_ACCEPT;
7535 +}
7536 +
7537 +static unsigned int 
7538 +quake3_nat_expected(struct sk_buff **pskb,
7539 +                    unsigned int hooknum,
7540 +                    struct ip_conntrack *ct, 
7541 +                    struct ip_nat_info *info) 
7542 +{
7543 +       const struct ip_conntrack *master = ct->master->expectant;
7544 +       struct ip_nat_multi_range mr;
7545 +       u_int32_t newsrcip, newdstip, newip;
7546 +#if 0 
7547 +       const struct ip_conntrack_tuple *repl =
7548 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7549 +       struct iphdr *iph = (*pskb)->nh.iph;
7550 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
7551 +#endif
7552 +
7553 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7554 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7555 +
7556 +       IP_NF_ASSERT(info);
7557 +       IP_NF_ASSERT(master);
7558 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7559 +       
7560 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7561 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7562 +       
7563 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7564 +               newip = newsrcip;
7565 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7566 +                      "newsrc: %u.%u.%u.%u\n",
7567 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7568 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7569 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7570 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7571 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7572 +                      NIPQUAD(newip));
7573 +               
7574 +       } else {
7575 +               newip = newdstip;
7576 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7577 +                      "newdst: %u.%u.%u.%u\n",
7578 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7579 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7580 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7581 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7582 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7583 +                      NIPQUAD(newip));
7584 +       }
7585 +       
7586 +       mr.rangesize = 1;
7587 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7588 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
7589 +
7590 +       return ip_nat_setup_info(ct,&mr,hooknum);
7591 +}
7592 +
7593 +static struct ip_nat_helper quake3[MAX_PORTS];
7594 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
7595 +
7596 +static void fini(void)
7597 +{
7598 +       int i;
7599 +       
7600 +       for (i = 0 ; i < ports_c; i++) {
7601 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7602 +                      ip_nat_helper_unregister(&quake3[i]);
7603 +       }
7604 +}
7605 +
7606 +static int __init init(void)
7607 +       {
7608 +               int i, ret = 0;
7609 +               char *tmpname;
7610 +
7611 +               if (!ports[0])
7612 +                       ports[0] = QUAKE3_MASTER_PORT;
7613 +               
7614 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7615 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7616 +
7617 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7618 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7619 +                       quake3[i].mask.dst.protonum = 0xFFFF;
7620 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
7621 +                       quake3[i].help = quake3_nat_help;
7622 +                       quake3[i].flags = 0;
7623 +                       quake3[i].me = THIS_MODULE;
7624 +                       quake3[i].expect = quake3_nat_expected;
7625 +                       
7626 +                       tmpname = &quake3_names[i][0];
7627 +                       if (ports[i] == QUAKE3_MASTER_PORT)
7628 +                               sprintf(tmpname, "quake3");
7629 +                       else
7630 +                               sprintf(tmpname, "quake3-%d", i);
7631 +                       quake3[i].name = tmpname;
7632 +                       
7633 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7634 +                              ports[i], quake3[i].name);
7635 +                       ret = ip_nat_helper_register(&quake3[i]);
7636 +                       
7637 +                       if (ret) {
7638 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
7639 +                                      ports[i]);
7640 +                               fini();
7641 +                               return ret;
7642 +                       }
7643 +                       ports_c++;
7644 +               }
7645 +               return ret;
7646 +       }
7647 +       
7648 +module_init(init);
7649 +module_exit(fini);
7650 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.7/net/ipv4/netfilter/ip_nat_rtsp.c
7651 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_rtsp.c    1970-01-01 01:00:00.000000000 +0100
7652 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_rtsp.c        2004-06-25 12:24:50.035421040 +0200
7653 @@ -0,0 +1,621 @@
7654 +/*
7655 + * RTSP extension for TCP NAT alteration
7656 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7657 + * based on ip_nat_irc.c
7658 + *
7659 + *      This program is free software; you can redistribute it and/or
7660 + *      modify it under the terms of the GNU General Public License
7661 + *      as published by the Free Software Foundation; either version
7662 + *      2 of the License, or (at your option) any later version.
7663 + *
7664 + * Module load syntax:
7665 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7666 + *                           stunaddr=<address>
7667 + *                           destaction=[auto|strip|none]
7668 + *
7669 + * If no ports are specified, the default will be port 554 only.
7670 + *
7671 + * stunaddr specifies the address used to detect that a client is using STUN.
7672 + * If this address is seen in the destination parameter, it is assumed that
7673 + * the client has already punched a UDP hole in the firewall, so we don't
7674 + * mangle the client_port.  If none is specified, it is autodetected.  It
7675 + * only needs to be set if you have multiple levels of NAT.  It should be
7676 + * set to the external address that the STUN clients detect.  Note that in
7677 + * this case, it will not be possible for clients to use UDP with servers
7678 + * between the NATs.
7679 + *
7680 + * If no destaction is specified, auto is used.
7681 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
7682 + *   destaction=strip: always strip destination parameter (not recommended).
7683 + *   destaction=none:  do not touch destination parameter (not recommended).
7684 + */
7685 +
7686 +#include <linux/module.h>
7687 +#include <linux/netfilter_ipv4.h>
7688 +#include <linux/ip.h>
7689 +#include <linux/tcp.h>
7690 +#include <linux/kernel.h>
7691 +#include <net/tcp.h>
7692 +#include <linux/netfilter_ipv4/ip_nat.h>
7693 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7694 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7695 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7696 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7697 +
7698 +#include <linux/inet.h>
7699 +#include <linux/ctype.h>
7700 +#define NF_NEED_STRNCASECMP
7701 +#define NF_NEED_STRTOU16
7702 +#include <linux/netfilter_helpers.h>
7703 +#define NF_NEED_MIME_NEXTLINE
7704 +#include <linux/netfilter_mime.h>
7705 +
7706 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7707 +#ifdef IP_NF_RTSP_DEBUG
7708 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7709 +#else
7710 +#define DEBUGP(fmt, args...)
7711 +#endif
7712 +
7713 +#define MAX_PORTS       8
7714 +#define DSTACT_AUTO     0
7715 +#define DSTACT_STRIP    1
7716 +#define DSTACT_NONE     2
7717 +
7718 +static int      ports[MAX_PORTS];
7719 +static char*    stunaddr = NULL;
7720 +static char*    destaction = NULL;
7721 +
7722 +static int       num_ports = 0;
7723 +static u_int32_t extip = 0;
7724 +static int       dstact = 0;
7725 +
7726 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7727 +MODULE_DESCRIPTION("RTSP network address translation module");
7728 +MODULE_LICENSE("GPL");
7729 +#ifdef MODULE_PARM
7730 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7731 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7732 +MODULE_PARM(stunaddr, "s");
7733 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7734 +MODULE_PARM(destaction, "s");
7735 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7736 +#endif
7737 +
7738 +/* protects rtsp part of conntracks */
7739 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7740 +
7741 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7742 +
7743 +/*** helper functions ***/
7744 +
7745 +static void
7746 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7747 +{
7748 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
7749 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7750 +
7751 +    *pptcpdata = (char*)tcph + tcph->doff*4;
7752 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7753 +}
7754 +
7755 +/*** nat functions ***/
7756 +
7757 +/*
7758 + * Mangle the "Transport:" header:
7759 + *   - Replace all occurences of "client_port=<spec>"
7760 + *   - Handle destination parameter
7761 + *
7762 + * In:
7763 + *   ct, ctinfo = conntrack context
7764 + *   pskb       = packet
7765 + *   tranoff    = Transport header offset from TCP data
7766 + *   tranlen    = Transport header length (incl. CRLF)
7767 + *   rport_lo   = replacement low  port (host endian)
7768 + *   rport_hi   = replacement high port (host endian)
7769 + *
7770 + * Returns packet size difference.
7771 + *
7772 + * Assumes that a complete transport header is present, ending with CR or LF
7773 + */
7774 +static int
7775 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7776 +                 struct ip_conntrack_expect* exp,
7777 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
7778 +{
7779 +    char*       ptcp;
7780 +    uint        tcplen;
7781 +    char*       ptran;
7782 +    char        rbuf1[16];      /* Replacement buffer (one port) */
7783 +    uint        rbuf1len;       /* Replacement len (one port) */
7784 +    char        rbufa[16];      /* Replacement buffer (all ports) */
7785 +    uint        rbufalen;       /* Replacement len (all ports) */
7786 +    u_int32_t   newip;
7787 +    u_int16_t   loport, hiport;
7788 +    uint        off = 0;
7789 +    uint        diff;           /* Number of bytes we removed */
7790 +
7791 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7792 +    struct ip_conntrack_tuple t;
7793 +
7794 +    char    szextaddr[15+1];
7795 +    uint    extaddrlen;
7796 +    int     is_stun;
7797 +
7798 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7799 +    ptran = ptcp+tranoff;
7800 +
7801 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7802 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7803 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
7804 +    {
7805 +        INFOP("sanity check failed\n");
7806 +        return 0;
7807 +    }
7808 +    off += 10;
7809 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7810 +
7811 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7812 +    t = exp->tuple;
7813 +    t.dst.ip = newip;
7814 +
7815 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7816 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7817 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7818 +
7819 +    rbuf1len = rbufalen = 0;
7820 +    switch (prtspexp->pbtype)
7821 +    {
7822 +    case pb_single:
7823 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7824 +        {
7825 +            t.dst.u.udp.port = htons(loport);
7826 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7827 +            {
7828 +                DEBUGP("using port %hu\n", loport);
7829 +                break;
7830 +            }
7831 +        }
7832 +        if (loport != 0)
7833 +        {
7834 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7835 +            rbufalen = sprintf(rbufa, "%hu", loport);
7836 +        }
7837 +        break;
7838 +    case pb_range:
7839 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7840 +        {
7841 +            t.dst.u.udp.port = htons(loport);
7842 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7843 +            {
7844 +                hiport = loport + ~exp->mask.dst.u.udp.port;
7845 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
7846 +                break;
7847 +            }
7848 +        }
7849 +        if (loport != 0)
7850 +        {
7851 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7852 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7853 +        }
7854 +        break;
7855 +    case pb_discon:
7856 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7857 +        {
7858 +            t.dst.u.udp.port = htons(loport);
7859 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7860 +            {
7861 +                DEBUGP("using port %hu (1 of 2)\n", loport);
7862 +                break;
7863 +            }
7864 +        }
7865 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7866 +        {
7867 +            t.dst.u.udp.port = htons(hiport);
7868 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7869 +            {
7870 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
7871 +                break;
7872 +            }
7873 +        }
7874 +        if (loport != 0 && hiport != 0)
7875 +        {
7876 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7877 +            if (hiport == loport+1)
7878 +            {
7879 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7880 +            }
7881 +            else
7882 +            {
7883 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7884 +            }
7885 +        }
7886 +        break;
7887 +    }
7888 +
7889 +    if (rbuf1len == 0)
7890 +    {
7891 +        return 0;   /* cannot get replacement port(s) */
7892 +    }
7893 +
7894 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
7895 +    while (off < tranlen)
7896 +    {
7897 +        uint        saveoff;
7898 +        const char* pparamend;
7899 +        uint        nextparamoff;
7900 +
7901 +        pparamend = memchr(ptran+off, ',', tranlen-off);
7902 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7903 +        nextparamoff = pparamend-ptcp;
7904 +
7905 +        /*
7906 +         * We pass over each param twice.  On the first pass, we look for a
7907 +         * destination= field.  It is handled by the security policy.  If it
7908 +         * is present, allowed, and equal to our external address, we assume
7909 +         * that STUN is being used and we leave the client_port= field alone.
7910 +         */
7911 +        is_stun = 0;
7912 +        saveoff = off;
7913 +        while (off < nextparamoff)
7914 +        {
7915 +            const char* pfieldend;
7916 +            uint        nextfieldoff;
7917 +
7918 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7919 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7920 +
7921 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7922 +            {
7923 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7924 +                {
7925 +                    is_stun = 1;
7926 +                }
7927 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7928 +                {
7929 +                    diff = nextfieldoff-off;
7930 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7931 +                                                         off, diff, NULL, 0))
7932 +                    {
7933 +                        /* mangle failed, all we can do is bail */
7934 +                        return 0;
7935 +                    }
7936 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7937 +                    ptran = ptcp+tranoff;
7938 +                    tranlen -= diff;
7939 +                    nextparamoff -= diff;
7940 +                    nextfieldoff -= diff;
7941 +                }
7942 +            }
7943 +
7944 +            off = nextfieldoff;
7945 +        }
7946 +        if (is_stun)
7947 +        {
7948 +            continue;
7949 +        }
7950 +        off = saveoff;
7951 +        while (off < nextparamoff)
7952 +        {
7953 +            const char* pfieldend;
7954 +            uint        nextfieldoff;
7955 +
7956 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7957 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7958 +
7959 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
7960 +            {
7961 +                u_int16_t   port;
7962 +                uint        numlen;
7963 +                uint        origoff;
7964 +                uint        origlen;
7965 +                char*       rbuf    = rbuf1;
7966 +                uint        rbuflen = rbuf1len;
7967 +
7968 +                off += 12;
7969 +                origoff = (ptran-ptcp)+off;
7970 +                origlen = 0;
7971 +                numlen = nf_strtou16(ptran+off, &port);
7972 +                off += numlen;
7973 +                origlen += numlen;
7974 +                if (port != prtspexp->loport)
7975 +                {
7976 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
7977 +                }
7978 +                else
7979 +                {
7980 +                    if (ptran[off] == '-' || ptran[off] == '/')
7981 +                    {
7982 +                        off++;
7983 +                        origlen++;
7984 +                        numlen = nf_strtou16(ptran+off, &port);
7985 +                        off += numlen;
7986 +                        origlen += numlen;
7987 +                        rbuf = rbufa;
7988 +                        rbuflen = rbufalen;
7989 +                    }
7990 +
7991 +                    /*
7992 +                     * note we cannot just memcpy() if the sizes are the same.
7993 +                     * the mangle function does skb resizing, checks for a
7994 +                     * cloned skb, and updates the checksums.
7995 +                     *
7996 +                     * parameter 4 below is offset from start of tcp data.
7997 +                     */
7998 +                    diff = origlen-rbuflen;
7999 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
8000 +                                              origoff, origlen, rbuf, rbuflen))
8001 +                    {
8002 +                        /* mangle failed, all we can do is bail */
8003 +                        return 0;
8004 +                    }
8005 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
8006 +                    ptran = ptcp+tranoff;
8007 +                    tranlen -= diff;
8008 +                    nextparamoff -= diff;
8009 +                    nextfieldoff -= diff;
8010 +                }
8011 +            }
8012 +
8013 +            off = nextfieldoff;
8014 +        }
8015 +
8016 +        off = nextparamoff;
8017 +    }
8018 +
8019 +    return 1;
8020 +}
8021 +
8022 +static unsigned int
8023 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
8024 +{
8025 +    struct ip_nat_multi_range mr;
8026 +    u_int32_t newdstip, newsrcip, newip;
8027 +
8028 +    struct ip_conntrack *master = master_ct(ct);
8029 +
8030 +    IP_NF_ASSERT(info);
8031 +    IP_NF_ASSERT(master);
8032 +
8033 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8034 +
8035 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8036 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8037 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
8038 +
8039 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
8040 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
8041 +
8042 +    mr.rangesize = 1;
8043 +    /* We don't want to manip the per-protocol, just the IPs. */
8044 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8045 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
8046 +
8047 +    return ip_nat_setup_info(ct, &mr, hooknum);
8048 +}
8049 +
8050 +static uint
8051 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
8052 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
8053 +{
8054 +    char*   ptcp;
8055 +    uint    tcplen;
8056 +    uint    hdrsoff;
8057 +    uint    hdrslen;
8058 +    uint    lineoff;
8059 +    uint    linelen;
8060 +    uint    off;
8061 +
8062 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
8063 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
8064 +
8065 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
8066 +
8067 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
8068 +
8069 +    hdrsoff = exp->seq - ntohl(tcph->seq);
8070 +    hdrslen = prtspexp->len;
8071 +    off = hdrsoff;
8072 +
8073 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
8074 +    {
8075 +        if (linelen == 0)
8076 +        {
8077 +            break;
8078 +        }
8079 +        if (off > hdrsoff+hdrslen)
8080 +        {
8081 +            INFOP("!! overrun !!");
8082 +            break;
8083 +        }
8084 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
8085 +
8086 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
8087 +        {
8088 +            uint oldtcplen = tcplen;
8089 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
8090 +            {
8091 +                break;
8092 +            }
8093 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
8094 +            hdrslen -= (oldtcplen-tcplen);
8095 +            off -= (oldtcplen-tcplen);
8096 +            lineoff -= (oldtcplen-tcplen);
8097 +            linelen -= (oldtcplen-tcplen);
8098 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
8099 +        }
8100 +    }
8101 +
8102 +    return NF_ACCEPT;
8103 +}
8104 +
8105 +static uint
8106 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
8107 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
8108 +{
8109 +    /* XXX: unmangle */
8110 +    return NF_ACCEPT;
8111 +}
8112 +
8113 +static uint
8114 +help(struct ip_conntrack* ct,
8115 +     struct ip_conntrack_expect* exp,
8116 +     struct ip_nat_info* info,
8117 +     enum ip_conntrack_info ctinfo,
8118 +     unsigned int hooknum,
8119 +     struct sk_buff** pskb)
8120 +{
8121 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
8122 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
8123 +    uint datalen;
8124 +    int dir;
8125 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
8126 +    int rc = NF_ACCEPT;
8127 +
8128 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
8129 +    {
8130 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
8131 +        return NF_ACCEPT;
8132 +    }
8133 +
8134 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
8135 +
8136 +    /*
8137 +     * Only mangle things once: original direction in POST_ROUTING
8138 +     * and reply direction on PRE_ROUTING.
8139 +     */
8140 +    dir = CTINFO2DIR(ctinfo);
8141 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8142 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
8143 +    {
8144 +        DEBUGP("Not touching dir %s at hook %s\n",
8145 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8146 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8147 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8148 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8149 +        return NF_ACCEPT;
8150 +    }
8151 +    DEBUGP("got beyond not touching\n");
8152 +
8153 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
8154 +
8155 +    LOCK_BH(&ip_rtsp_lock);
8156 +    /* Ensure the packet contains all of the marked data */
8157 +    if (!between(exp->seq + ct_rtsp_info->len,
8158 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
8159 +    {
8160 +        /* Partial retransmission?  Probably a hacker. */
8161 +        if (net_ratelimit())
8162 +        {
8163 +            INFOP("partial packet %u/%u in %u/%u\n",
8164 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
8165 +        }
8166 +        UNLOCK_BH(&ip_rtsp_lock);
8167 +        return NF_DROP;
8168 +    }
8169 +
8170 +    switch (dir)
8171 +    {
8172 +    case IP_CT_DIR_ORIGINAL:
8173 +        rc = help_out(ct, ctinfo, exp, pskb);
8174 +        break;
8175 +    case IP_CT_DIR_REPLY:
8176 +        rc = help_in(ct, ctinfo, exp, pskb);
8177 +        break;
8178 +    }
8179 +    UNLOCK_BH(&ip_rtsp_lock);
8180 +
8181 +    return rc;
8182 +}
8183 +
8184 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
8185 +static char rtsp_names[MAX_PORTS][10];
8186 +
8187 +/* This function is intentionally _NOT_ defined as  __exit */
8188 +static void
8189 +fini(void)
8190 +{
8191 +    int i;
8192 +
8193 +    for (i = 0; i < num_ports; i++)
8194 +    {
8195 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
8196 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
8197 +    }
8198 +}
8199 +
8200 +static int __init
8201 +init(void)
8202 +{
8203 +    int ret = 0;
8204 +    int i;
8205 +    struct ip_nat_helper* hlpr;
8206 +    char* tmpname;
8207 +
8208 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
8209 +
8210 +    if (ports[0] == 0)
8211 +    {
8212 +        ports[0] = RTSP_PORT;
8213 +    }
8214 +
8215 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
8216 +    {
8217 +        hlpr = &ip_nat_rtsp_helpers[i];
8218 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
8219 +
8220 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
8221 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
8222 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
8223 +        hlpr->mask.dst.protonum = 0xFFFF;
8224 +        hlpr->help = help;
8225 +        hlpr->flags = 0;
8226 +        hlpr->me = THIS_MODULE;
8227 +        hlpr->expect = expected;
8228 +
8229 +        tmpname = &rtsp_names[i][0];
8230 +        if (ports[i] == RTSP_PORT)
8231 +        {
8232 +                sprintf(tmpname, "rtsp");
8233 +        }
8234 +        else
8235 +        {
8236 +                sprintf(tmpname, "rtsp-%d", i);
8237 +        }
8238 +        hlpr->name = tmpname;
8239 +
8240 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
8241 +        ret = ip_nat_helper_register(hlpr);
8242 +
8243 +        if (ret)
8244 +        {
8245 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
8246 +            fini();
8247 +            return 1;
8248 +        }
8249 +        num_ports++;
8250 +    }
8251 +    if (stunaddr != NULL)
8252 +    {
8253 +        extip = in_aton(stunaddr);
8254 +    }
8255 +    if (destaction != NULL)
8256 +    {
8257 +        if (strcmp(destaction, "auto") == 0)
8258 +        {
8259 +            dstact = DSTACT_AUTO;
8260 +        }
8261 +        if (strcmp(destaction, "strip") == 0)
8262 +        {
8263 +            dstact = DSTACT_STRIP;
8264 +        }
8265 +        if (strcmp(destaction, "none") == 0)
8266 +        {
8267 +            dstact = DSTACT_NONE;
8268 +        }
8269 +    }
8270 +    return ret;
8271 +}
8272 +
8273 +module_init(init);
8274 +module_exit(fini);
8275 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.7/net/ipv4/netfilter/ip_nat_standalone.c
8276 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_standalone.c      2004-06-25 10:47:46.000000000 +0200
8277 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_standalone.c  2004-06-25 12:21:37.877633464 +0200
8278 @@ -177,6 +177,45 @@
8279         return do_bindings(ct, ctinfo, info, hooknum, pskb);
8280  }
8281  
8282 +struct nat_route_key
8283 +{
8284 +       u_int32_t addr;
8285 +#ifdef CONFIG_XFRM
8286 +       u_int16_t port;
8287 +#endif
8288 +};
8289 +
8290 +static inline void
8291 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
8292 +{
8293 +       struct iphdr *iph = skb->nh.iph;
8294 +
8295 +       key->addr = which ? iph->daddr : iph->saddr;
8296 +#ifdef CONFIG_XFRM
8297 +       key->port = 0;
8298 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8299 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8300 +               key->port = ports[which];
8301 +       }
8302 +#endif
8303 +}
8304 +
8305 +static inline int
8306 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
8307 +{
8308 +       struct iphdr *iph = skb->nh.iph;
8309 +
8310 +       if (key->addr != (which ? iph->daddr : iph->saddr))
8311 +               return 1;
8312 +#ifdef CONFIG_XFRM
8313 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8314 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8315 +               if (key->port != ports[which])
8316 +                       return 1;
8317 +       }
8318 +#endif
8319 +}
8320 +
8321  static unsigned int
8322  ip_nat_out(unsigned int hooknum,
8323            struct sk_buff **pskb,
8324 @@ -184,6 +223,9 @@
8325            const struct net_device *out,
8326            int (*okfn)(struct sk_buff *))
8327  {
8328 +       struct nat_route_key key;
8329 +       unsigned int ret;
8330 +
8331         /* root is playing with raw sockets. */
8332         if ((*pskb)->len < sizeof(struct iphdr)
8333             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8334 @@ -206,7 +248,29 @@
8335                         return NF_STOLEN;
8336         }
8337  
8338 -       return ip_nat_fn(hooknum, pskb, in, out, okfn);
8339 +       nat_route_key_get(*pskb, &key, 0);
8340 +       ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8341 +
8342 +       if (ret != NF_DROP && ret != NF_STOLEN
8343 +           && nat_route_key_compare(*pskb, &key, 0)) {
8344 +               if (ip_route_me_harder(pskb) != 0)
8345 +                       ret = NF_DROP;
8346 +#ifdef CONFIG_XFRM
8347 +               /*
8348 +                * POST_ROUTING hook is called with fixed outfn, we need
8349 +                * to manually confirm the packet and direct it to the
8350 +                * transformers if a policy matches.
8351 +                */
8352 +               else if ((*pskb)->dst->xfrm != NULL) {
8353 +                       ret = ip_conntrack_confirm(*pskb);
8354 +                       if (ret != NF_DROP) {
8355 +                               dst_output(*pskb);
8356 +                               ret = NF_STOLEN;
8357 +                       }
8358 +               }
8359 +#endif
8360 +       }
8361 +       return ret;
8362  }
8363  
8364  #ifdef CONFIG_IP_NF_NAT_LOCAL
8365 @@ -217,7 +281,7 @@
8366                 const struct net_device *out,
8367                 int (*okfn)(struct sk_buff *))
8368  {
8369 -       u_int32_t saddr, daddr;
8370 +       struct nat_route_key key;
8371         unsigned int ret;
8372  
8373         /* root is playing with raw sockets. */
8374 @@ -225,14 +289,14 @@
8375             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8376                 return NF_ACCEPT;
8377  
8378 -       saddr = (*pskb)->nh.iph->saddr;
8379 -       daddr = (*pskb)->nh.iph->daddr;
8380 -
8381 +       nat_route_key_get(*pskb, &key, 1);
8382         ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8383 +
8384         if (ret != NF_DROP && ret != NF_STOLEN
8385 -           && ((*pskb)->nh.iph->saddr != saddr
8386 -               || (*pskb)->nh.iph->daddr != daddr))
8387 -               return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
8388 +           && nat_route_key_compare(*pskb, &key, 1)) {
8389 +               if (ip_route_me_harder(pskb) != 0)
8390 +                       ret = NF_DROP;
8391 +       }
8392         return ret;
8393  }
8394  #endif
8395 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.7/net/ipv4/netfilter/ip_nat_talk.c
8396 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_talk.c    1970-01-01 01:00:00.000000000 +0100
8397 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_talk.c        2004-06-25 12:28:43.653905632 +0200
8398 @@ -0,0 +1,473 @@
8399 +/* 
8400 + * talk extension for UDP NAT alteration. 
8401 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8402 + *
8403 + *      This program is free software; you can redistribute it and/or
8404 + *      modify it under the terms of the GNU General Public License
8405 + *      as published by the Free Software Foundation; either version
8406 + *      2 of the License, or (at your option) any later version.
8407 + **
8408 + *     Module load syntax:
8409 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
8410 + *
8411 + *             talk=[0|1]      disable|enable old talk support
8412 + *            ntalk=[0|1]      disable|enable ntalk support
8413 + *           ntalk2=[0|1]      disable|enable ntalk2 support
8414 + *
8415 + *     The default is talk=1 ntalk=1 ntalk2=1
8416 + *
8417 + *  
8418 + */
8419 +#include <linux/module.h>
8420 +#include <linux/netfilter_ipv4.h>
8421 +#include <linux/ip.h>
8422 +#include <linux/udp.h>
8423 +#include <linux/kernel.h>
8424 +#include <net/tcp.h>
8425 +#include <net/udp.h>
8426 +
8427 +#include <linux/netfilter_ipv4/ip_nat.h>
8428 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8429 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8430 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8431 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8432 +
8433 +/* Default all talk protocols are supported */
8434 +static int talk   = 1;
8435 +static int ntalk  = 1;
8436 +static int ntalk2 = 1;
8437 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8438 +MODULE_DESCRIPTION("talk network address translation module");
8439 +#ifdef MODULE_PARM
8440 +MODULE_PARM(talk, "i");
8441 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8442 +MODULE_PARM(ntalk, "i");
8443 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8444 +MODULE_PARM(ntalk2, "i");
8445 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8446 +#endif
8447 +
8448 +#if 0
8449 +#define DEBUGP printk
8450 +#define IP_NAT_TALK_DEBUG
8451 +#else
8452 +#define DEBUGP(format, args...)
8453 +#endif
8454 +
8455 +/* FIXME: Time out? --RR */
8456 +
8457 +static int
8458 +mangle_packet(struct sk_buff **pskb,
8459 +             struct ip_conntrack *ct,
8460 +             u_int32_t newip,
8461 +             u_int16_t port,
8462 +             struct talk_addr *addr,
8463 +             struct talk_addr *ctl_addr)
8464 +{
8465 +       struct iphdr *iph = (*pskb)->nh.iph;
8466 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8467 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
8468 +
8469 +       /* Fortunately talk sends a structure with the address and
8470 +          port in it. The size of the packet won't change. */
8471 +
8472 +       if (ctl_addr == NULL) {
8473 +               /* response */
8474 +               if (addr->ta_addr == INADDR_ANY)
8475 +                       return 1;
8476 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8477 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8478 +                      NIPQUAD(newip), ntohs(port));
8479 +               addr->ta_addr = newip;
8480 +               addr->ta_port = port;
8481 +       } else {
8482 +               /* message */
8483 +               if (addr->ta_addr != INADDR_ANY) {
8484 +                       /* Change address inside packet to match way we're mapping
8485 +                          this connection. */
8486 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8487 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8488 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
8489 +                              ntohs(addr->ta_port));
8490 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8491 +               }
8492 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8493 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8494 +                      NIPQUAD(newip), ntohs(port));
8495 +               ctl_addr->ta_addr = newip;
8496 +               ctl_addr->ta_port = port;
8497 +       }
8498 +
8499 +       /* Fix checksums */
8500 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8501 +       udph->check = 0;
8502 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8503 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8504 +               
8505 +       ip_send_check(iph);
8506 +       return 1;
8507 +}
8508 +
8509 +static int talk_help_msg(struct ip_conntrack *ct,
8510 +                        struct sk_buff **pskb,
8511 +                        u_char type,
8512 +                        struct talk_addr *addr,
8513 +                        struct talk_addr *ctl_addr)
8514 +{
8515 +       u_int32_t newip;
8516 +       u_int16_t port;
8517 +       
8518 +       unsigned int verdict = NF_ACCEPT;
8519 +
8520 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8521 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8522 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8523 +               type);
8524 +
8525 +       /* Change address inside packet to match way we're mapping
8526 +          this connection. */
8527 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8528 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8529 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8530 +               NIPQUAD(newip), ntohs(port));
8531 +
8532 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8533 +               verdict = NF_DROP;
8534 +
8535 +       return verdict;
8536 +}
8537 +
8538 +static int talk_help_response(struct ip_conntrack *ct,
8539 +                             struct ip_conntrack_expect *exp,
8540 +                             struct sk_buff **pskb,
8541 +                             u_char type,
8542 +                             u_char answer,
8543 +                             struct talk_addr *addr)
8544 +{
8545 +       u_int32_t newip;
8546 +       u_int16_t port;
8547 +       struct ip_conntrack_tuple t;
8548 +       struct ip_ct_talk_expect *ct_talk_info;
8549 +
8550 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8551 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8552 +               type, answer);
8553 +       
8554 +       LOCK_BH(&ip_talk_lock);
8555 +       ct_talk_info = &exp->help.exp_talk_info;
8556 +
8557 +       if (!(answer == SUCCESS 
8558 +             && (type == LOOK_UP || type == ANNOUNCE)
8559 +             && exp != NULL)) {
8560 +               UNLOCK_BH(&ip_talk_lock);
8561 +               return NF_ACCEPT;
8562 +       }
8563 +               
8564 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
8565 +               ntohs(ct_talk_info->port), 
8566 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8567 +
8568 +       /* Change address inside packet to match way we're mapping
8569 +          this connection. */
8570 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
8571 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
8572 +       /* We can read expect here without conntrack lock, since it's
8573 +          only set in ip_conntrack_talk , with ip_talk_lock held
8574 +          writable */ 
8575 +       t = exp->tuple;
8576 +       t.dst.ip = newip;
8577 +
8578 +       /* Try to get same port: if not, try to change it. */
8579 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8580 +               if (type == LOOK_UP)
8581 +                       t.dst.u.tcp.port = htons(port);
8582 +               else
8583 +                       t.dst.u.udp.port = htons(port);
8584 +
8585 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
8586 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8587 +                       break;
8588 +               }
8589 +       }
8590 +       UNLOCK_BH(&ip_talk_lock);
8591 +
8592 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8593 +               return NF_DROP;
8594 +       
8595 +       return NF_ACCEPT;
8596 +}
8597 +
8598 +static unsigned int talk_help(struct ip_conntrack *ct,
8599 +                             struct ip_conntrack_expect *exp,
8600 +                             struct ip_nat_info *info,
8601 +                             enum ip_conntrack_info ctinfo,
8602 +                             unsigned int hooknum,
8603 +                             struct sk_buff **pskb,
8604 +                             int talk_port)
8605 +{
8606 +       struct iphdr *iph = (*pskb)->nh.iph;
8607 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8608 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8609 +       char *data = (char *)udph + sizeof(struct udphdr);
8610 +       int dir;
8611 +
8612 +       /* Only mangle things once: original direction in POST_ROUTING
8613 +          and reply direction on PRE_ROUTING. */
8614 +       dir = CTINFO2DIR(ctinfo);
8615 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8616 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8617 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8618 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8619 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8620 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8621 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8622 +               return NF_ACCEPT;
8623 +       }
8624 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8625 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8626 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8627 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8628 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8629 +              NIPQUAD(iph->saddr), ntohs(udph->source),
8630 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
8631 +              talk_port);
8632 +
8633 +       /* Because conntrack does not drop packets, checking must be repeated here... */
8634 +       if (talk_port == TALK_PORT) {
8635 +               if (dir == IP_CT_DIR_ORIGINAL
8636 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8637 +                       return talk_help_msg(ct, pskb,
8638 +                                            ((struct talk_msg *)data)->type, 
8639 +                                            &(((struct talk_msg *)data)->addr),
8640 +                                            &(((struct talk_msg *)data)->ctl_addr));
8641 +               else if (dir == IP_CT_DIR_REPLY
8642 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8643 +                       return talk_help_response(ct, exp, pskb,
8644 +                                                 ((struct talk_response *)data)->type, 
8645 +                                                 ((struct talk_response *)data)->answer,
8646 +                                                 &(((struct talk_response *)data)->addr));
8647 +               else {  
8648 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8649 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
8650 +                              (unsigned)udplen - sizeof(struct udphdr), 
8651 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8652 +                       return NF_DROP;
8653 +               }
8654 +       } else {
8655 +               if (dir == IP_CT_DIR_ORIGINAL) {
8656 +                       if (ntalk
8657 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8658 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8659 +                               return talk_help_msg(ct, pskb,
8660 +                                                    ((struct ntalk_msg *)data)->type, 
8661 +                                                    &(((struct ntalk_msg *)data)->addr),
8662 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
8663 +                       else if (ntalk2
8664 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8665 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8666 +                                && udplen == sizeof(struct udphdr) 
8667 +                                             + sizeof(struct ntalk2_msg) 
8668 +                                             + ((struct ntalk2_msg *)data)->extended)
8669 +                               return talk_help_msg(ct, pskb,
8670 +                                                    ((struct ntalk2_msg *)data)->type, 
8671 +                                                    &(((struct ntalk2_msg *)data)->addr),
8672 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
8673 +                       else {
8674 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
8675 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8676 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8677 +                               return NF_DROP;
8678 +                       }
8679 +               } else {
8680 +                       if (ntalk
8681 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8682 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8683 +                               return talk_help_response(ct, exp, pskb,
8684 +                                                         ((struct ntalk_response *)data)->type, 
8685 +                                                         ((struct ntalk_response *)data)->answer,
8686 +                                                         &(((struct ntalk_response *)data)->addr));
8687 +                       else if (ntalk2
8688 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8689 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8690 +                               return talk_help_response(ct, exp, pskb,
8691 +                                                         ((struct ntalk2_response *)data)->type, 
8692 +                                                         ((struct ntalk2_response *)data)->answer,
8693 +                                                         &(((struct ntalk2_response *)data)->addr));
8694 +                       else {
8695 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
8696 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8697 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8698 +                               return NF_DROP;
8699 +                       }
8700 +               }
8701 +       }
8702 +}
8703 +
8704 +static unsigned int help(struct ip_conntrack *ct,
8705 +                        struct ip_conntrack_expect *exp,
8706 +                        struct ip_nat_info *info,
8707 +                        enum ip_conntrack_info ctinfo,
8708 +                        unsigned int hooknum,
8709 +                        struct sk_buff **pskb)
8710 +{
8711 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8712 +}
8713 +
8714 +static unsigned int nhelp(struct ip_conntrack *ct,
8715 +                         struct ip_conntrack_expect *exp,
8716 +                         struct ip_nat_info *info,
8717 +                         enum ip_conntrack_info ctinfo,
8718 +                         unsigned int hooknum,
8719 +                         struct sk_buff **pskb)
8720 +{
8721 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8722 +}
8723 +
8724 +static unsigned int
8725 +talk_nat_expected(struct sk_buff **pskb,
8726 +                 unsigned int hooknum,
8727 +                 struct ip_conntrack *ct,
8728 +                 struct ip_nat_info *info);
8729 +
8730 +static struct ip_nat_helper talk_helpers[2] = 
8731 +       { { { NULL, NULL },
8732 +            "talk",                                    /* name */
8733 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8734 +            THIS_MODULE,                               /* module */
8735 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8736 +              { 0, { 0 }, IPPROTO_UDP } },
8737 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8738 +              { 0, { 0 }, 0xFFFF } },
8739 +            help,                                      /* helper */
8740 +            talk_nat_expected },                       /* expectfn */
8741 +         { { NULL, NULL },
8742 +            "ntalk",                                   /* name */
8743 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8744 +            THIS_MODULE,                                       /* module */
8745 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8746 +              { 0, { 0 }, IPPROTO_UDP } },
8747 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8748 +              { 0, { 0 }, 0xFFFF } },
8749 +            nhelp,                                     /* helper */
8750 +            talk_nat_expected }                                /* expectfn */
8751 +       };
8752 +          
8753 +static unsigned int
8754 +talk_nat_expected(struct sk_buff **pskb,
8755 +                 unsigned int hooknum,
8756 +                 struct ip_conntrack *ct,
8757 +                 struct ip_nat_info *info)
8758 +{
8759 +       struct ip_nat_multi_range mr;
8760 +       u_int32_t newdstip, newsrcip, newip;
8761 +       u_int16_t port;
8762 +       unsigned int ret;
8763 +       
8764 +       struct ip_conntrack *master = master_ct(ct);
8765 +
8766 +       IP_NF_ASSERT(info);
8767 +       IP_NF_ASSERT(master);
8768 +
8769 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8770 +
8771 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8772 +
8773 +       LOCK_BH(&ip_talk_lock);
8774 +       port = ct->master->help.exp_talk_info.port;
8775 +       UNLOCK_BH(&ip_talk_lock);
8776 +
8777 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8778 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8779 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8780 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8781 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8782 +              ct, master);
8783 +
8784 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8785 +               /* Callee client -> caller server */
8786 +#ifdef IP_NAT_TALK_DEBUG
8787 +               struct iphdr *iph = (*pskb)->nh.iph;
8788 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
8789 +
8790 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8791 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
8792 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
8793 +#endif
8794 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8795 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8796 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8797 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8798 +       } else {
8799 +               /* Callee client -> caller client */
8800 +#ifdef IP_NAT_TALK_DEBUG
8801 +               struct iphdr *iph = (*pskb)->nh.iph;
8802 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8803 +
8804 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8805 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
8806 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
8807 +#endif
8808 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8809 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8810 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8811 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8812 +       }
8813 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8814 +               newip = newsrcip;
8815 +       else
8816 +               newip = newdstip;
8817 +
8818 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8819 +
8820 +       mr.rangesize = 1;
8821 +       /* We don't want to manip the per-protocol, just the IPs... */
8822 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8823 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8824 +       
8825 +       /* ... unless we're doing a MANIP_DST, in which case, make
8826 +          sure we map to the correct port */
8827 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8828 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8829 +               mr.range[0].min = mr.range[0].max
8830 +                       = ((union ip_conntrack_manip_proto)
8831 +                               { .udp = { port } });
8832 +       }
8833 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
8834 +
8835 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8836 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8837 +               /* NAT expectfn called with ip_nat_lock write-locked */
8838 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
8839 +       }
8840 +       return ret;
8841 +}
8842 +
8843 +static int __init init(void)
8844 +{
8845 +       int ret = 0;
8846 +
8847 +       if (talk > 0) {
8848 +               ret = ip_nat_helper_register(&talk_helpers[0]);
8849 +
8850 +               if (ret != 0)
8851 +                       return ret;
8852 +       }
8853 +       if (ntalk > 0 || ntalk2 > 0) {
8854 +               ret = ip_nat_helper_register(&talk_helpers[1]);
8855 +
8856 +               if (ret != 0 && talk > 0)
8857 +                       ip_nat_helper_unregister(&talk_helpers[0]);
8858 +       }
8859 +       return ret;
8860 +}
8861 +
8862 +static void __exit fini(void)
8863 +{
8864 +       if (talk > 0)
8865 +               ip_nat_helper_unregister(&talk_helpers[0]);
8866 +       if (ntalk > 0 || ntalk2 > 0)
8867 +               ip_nat_helper_unregister(&talk_helpers[1]);
8868 +}
8869 +
8870 +module_init(init);
8871 +module_exit(fini);
8872 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_pool.c linux-2.6.7/net/ipv4/netfilter/ip_pool.c
8873 --- linux-2.6.7.org/net/ipv4/netfilter/ip_pool.c        1970-01-01 01:00:00.000000000 +0100
8874 +++ linux-2.6.7/net/ipv4/netfilter/ip_pool.c    2004-06-25 12:21:11.464648848 +0200
8875 @@ -0,0 +1,332 @@
8876 +/* Kernel module for IP pool management */
8877 +
8878 +#include <linux/module.h>
8879 +#include <linux/ip.h>
8880 +#include <linux/skbuff.h>
8881 +#include <linux/netfilter_ipv4/ip_tables.h>
8882 +#include <linux/netfilter_ipv4/ip_pool.h>
8883 +#include <linux/errno.h>
8884 +#include <asm/uaccess.h>
8885 +#include <asm/bitops.h>
8886 +#include <linux/interrupt.h>
8887 +#include <linux/spinlock.h>
8888 +
8889 +#if 0
8890 +#define DP printk
8891 +#else
8892 +#define DP(format, args...)
8893 +#endif
8894 +
8895 +MODULE_LICENSE("GPL");
8896 +
8897 +#define NR_POOL 16
8898 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8899 +
8900 +struct ip_pool {
8901 +       u_int32_t first_ip;     /* host byte order, included in range */
8902 +       u_int32_t last_ip;      /* host byte order, included in range */
8903 +       void *members;          /* the bitmap proper */
8904 +       int nr_use;             /* total nr. of tests through this */
8905 +       int nr_match;           /* total nr. of matches through this */
8906 +       rwlock_t lock;
8907 +};
8908 +
8909 +static struct ip_pool *POOL;
8910 +
8911 +static inline struct ip_pool *lookup(ip_pool_t index)
8912 +{
8913 +       if (index < 0 || index >= nr_pool) {
8914 +               DP("ip_pool:lookup: bad index %d\n", index);
8915 +               return 0;
8916 +       }
8917 +       return POOL+index;
8918 +}
8919 +
8920 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8921 +{
8922 +        struct ip_pool *pool = lookup(index);
8923 +       int res = 0;
8924 +
8925 +       if (!pool || !pool->members)
8926 +               return 0;
8927 +       read_lock_bh(&pool->lock);
8928 +       if (pool->members) {
8929 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
8930 +                       addr -= pool->first_ip;
8931 +                       if (test_bit(addr, pool->members)) {
8932 +                               res = 1;
8933 +#ifdef CONFIG_IP_POOL_STATISTICS
8934 +                               pool->nr_match++;
8935 +#endif
8936 +                       }
8937 +               }
8938 +#ifdef CONFIG_IP_POOL_STATISTICS
8939 +               pool->nr_use++;
8940 +#endif
8941 +       }
8942 +       read_unlock_bh(&pool->lock);
8943 +       return res;
8944 +}
8945 +
8946 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8947 +{
8948 +       struct ip_pool *pool;
8949 +       int res = -1;
8950 +
8951 +       pool = lookup(index);
8952 +       if (    !pool || !pool->members
8953 +            || addr < pool->first_ip || addr > pool->last_ip)
8954 +               return -1;
8955 +       read_lock_bh(&pool->lock);
8956 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8957 +               addr -= pool->first_ip;
8958 +               res = isdel
8959 +                       ? (0 != test_and_clear_bit(addr, pool->members))
8960 +                       : (0 != test_and_set_bit(addr, pool->members));
8961 +       }
8962 +       read_unlock_bh(&pool->lock);
8963 +       return res;
8964 +}
8965 +
8966 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8967 +{
8968 +       int res = pool_change(index,addr,isdel);
8969 +
8970 +       if (!isdel) res = !res;
8971 +       return res;
8972 +}
8973 +
8974 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8975 +{
8976 +       return 4*((((b-a+8)/8)+3)/4);
8977 +}
8978 +
8979 +static inline int poolbytes(ip_pool_t index)
8980 +{
8981 +       struct ip_pool *pool = lookup(index);
8982 +
8983 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8984 +}
8985 +
8986 +static int setpool(
8987 +       struct sock *sk,
8988 +       int optval,
8989 +       void *user,
8990 +       unsigned int len
8991 +) {
8992 +       struct ip_pool_request req;
8993 +
8994 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8995 +       if (!capable(CAP_NET_ADMIN))
8996 +               return -EPERM;
8997 +       if (optval != SO_IP_POOL)
8998 +               return -EBADF;
8999 +       if (len != sizeof(req))
9000 +               return -EINVAL;
9001 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
9002 +               return -EFAULT;
9003 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
9004 +       return -EINVAL;
9005 +}
9006 +
9007 +static int getpool(
9008 +       struct sock *sk,
9009 +       int optval,
9010 +       void *user,
9011 +       int *len
9012 +) {
9013 +       struct ip_pool_request req;
9014 +       struct ip_pool *pool;
9015 +       ip_pool_t i;
9016 +       int newbytes;
9017 +       void *newmembers;
9018 +       int res;
9019 +
9020 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
9021 +       if (!capable(CAP_NET_ADMIN))
9022 +               return -EINVAL;
9023 +       if (optval != SO_IP_POOL)
9024 +               return -EINVAL;
9025 +       if (*len != sizeof(req)) {
9026 +               return -EFAULT;
9027 +       }
9028 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
9029 +               return -EFAULT;
9030 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
9031 +       if (req.op < IP_POOL_BAD001) {
9032 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
9033 +               return -EFAULT;
9034 +       }
9035 +       switch(req.op) {
9036 +       case IP_POOL_HIGH_NR:
9037 +               DP("ip_pool HIGH_NR\n");
9038 +               req.index = IP_POOL_NONE;
9039 +               for (i=0; i<nr_pool; i++)
9040 +                       if (POOL[i].members)
9041 +                               req.index = i;
9042 +               return copy_to_user(user, &req, sizeof(req));
9043 +       case IP_POOL_LOOKUP:
9044 +               DP("ip_pool LOOKUP\n");
9045 +               pool = lookup(req.index);
9046 +               if (!pool)
9047 +                       return -EINVAL;
9048 +               if (!pool->members)
9049 +                       return -EBADF;
9050 +               req.addr = htonl(pool->first_ip);
9051 +               req.addr2 = htonl(pool->last_ip);
9052 +               return copy_to_user(user, &req, sizeof(req));
9053 +       case IP_POOL_USAGE:
9054 +               DP("ip_pool USE\n");
9055 +               pool = lookup(req.index);
9056 +               if (!pool)
9057 +                       return -EINVAL;
9058 +               if (!pool->members)
9059 +                       return -EBADF;
9060 +               req.addr = pool->nr_use;
9061 +               req.addr2 = pool->nr_match;
9062 +               return copy_to_user(user, &req, sizeof(req));
9063 +       case IP_POOL_TEST_ADDR:
9064 +               DP("ip_pool TEST 0x%08x\n", req.addr);
9065 +               pool = lookup(req.index);
9066 +               if (!pool)
9067 +                       return -EINVAL;
9068 +               res = 0;
9069 +               read_lock_bh(&pool->lock);
9070 +               if (!pool->members) {
9071 +                       DP("ip_pool TEST_ADDR no members in pool\n");
9072 +                       res = -EBADF;
9073 +                       goto unlock_and_return_res;
9074 +               }
9075 +               req.addr = ntohl(req.addr);
9076 +               if (req.addr < pool->first_ip) {
9077 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
9078 +                       res = -ERANGE;
9079 +                       goto unlock_and_return_res;
9080 +               }
9081 +               if (req.addr > pool->last_ip) {
9082 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
9083 +                       res = -ERANGE;
9084 +                       goto unlock_and_return_res;
9085 +               }
9086 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
9087 +                                       pool->members));
9088 +               read_unlock_bh(&pool->lock);
9089 +               return copy_to_user(user, &req, sizeof(req));
9090 +       case IP_POOL_FLUSH:
9091 +               DP("ip_pool FLUSH not yet implemented.\n");
9092 +               return -EBUSY;
9093 +       case IP_POOL_DESTROY:
9094 +               DP("ip_pool DESTROY not yet implemented.\n");
9095 +               return -EBUSY;
9096 +       case IP_POOL_INIT:
9097 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
9098 +               pool = lookup(req.index);
9099 +               if (!pool)
9100 +                       return -EINVAL;
9101 +               req.addr = ntohl(req.addr);
9102 +               req.addr2 = ntohl(req.addr2);
9103 +               if (req.addr > req.addr2) {
9104 +                       DP("ip_pool INIT bad ip range\n");
9105 +                       return -EINVAL;
9106 +               }
9107 +               newbytes = bitmap_bytes(req.addr, req.addr2);
9108 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
9109 +               if (!newmembers) {
9110 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
9111 +                       return -ENOMEM;
9112 +               }
9113 +               memset(newmembers, 0, newbytes);
9114 +               write_lock_bh(&pool->lock);
9115 +               if (pool->members) {
9116 +                       DP("ip_pool INIT pool %d exists\n", req.index);
9117 +                       kfree(newmembers);
9118 +                       res = -EBUSY;
9119 +                       goto unlock_and_return_res;
9120 +               }
9121 +               pool->first_ip = req.addr;
9122 +               pool->last_ip = req.addr2;
9123 +               pool->nr_use = 0;
9124 +               pool->nr_match = 0;
9125 +               pool->members = newmembers;
9126 +               write_unlock_bh(&pool->lock);
9127 +               return 0;
9128 +       case IP_POOL_ADD_ADDR:
9129 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
9130 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
9131 +               return copy_to_user(user, &req, sizeof(req));
9132 +       case IP_POOL_DEL_ADDR:
9133 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
9134 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
9135 +               return copy_to_user(user, &req, sizeof(req));
9136 +       default:
9137 +               DP("ip_pool:getpool bad op %d\n", req.op);
9138 +               return -EINVAL;
9139 +       }
9140 +       return -EINVAL;
9141 +
9142 +unlock_and_return_res:
9143 +       if (pool)
9144 +               read_unlock_bh(&pool->lock);
9145 +       return res;
9146 +}
9147 +
9148 +static struct nf_sockopt_ops so_pool
9149 += { { NULL, NULL }, PF_INET,
9150 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
9151 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
9152 +    0, NULL };
9153 +
9154 +MODULE_PARM(nr_pool, "i");
9155 +
9156 +static int __init init(void)
9157 +{
9158 +       ip_pool_t i;
9159 +       int res;
9160 +
9161 +       if (nr_pool < 1) {
9162 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
9163 +               return -EINVAL;
9164 +       }
9165 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
9166 +       if (!POOL) {
9167 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
9168 +                       nr_pool);
9169 +               return -ENOMEM;
9170 +       }
9171 +       for (i=0; i<nr_pool; i++) {
9172 +               POOL[i].first_ip = 0;
9173 +               POOL[i].last_ip = 0;
9174 +               POOL[i].members = 0;
9175 +               POOL[i].nr_use = 0;
9176 +               POOL[i].nr_match = 0;
9177 +               POOL[i].lock = RW_LOCK_UNLOCKED;
9178 +       }
9179 +       res = nf_register_sockopt(&so_pool);
9180 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
9181 +       if (res != 0) {
9182 +               kfree(POOL);
9183 +               POOL = 0;
9184 +       }
9185 +       return res;
9186 +}
9187 +
9188 +static void __exit fini(void)
9189 +{
9190 +       ip_pool_t i;
9191 +
9192 +       DP("ip_pool:fini BYEBYE\n");
9193 +       nf_unregister_sockopt(&so_pool);
9194 +       for (i=0; i<nr_pool; i++) {
9195 +               if (POOL[i].members) {
9196 +                       kfree(POOL[i].members);
9197 +                       POOL[i].members = 0;
9198 +               }
9199 +       }
9200 +       kfree(POOL);
9201 +       POOL = 0;
9202 +       DP("ip_pool:fini these are the famous last words\n");
9203 +       return;
9204 +}
9205 +
9206 +module_init(init);
9207 +module_exit(fini);
9208 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.7/net/ipv4/netfilter/ipt_CONNMARK.c
9209 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_CONNMARK.c   1970-01-01 01:00:00.000000000 +0100
9210 +++ linux-2.6.7/net/ipv4/netfilter/ipt_CONNMARK.c       2004-06-25 12:21:25.484517504 +0200
9211 @@ -0,0 +1,118 @@
9212 +/* This kernel module is used to modify the connection mark values, or
9213 + * to optionally restore the skb nfmark from the connection mark
9214 + *
9215 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9216 + * by Henrik Nordstrom <hno@marasystems.com>
9217 + *
9218 + * This program is free software; you can redistribute it and/or modify
9219 + * it under the terms of the GNU General Public License as published by
9220 + * the Free Software Foundation; either version 2 of the License, or
9221 + * (at your option) any later version.
9222 + *
9223 + * This program is distributed in the hope that it will be useful,
9224 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9225 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9226 + * GNU General Public License for more details.
9227 + *
9228 + * You should have received a copy of the GNU General Public License
9229 + * along with this program; if not, write to the Free Software
9230 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
9231 + */
9232 +#include <linux/module.h>
9233 +#include <linux/skbuff.h>
9234 +#include <linux/ip.h>
9235 +#include <net/checksum.h>
9236 +
9237 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9238 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
9239 +MODULE_LICENSE("GPL");
9240 +
9241 +#include <linux/netfilter_ipv4/ip_tables.h>
9242 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
9243 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9244 +
9245 +static unsigned int
9246 +target(struct sk_buff **pskb,
9247 +       const struct net_device *in,
9248 +       const struct net_device *out,
9249 +       unsigned int hooknum,
9250 +       const void *targinfo,
9251 +       void *userinfo)
9252 +{
9253 +       const struct ipt_connmark_target_info *markinfo = targinfo;
9254 +       unsigned long diff;
9255 +       unsigned long nfmark;
9256 +       unsigned long newmark;
9257 +
9258 +       enum ip_conntrack_info ctinfo;
9259 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
9260 +       if (ct) {
9261 +           switch(markinfo->mode) {
9262 +           case IPT_CONNMARK_SET:
9263 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
9264 +               if (newmark != ct->mark)
9265 +                   ct->mark = newmark;
9266 +               break;
9267 +           case IPT_CONNMARK_SAVE:
9268 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
9269 +               if (ct->mark != newmark)
9270 +                   ct->mark = newmark;
9271 +               break;
9272 +           case IPT_CONNMARK_RESTORE:
9273 +               nfmark = (*pskb)->nfmark;
9274 +               diff = (ct->mark ^ nfmark & markinfo->mask);
9275 +               if (diff != 0) {
9276 +                   (*pskb)->nfmark = nfmark ^ diff;
9277 +                   (*pskb)->nfcache |= NFC_ALTERED;
9278 +               }
9279 +               break;
9280 +           }
9281 +       }
9282 +
9283 +       return IPT_CONTINUE;
9284 +}
9285 +
9286 +static int
9287 +checkentry(const char *tablename,
9288 +          const struct ipt_entry *e,
9289 +          void *targinfo,
9290 +          unsigned int targinfosize,
9291 +          unsigned int hook_mask)
9292 +{
9293 +       struct ipt_connmark_target_info *matchinfo = targinfo;
9294 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
9295 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
9296 +                      targinfosize,
9297 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
9298 +               return 0;
9299 +       }
9300 +
9301 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
9302 +           if (strcmp(tablename, "mangle") != 0) {
9303 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9304 +                   return 0;
9305 +           }
9306 +       }
9307 +
9308 +       return 1;
9309 +}
9310 +
9311 +static struct ipt_target ipt_connmark_reg = {
9312 +       .name = "CONNMARK",
9313 +       .target = &target,
9314 +       .checkentry = &checkentry,
9315 +       .me = THIS_MODULE
9316 +};
9317 +
9318 +static int __init init(void)
9319 +{
9320 +       return ipt_register_target(&ipt_connmark_reg);
9321 +}
9322 +
9323 +static void __exit fini(void)
9324 +{
9325 +       ipt_unregister_target(&ipt_connmark_reg);
9326 +}
9327 +
9328 +module_init(init);
9329 +module_exit(fini);
9330 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.7/net/ipv4/netfilter/ipt_IPMARK.c
9331 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPMARK.c     1970-01-01 01:00:00.000000000 +0100
9332 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPMARK.c 2004-06-25 12:21:27.028282816 +0200
9333 @@ -0,0 +1,81 @@
9334 +/* This is a module which is used for setting the NFMARK field of an skb. */
9335 +#include <linux/module.h>
9336 +#include <linux/skbuff.h>
9337 +#include <linux/ip.h>
9338 +#include <net/checksum.h>
9339 +
9340 +#include <linux/netfilter_ipv4/ip_tables.h>
9341 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
9342 +
9343 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
9344 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
9345 +MODULE_LICENSE("GPL");
9346 +
9347 +static unsigned int
9348 +target(struct sk_buff **pskb,
9349 +       const struct net_device *in,
9350 +       const struct net_device *out,
9351 +       unsigned int hooknum,
9352 +       const void *targinfo,
9353 +       void *userinfo)
9354 +{
9355 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
9356 +       struct iphdr *iph = (*pskb)->nh.iph;
9357 +       unsigned long mark;
9358 +
9359 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
9360 +               mark = (unsigned long) ntohl(iph->saddr);
9361 +       else
9362 +               mark = (unsigned long) ntohl(iph->daddr);
9363 +
9364 +       mark &= ipmarkinfo->andmask;
9365 +       mark |= ipmarkinfo->ormask;
9366 +       
9367 +       if ((*pskb)->nfmark != mark) {
9368 +               (*pskb)->nfmark = mark;
9369 +               (*pskb)->nfcache |= NFC_ALTERED;
9370 +       }
9371 +       return IPT_CONTINUE;
9372 +}
9373 +
9374 +static int
9375 +checkentry(const char *tablename,
9376 +          const struct ipt_entry *e,
9377 +           void *targinfo,
9378 +           unsigned int targinfosize,
9379 +           unsigned int hook_mask)
9380 +{
9381 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
9382 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
9383 +                      targinfosize,
9384 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
9385 +               return 0;
9386 +       }
9387 +
9388 +       if (strcmp(tablename, "mangle") != 0) {
9389 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9390 +               return 0;
9391 +       }
9392 +
9393 +       return 1;
9394 +}
9395 +
9396 +static struct ipt_target ipt_ipmark_reg = { 
9397 +       .name = "IPMARK",
9398 +       .target = target,
9399 +       .checkentry = checkentry,
9400 +       .me = THIS_MODULE
9401 +};
9402 +
9403 +static int __init init(void)
9404 +{
9405 +       return ipt_register_target(&ipt_ipmark_reg);
9406 +}
9407 +
9408 +static void __exit fini(void)
9409 +{
9410 +       ipt_unregister_target(&ipt_ipmark_reg);
9411 +}
9412 +
9413 +module_init(init);
9414 +module_exit(fini);
9415 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
9416 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      1970-01-01 01:00:00.000000000 +0100
9417 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  2004-06-25 12:21:06.371423136 +0200
9418 @@ -0,0 +1,89 @@
9419 +/**
9420 + * Strip all IP options in the IP packet header.
9421 + *
9422 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
9423 + * This software is distributed under GNU GPL v2, 1991
9424 + */
9425 +
9426 +#include <linux/module.h>
9427 +#include <linux/skbuff.h>
9428 +#include <linux/ip.h>
9429 +#include <net/checksum.h>
9430 +
9431 +#include <linux/netfilter_ipv4/ip_tables.h>
9432 +
9433 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
9434 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
9435 +MODULE_LICENSE("GPL");
9436 +
9437 +static unsigned int
9438 +target(struct sk_buff **pskb,
9439 +       const struct net_device *in,
9440 +       const struct net_device *out,
9441 +       unsigned int hooknum,
9442 +       const void *targinfo,
9443 +       void *userinfo)
9444 +{
9445 +       struct iphdr *iph;
9446 +       struct sk_buff *skb;
9447 +       struct ip_options *opt;
9448 +       unsigned char *optiph;
9449 +       int l;
9450 +       
9451 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
9452 +               return NF_DROP;
9453
9454 +       skb = (*pskb);
9455 +       iph = (*pskb)->nh.iph;
9456 +       optiph = skb->nh.raw;
9457 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
9458 +
9459 +       /* if no options in packet then nothing to clear. */
9460 +       if (iph->ihl * 4 == sizeof(struct iphdr))
9461 +               return IPT_CONTINUE;
9462 +
9463 +       /* else clear all options */
9464 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
9465 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
9466 +       opt = &(IPCB(skb)->opt);
9467 +       opt->is_data = 0;
9468 +       opt->optlen = l;
9469 +
9470 +       skb->nfcache |= NFC_ALTERED;
9471 +
9472 +        return IPT_CONTINUE;
9473 +}
9474 +
9475 +static int
9476 +checkentry(const char *tablename,
9477 +          const struct ipt_entry *e,
9478 +           void *targinfo,
9479 +           unsigned int targinfosize,
9480 +           unsigned int hook_mask)
9481 +{
9482 +       if (strcmp(tablename, "mangle")) {
9483 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9484 +               return 0;
9485 +       }
9486 +       /* nothing else to check because no parameters */
9487 +       return 1;
9488 +}
9489 +
9490 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
9491 +       .name = "IPV4OPTSSTRIP",
9492 +       .target = target,
9493 +       .checkentry = checkentry,
9494 +       .me = THIS_MODULE };
9495 +
9496 +static int __init init(void)
9497 +{
9498 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
9499 +}
9500 +
9501 +static void __exit fini(void)
9502 +{
9503 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9504 +}
9505 +
9506 +module_init(init);
9507 +module_exit(fini);
9508 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.7/net/ipv4/netfilter/ipt_NETLINK.c
9509 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_NETLINK.c    1970-01-01 01:00:00.000000000 +0100
9510 +++ linux-2.6.7/net/ipv4/netfilter/ipt_NETLINK.c        2004-06-25 12:21:06.897343184 +0200
9511 @@ -0,0 +1,119 @@
9512 +#include <linux/module.h>
9513 +#include <linux/version.h>
9514 +#include <linux/config.h>
9515 +#include <linux/socket.h>
9516 +#include <linux/skbuff.h>
9517 +#include <linux/kernel.h>
9518 +#include <linux/netlink.h>
9519 +#include <linux/netdevice.h>
9520 +#include <linux/mm.h>
9521 +#include <linux/socket.h>
9522 +#include <linux/netfilter_ipv4/ip_tables.h>
9523 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9524 +#include <net/sock.h>
9525 +
9526 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9527 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9528 +MODULE_LICENSE("GPL");
9529 +
9530 +#if 0
9531 +#define DEBUGP printk
9532 +#else
9533 +#define DEBUGP(format, args...)
9534 +#endif
9535 +
9536 +static struct sock *ipfwsk;
9537 +
9538 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9539 +                                   unsigned int hooknum,
9540 +                                   const struct net_device *in,
9541 +                                   const struct net_device *out,
9542 +                                   const void *targinfo, void *userinfo)
9543 +{
9544 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9545 +       struct iphdr *ip = (*pskb)->nh.iph;
9546 +       struct sk_buff *outskb;
9547 +       struct netlink_t nlhdr;
9548 +       size_t len=0;
9549 +
9550 +       /* Allocate a socket buffer */
9551 +       if ( MASK(nld->flags, USE_SIZE) )
9552 +               len = nld->size+sizeof(nlhdr);
9553 +       else
9554 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
9555 +
9556 +       outskb=alloc_skb(len, GFP_ATOMIC);
9557 +
9558 +       if (outskb) {
9559 +               nlhdr.len=len;
9560 +               
9561 +               if ( MASK(nld->flags, USE_MARK) )
9562 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
9563 +               else
9564 +                       nlhdr.mark=(*pskb)->nfmark;
9565 +               
9566 +               if ( in && in->name ) {
9567 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9568 +               }else if ( out && out->name ){
9569 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9570 +               }
9571 +
9572 +               skb_put(outskb, len);
9573 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9574 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9575 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9576 +       }else{
9577 +               if (net_ratelimit())
9578 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9579 +       }
9580 +
9581 +       if ( MASK(nld->flags, USE_DROP) )
9582 +               return NF_DROP;
9583 +
9584 +       return IPT_CONTINUE;
9585 +}
9586 +
9587 +static int ipt_netlink_checkentry(const char *tablename,
9588 +                              const struct ipt_entry *e,
9589 +                              void *targinfo,
9590 +                              unsigned int targinfosize,
9591 +                              unsigned int hookmask)
9592 +{
9593 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9594 +
9595 +       return 1;
9596 +}
9597 +
9598 +static struct ipt_target ipt_netlink_reg = { 
9599 +       {NULL, NULL},
9600 +       "NETLINK",
9601 +       ipt_netlink_target,
9602 +       ipt_netlink_checkentry,
9603 +       NULL,
9604 +       THIS_MODULE
9605 +};
9606 +
9607 +static int __init init(void)
9608 +{
9609 +       DEBUGP("ipt_NETLINK: init module\n");   
9610 +
9611 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
9612 +               return -EINVAL;
9613 +       }
9614 +
9615 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9616 +               return -EINVAL;
9617 +       }
9618 +
9619 +       return 0;
9620 +}
9621 +
9622 +static void __exit fini(void)
9623 +{
9624 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
9625 +       ipt_unregister_target(&ipt_netlink_reg);
9626 +       if(ipfwsk->socket) sock_release(ipfwsk->socket);
9627 +}
9628 +
9629 +module_init(init);
9630 +module_exit(fini);
9631 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.7/net/ipv4/netfilter/ipt_POOL.c
9632 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_POOL.c       1970-01-01 01:00:00.000000000 +0100
9633 +++ linux-2.6.7/net/ipv4/netfilter/ipt_POOL.c   2004-06-25 12:21:11.466648544 +0200
9634 @@ -0,0 +1,116 @@
9635 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9636 + *
9637 + * This target can be used almost everywhere. It acts on some specified
9638 + * IP pool, adding or deleting some IP address in the pool. The address
9639 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9640 + * of the packet under inspection.
9641 + *
9642 + * The target normally returns IPT_CONTINUE.
9643 + */
9644 +
9645 +#include <linux/types.h>
9646 +#include <linux/ip.h>
9647 +#include <linux/timer.h>
9648 +#include <linux/module.h>
9649 +#include <linux/netfilter.h>
9650 +#include <linux/netdevice.h>
9651 +#include <linux/if.h>
9652 +#include <linux/inetdevice.h>
9653 +#include <net/protocol.h>
9654 +#include <net/checksum.h>
9655 +#include <linux/netfilter_ipv4.h>
9656 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9657 +#include <linux/netfilter_ipv4/ipt_pool.h>
9658 +
9659 +#if 0
9660 +#define DEBUGP printk
9661 +#else
9662 +#define DEBUGP(format, args...)
9663 +#endif
9664 +
9665 +/*** NOTE NOTE NOTE NOTE ***
9666 +**
9667 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9668 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9669 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9670 +** is modified for the source IP address of the packet under inspection.
9671 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9672 +**
9673 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9674 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9675 +**
9676 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9677 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9678 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9679 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9680 +*/
9681 +
9682 +static int
9683 +do_check(const char *tablename,
9684 +              const struct ipt_entry *e,
9685 +              void *targinfo,
9686 +              unsigned int targinfosize,
9687 +              unsigned int hook_mask)
9688 +{
9689 +       const struct ipt_pool_info *ipi = targinfo;
9690 +
9691 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9692 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
9693 +               return 0;
9694 +       }
9695 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9696 +       return 1;
9697 +}
9698 +
9699 +static unsigned int
9700 +do_target(struct sk_buff **pskb,
9701 +               unsigned int hooknum,
9702 +               const struct net_device *in,
9703 +               const struct net_device *out,
9704 +               const void *targinfo,
9705 +               void *userinfo)
9706 +{
9707 +       const struct ipt_pool_info *ipi = targinfo;
9708 +       int modified;
9709 +       unsigned int verdict = IPT_CONTINUE;
9710 +
9711 +       if (ipi->src != IP_POOL_NONE) {
9712 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9713 +                                       ipi->flags & IPT_POOL_DEL_SRC);
9714 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9715 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9716 +                               verdict = NF_ACCEPT;
9717 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9718 +                               verdict = NF_DROP;
9719 +               }
9720 +       }
9721 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9722 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9723 +                                       ipi->flags & IPT_POOL_DEL_DST);
9724 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9725 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9726 +                               verdict = NF_ACCEPT;
9727 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9728 +                               verdict = NF_DROP;
9729 +               }
9730 +       }
9731 +       return verdict;
9732 +}
9733 +
9734 +static struct ipt_target pool_reg
9735 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9736 +
9737 +static int __init init(void)
9738 +{
9739 +       DEBUGP("init ipt_POOL\n");
9740 +       return ipt_register_target(&pool_reg);
9741 +}
9742 +
9743 +static void __exit fini(void)
9744 +{
9745 +       DEBUGP("fini ipt_POOL\n");
9746 +       ipt_unregister_target(&pool_reg);
9747 +}
9748 +
9749 +module_init(init);
9750 +module_exit(fini);
9751 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.7/net/ipv4/netfilter/ipt_ROUTE.c
9752 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ROUTE.c      1970-01-01 01:00:00.000000000 +0100
9753 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ROUTE.c  2004-06-25 12:21:28.214102544 +0200
9754 @@ -0,0 +1,393 @@
9755 +/*
9756 + * This implements the ROUTE target, which enables you to setup unusual
9757 + * routes not supported by the standard kernel routing table.
9758 + *
9759 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
9760 + *
9761 + * v 1.9 2004/05/14
9762 + *
9763 + * This software is distributed under GNU GPL v2, 1991
9764 + */
9765 +
9766 +#include <linux/module.h>
9767 +#include <linux/skbuff.h>
9768 +#include <linux/ip.h>
9769 +#include <linux/netfilter_ipv4/ip_tables.h>
9770 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
9771 +#include <linux/netdevice.h>
9772 +#include <linux/route.h>
9773 +#include <net/ip.h>
9774 +#include <net/route.h>
9775 +#include <net/icmp.h>
9776 +#include <net/checksum.h>
9777 +
9778 +#if 0
9779 +#define DEBUGP printk
9780 +#else
9781 +#define DEBUGP(format, args...)
9782 +#endif
9783 +
9784 +MODULE_LICENSE("GPL");
9785 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
9786 +MODULE_DESCRIPTION("iptables ROUTE target module");
9787 +
9788 +/* Try to route the packet according to the routing keys specified in
9789 + * route_info. Keys are :
9790 + *  - ifindex : 
9791 + *      0 if no oif preferred, 
9792 + *      otherwise set to the index of the desired oif
9793 + *  - route_info->gw :
9794 + *      0 if no gateway specified,
9795 + *      otherwise set to the next host to which the pkt must be routed
9796 + * If success, skb->dev is the output device to which the packet must 
9797 + * be sent and skb->dst is not NULL
9798 + *
9799 + * RETURN: -1 if an error occured
9800 + *          1 if the packet was succesfully routed to the 
9801 + *            destination desired
9802 + *          0 if the kernel routing table could not route the packet
9803 + *            according to the keys specified
9804 + */
9805 +static int route(struct sk_buff *skb,
9806 +                unsigned int ifindex,
9807 +                const struct ipt_route_target_info *route_info)
9808 +{
9809 +       int err;
9810 +       struct rtable *rt;
9811 +       struct iphdr *iph = skb->nh.iph;
9812 +       struct flowi fl = {
9813 +               .oif = ifindex,
9814 +               .nl_u = {
9815 +                       .ip4_u = {
9816 +                               .daddr = iph->daddr,
9817 +                               .saddr = 0,
9818 +                               .tos = RT_TOS(iph->tos),
9819 +                               .scope = RT_SCOPE_UNIVERSE,
9820 +                       }
9821 +               } 
9822 +       };
9823 +       
9824 +       /* The destination address may be overloaded by the target */
9825 +       if (route_info->gw)
9826 +               fl.fld_dst = route_info->gw;
9827 +       
9828 +       /* Trying to route the packet using the standard routing table. */
9829 +       if ((err = ip_route_output_key(&rt, &fl))) {
9830 +               if (net_ratelimit()) 
9831 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
9832 +               return -1;
9833 +       }
9834 +       
9835 +       /* Drop old route. */
9836 +       dst_release(skb->dst);
9837 +       skb->dst = NULL;
9838 +
9839 +       /* Success if no oif specified or if the oif correspond to the 
9840 +        * one desired */
9841 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
9842 +               skb->dst = &rt->u.dst;
9843 +               skb->dev = skb->dst->dev;
9844 +               return 1;
9845 +       }
9846 +       
9847 +       /* The interface selected by the routing table is not the one
9848 +        * specified by the user. This may happen because the dst address
9849 +        * is one of our own addresses.
9850 +        */
9851 +       if (net_ratelimit()) 
9852 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
9853 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
9854 +       
9855 +       return 0;
9856 +}
9857 +
9858 +
9859 +/* Stolen from ip_finish_output2
9860 + * PRE : skb->dev is set to the device we are leaving by
9861 + *       skb->dst is not NULL
9862 + * POST: the packet is sent with the link layer header pushed
9863 + *       the packet is destroyed
9864 + */
9865 +static void ip_direct_send(struct sk_buff *skb)
9866 +{
9867 +       struct dst_entry *dst = skb->dst;
9868 +       struct hh_cache *hh = dst->hh;
9869 +
9870 +       if (hh) {
9871 +               read_lock_bh(&hh->hh_lock);
9872 +               memcpy(skb->data - 16, hh->hh_data, 16);
9873 +               read_unlock_bh(&hh->hh_lock);
9874 +               skb_push(skb, hh->hh_len);
9875 +               hh->hh_output(skb);
9876 +       } else if (dst->neighbour)
9877 +               dst->neighbour->output(skb);
9878 +       else {
9879 +               if (net_ratelimit())
9880 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
9881 +               kfree_skb(skb);
9882 +       }
9883 +}
9884 +
9885 +
9886 +/* PRE : skb->dev is set to the device we are leaving by
9887 + * POST: - the packet is directly sent to the skb->dev device, without 
9888 + *         pushing the link layer header.
9889 + *       - the packet is destroyed
9890 + */
9891 +static inline int dev_direct_send(struct sk_buff *skb)
9892 +{
9893 +       return dev_queue_xmit(skb);
9894 +}
9895 +
9896 +
9897 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
9898 +                             struct sk_buff *skb) 
9899 +{
9900 +       unsigned int ifindex = 0;
9901 +       struct net_device *dev_out = NULL;
9902 +
9903 +       /* The user set the interface name to use.
9904 +        * Getting the current interface index.
9905 +        */
9906 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
9907 +               ifindex = dev_out->ifindex;
9908 +       } else {
9909 +               /* Unknown interface name : packet dropped */
9910 +               if (net_ratelimit()) 
9911 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
9912 +               return NF_DROP;
9913 +       }
9914 +
9915 +       /* Trying the standard way of routing packets */
9916 +       switch (route(skb, ifindex, route_info)) {
9917 +       case 1:
9918 +               dev_put(dev_out);
9919 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
9920 +                       return IPT_CONTINUE;
9921 +
9922 +               ip_direct_send(skb);
9923 +               return NF_STOLEN;
9924 +
9925 +       case 0:
9926 +               /* Failed to send to oif. Trying the hard way */
9927 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
9928 +                       return NF_DROP;
9929 +
9930 +               if (net_ratelimit()) 
9931 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
9932 +                              ifindex);
9933 +
9934 +               /* We have to force the use of an interface.
9935 +                * This interface must be a tunnel interface since
9936 +                * otherwise we can't guess the hw address for
9937 +                * the packet. For a tunnel interface, no hw address
9938 +                * is needed.
9939 +                */
9940 +               if ((dev_out->type != ARPHRD_TUNNEL)
9941 +                   && (dev_out->type != ARPHRD_IPGRE)) {
9942 +                       if (net_ratelimit()) 
9943 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
9944 +                       dev_put(dev_out);
9945 +                       return NF_DROP;
9946 +               }
9947 +       
9948 +               /* Send the packet. This will also free skb
9949 +                * Do not go through the POST_ROUTING hook because 
9950 +                * skb->dst is not set and because it will probably
9951 +                * get confused by the destination IP address.
9952 +                */
9953 +               skb->dev = dev_out;
9954 +               dev_direct_send(skb);
9955 +               dev_put(dev_out);
9956 +               return NF_STOLEN;
9957 +               
9958 +       default:
9959 +               /* Unexpected error */
9960 +               dev_put(dev_out);
9961 +               return NF_DROP;
9962 +       }
9963 +}
9964 +
9965 +
9966 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
9967 +                             struct sk_buff *skb) 
9968 +{
9969 +       struct net_device *dev_in = NULL;
9970 +
9971 +       /* Getting the current interface index. */
9972 +       if (!(dev_in = dev_get_by_name(route_info->iif))) {
9973 +               if (net_ratelimit()) 
9974 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
9975 +               return NF_DROP;
9976 +       }
9977 +
9978 +       skb->dev = dev_in;
9979 +       dst_release(skb->dst);
9980 +       skb->dst = NULL;
9981 +
9982 +       netif_rx(skb);
9983 +       dev_put(dev_in);
9984 +       return NF_STOLEN;
9985 +}
9986 +
9987 +
9988 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
9989 +                            struct sk_buff *skb) 
9990 +{
9991 +       if (route(skb, 0, route_info)!=1)
9992 +               return NF_DROP;
9993 +
9994 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
9995 +               return IPT_CONTINUE;
9996 +
9997 +       ip_direct_send(skb);
9998 +       return NF_STOLEN;
9999 +}
10000 +
10001 +
10002 +static unsigned int ipt_route_target(struct sk_buff **pskb,
10003 +                                    const struct net_device *in,
10004 +                                    const struct net_device *out,
10005 +                                    unsigned int hooknum,
10006 +                                    const void *targinfo,
10007 +                                    void *userinfo)
10008 +{
10009 +       const struct ipt_route_target_info *route_info = targinfo;
10010 +       struct sk_buff *skb = *pskb;
10011 +
10012 +       /* If we are at PREROUTING or INPUT hook
10013 +        * the TTL isn't decreased by the IP stack
10014 +        */
10015 +       if (hooknum == NF_IP_PRE_ROUTING ||
10016 +           hooknum == NF_IP_LOCAL_IN) {
10017 +
10018 +               struct iphdr *iph = skb->nh.iph;
10019 +
10020 +               if (iph->ttl <= 1) {
10021 +                       struct rtable *rt;
10022 +                       struct flowi fl = {
10023 +                               .oif = 0,
10024 +                               .nl_u = {
10025 +                                       .ip4_u = {
10026 +                                               .daddr = iph->daddr,
10027 +                                               .saddr = iph->saddr,
10028 +                                               .tos = RT_TOS(iph->tos),
10029 +                                               .scope = ((iph->tos & RTO_ONLINK) ?
10030 +                                                         RT_SCOPE_LINK :
10031 +                                                         RT_SCOPE_UNIVERSE)
10032 +                                       }
10033 +                               } 
10034 +                       };
10035 +
10036 +                       if (ip_route_output_key(&rt, &fl)) {
10037 +                               return NF_DROP;
10038 +                       }
10039 +
10040 +                       if (skb->dev == rt->u.dst.dev) {
10041 +                               /* Drop old route. */
10042 +                               dst_release(skb->dst);
10043 +                               skb->dst = &rt->u.dst;
10044 +
10045 +                               /* this will traverse normal stack, and 
10046 +                                * thus call conntrack on the icmp packet */
10047 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
10048 +                                         ICMP_EXC_TTL, 0);
10049 +                       }
10050 +
10051 +                       return NF_DROP;
10052 +               }
10053 +
10054 +               /*
10055 +                * If we are at INPUT the checksum must be recalculated since
10056 +                * the length could change as the result of a defragmentation.
10057 +                */
10058 +               if(hooknum == NF_IP_LOCAL_IN) {
10059 +                       iph->ttl = iph->ttl - 1;
10060 +                       iph->check = 0;
10061 +                       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
10062 +               } else {
10063 +                       ip_decrease_ttl(iph);
10064 +               }
10065 +       }
10066 +
10067 +       /* Tell conntrack to forget this packet since it may get confused 
10068 +        * when a packet is leaving with dst address == our address.
10069 +        * Good idea ? Dunno. Need advice.
10070 +        */
10071 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
10072 +               nf_conntrack_put(skb->nfct);
10073 +               skb->nfct = NULL;
10074 +               skb->nfcache = 0;
10075 +#ifdef CONFIG_NETFILTER_DEBUG
10076 +               skb->nf_debug = 0;
10077 +#endif
10078 +       }
10079 +
10080 +       if (route_info->oif[0] != '\0') 
10081 +               return route_oif(route_info, *pskb);
10082 +       
10083 +       if (route_info->iif[0] != '\0') 
10084 +               return route_iif(route_info, *pskb);
10085 +
10086 +       if (route_info->gw) 
10087 +               return route_gw(route_info, *pskb);
10088 +
10089 +       if (net_ratelimit()) 
10090 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
10091 +
10092 +       return IPT_CONTINUE;
10093 +}
10094 +
10095 +
10096 +static int ipt_route_checkentry(const char *tablename,
10097 +                               const struct ipt_entry *e,
10098 +                               void *targinfo,
10099 +                               unsigned int targinfosize,
10100 +                               unsigned int hook_mask)
10101 +{
10102 +       if (strcmp(tablename, "mangle") != 0) {
10103 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
10104 +                      tablename);
10105 +               return 0;
10106 +       }
10107 +
10108 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
10109 +                           | (1 << NF_IP_LOCAL_IN)
10110 +                           | (1 << NF_IP_FORWARD)
10111 +                           | (1 << NF_IP_LOCAL_OUT)
10112 +                           | (1 << NF_IP_POST_ROUTING))) {
10113 +               printk("ipt_ROUTE: bad hook\n");
10114 +               return 0;
10115 +       }
10116 +
10117 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
10118 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
10119 +                      targinfosize,
10120 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
10121 +               return 0;
10122 +       }
10123 +
10124 +       return 1;
10125 +}
10126 +
10127 +
10128 +static struct ipt_target ipt_route_reg = { 
10129 +       .name = "ROUTE",
10130 +       .target = ipt_route_target,
10131 +       .checkentry = ipt_route_checkentry,
10132 +       .me = THIS_MODULE,
10133 +};
10134 +
10135 +static int __init init(void)
10136 +{
10137 +       return ipt_register_target(&ipt_route_reg);
10138 +}
10139 +
10140 +
10141 +static void __exit fini(void)
10142 +{
10143 +       ipt_unregister_target(&ipt_route_reg);
10144 +}
10145 +
10146 +module_init(init);
10147 +module_exit(fini);
10148 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.7/net/ipv4/netfilter/ipt_TARPIT.c
10149 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TARPIT.c     1970-01-01 01:00:00.000000000 +0100
10150 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TARPIT.c 2004-06-25 12:21:29.280940360 +0200
10151 @@ -0,0 +1,290 @@
10152 +/* 
10153 + * Kernel module to capture and hold incoming TCP connections using 
10154 + * no local per-connection resources.
10155 + * 
10156 + * Based on ipt_REJECT.c and offering functionality similar to 
10157 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
10158 + * 
10159 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
10160 + * 
10161 + * This program is free software; you can redistribute it and/or modify
10162 + * it under the terms of the GNU General Public License as published by
10163 + * the Free Software Foundation; either version 2 of the License, or
10164 + * (at your option) any later version.
10165 + *
10166 + * This program is distributed in the hope that it will be useful,
10167 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10168 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10169 + * GNU General Public License for more details.
10170 + *
10171 + * You should have received a copy of the GNU General Public License
10172 + * along with this program; if not, write to the Free Software
10173 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10174 + * 
10175 + * Goal:
10176 + * - Allow incoming TCP connections to be established.
10177 + * - Passing data should result in the connection being switched to the 
10178 + *   persist state (0 byte window), in which the remote side stops sending 
10179 + *   data and asks to continue every 60 seconds.
10180 + * - Attempts to shut down the connection should be ignored completely, so 
10181 + *   the remote side ends up having to time it out.
10182 + *
10183 + * This means:
10184 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
10185 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
10186 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
10187 + */
10188 +
10189 +#include <linux/config.h>
10190 +#include <linux/module.h>
10191 +#include <linux/skbuff.h>
10192 +#include <linux/ip.h>
10193 +#include <net/ip.h>
10194 +#include <net/tcp.h>
10195 +#include <net/icmp.h>
10196 +struct in_device;
10197 +#include <net/route.h>
10198 +#include <linux/random.h>
10199 +#include <linux/netfilter_ipv4/ip_tables.h>
10200 +
10201 +#if 0
10202 +#define DEBUGP printk
10203 +#else
10204 +#define DEBUGP(format, args...)
10205 +#endif
10206 +
10207 +MODULE_LICENSE("GPL");
10208 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
10209 +
10210 +/* Stolen from ip_finish_output2 */
10211 +static int ip_direct_send(struct sk_buff *skb)
10212 +{
10213 +       struct dst_entry *dst = skb->dst;
10214 +       struct hh_cache *hh = dst->hh;
10215 +
10216 +       if (hh) {    
10217 +               read_lock_bh(&hh->hh_lock);
10218 +               memcpy(skb->data - 16, hh->hh_data, 16);
10219 +                read_unlock_bh(&hh->hh_lock);
10220 +                skb_push(skb, hh->hh_len);
10221 +                return hh->hh_output(skb);
10222 +        } else if (dst->neighbour)
10223 +                return dst->neighbour->output(skb);
10224 +
10225 +       if (net_ratelimit())
10226 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
10227 +        kfree_skb(skb);
10228 +        return -EINVAL;
10229 +}
10230 +
10231 +
10232 +/* Send reply */
10233 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
10234 +{
10235 +       struct sk_buff *nskb;
10236 +       struct rtable *nrt;
10237 +       struct tcphdr *otcph, *ntcph;
10238 +       struct flowi fl = {};
10239 +       unsigned int otcplen;
10240 +       u_int16_t tmp;
10241 +
10242 +       /* A truncated TCP header isn't going to be useful */
10243 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
10244 +               return;
10245 +
10246 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
10247 +                                  + oskb->nh.iph->ihl);
10248 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
10249 +
10250 +       /* No replies for RST or FIN */
10251 +       if (otcph->rst || otcph->fin)
10252 +               return;
10253 +
10254 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
10255 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
10256 +               return;
10257 +
10258 +       /* Check checksum. */
10259 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
10260 +                        oskb->nh.iph->daddr,
10261 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
10262 +               return;
10263 +
10264 +       /* Copy skb (even if skb is about to be dropped, we can't just
10265 +           clone it because there may be other things, such as tcpdump,
10266 +           interested in it) */
10267 +       nskb = skb_copy(oskb, GFP_ATOMIC);
10268 +       if (!nskb)
10269 +               return;
10270 +
10271 +       /* This packet will not be the same as the other: clear nf fields */
10272 +       nf_conntrack_put(nskb->nfct);
10273 +       nskb->nfct = NULL;
10274 +       nskb->nfcache = 0;
10275 +#ifdef CONFIG_NETFILTER_DEBUG
10276 +       nskb->nf_debug = 0;
10277 +#endif
10278 +
10279 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
10280 +
10281 +       /* Truncate to length (no data) */
10282 +       ntcph->doff = sizeof(struct tcphdr)/4;
10283 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
10284 +       nskb->nh.iph->tot_len = htons(nskb->len);
10285 +
10286 +       /* Swap source and dest */
10287 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
10288 +       tmp = ntcph->source;
10289 +       ntcph->source = ntcph->dest;
10290 +       ntcph->dest = tmp;
10291 +
10292 +       /* Use supplied sequence number or make a new one */
10293 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
10294 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
10295 +                                                       nskb->nh.iph->daddr, 
10296 +                                                       ntcph->source, 
10297 +                                                       ntcph->dest));
10298 +
10299 +       /* Our SYN-ACKs must have a >0 window */
10300 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
10301 +
10302 +       ntcph->urg_ptr = 0;
10303 +
10304 +       /* Reset flags */
10305 +       ((u_int8_t *)ntcph)[13] = 0;
10306 +
10307 +       if (otcph->syn && otcph->ack) {
10308 +               ntcph->rst = 1;
10309 +               ntcph->ack_seq = 0;
10310 +       } else {
10311 +               ntcph->syn = otcph->syn;
10312 +               ntcph->ack = 1;
10313 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
10314 +       }
10315 +
10316 +       /* Adjust TCP checksum */
10317 +       ntcph->check = 0;
10318 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
10319 +                                  nskb->nh.iph->saddr,
10320 +                                  nskb->nh.iph->daddr,
10321 +                                  csum_partial((char *)ntcph,
10322 +                                               sizeof(struct tcphdr), 0));
10323 +
10324 +       /* Adjust IP TTL */
10325 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
10326 +
10327 +       /* Set DF, id = 0 */
10328 +       nskb->nh.iph->frag_off = htons(IP_DF);
10329 +       nskb->nh.iph->id = 0;
10330 +
10331 +       /* Adjust IP checksum */
10332 +       nskb->nh.iph->check = 0;
10333 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
10334 +                                          nskb->nh.iph->ihl);
10335 +
10336 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
10337 +       fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
10338 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
10339 +       fl.oif = 0;
10340 +
10341 +       if (ip_route_output_key(&nrt, &fl))
10342 +               goto free_nskb;
10343 +
10344 +       dst_release(nskb->dst);
10345 +       nskb->dst = &nrt->u.dst;
10346 +
10347 +       /* "Never happens" */
10348 +       if (nskb->len > dst_pmtu(nskb->dst))
10349 +               goto free_nskb;
10350 +
10351 +       ip_direct_send (nskb);
10352 +
10353 +       return;
10354 +
10355 + free_nskb:
10356 +       kfree_skb(nskb);
10357 +}
10358 +
10359 +
10360 +static unsigned int tarpit(struct sk_buff **pskb,
10361 +                          const struct net_device *in,
10362 +                          const struct net_device *out,
10363 +                          unsigned int hooknum,
10364 +                          const void *targinfo,
10365 +                          void *userinfo)
10366 +{
10367 +       struct sk_buff *skb = *pskb;
10368 +       struct rtable *rt = (struct rtable*)skb->dst;
10369 +
10370 +       /* Do we have an input route cache entry? */
10371 +       if (!rt)
10372 +               return NF_DROP;
10373 +
10374 +        /* No replies to physical multicast/broadcast */
10375 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
10376 +               return NF_DROP;
10377 +
10378 +        /* Now check at the protocol level */
10379 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
10380 +                return NF_DROP;
10381 +
10382 +       /* Our naive response construction doesn't deal with IP
10383 +           options, and probably shouldn't try. */
10384 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
10385 +               return NF_DROP;
10386 +
10387 +        /* We aren't interested in fragments */
10388 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
10389 +                return NF_DROP;
10390 +
10391 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
10392 +
10393 +       return NF_DROP;
10394 +}
10395 +
10396 +
10397 +static int check(const char *tablename,
10398 +                const struct ipt_entry *e,
10399 +                void *targinfo,
10400 +                unsigned int targinfosize,
10401 +                unsigned int hook_mask)
10402 +{
10403 +       /* Only allow these for input/forward packet filtering. */
10404 +       if (strcmp(tablename, "filter") != 0) {
10405 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
10406 +               return 0;
10407 +       }
10408 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
10409 +                           | (1 << NF_IP_FORWARD))) != 0) {
10410 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
10411 +               return 0;
10412 +       }
10413 +
10414 +       /* Must specify that it's a TCP packet */
10415 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
10416 +               DEBUGP("TARPIT: not valid for non-tcp\n");
10417 +               return 0;
10418 +       }
10419 +
10420 +       return 1;
10421 +}
10422 +
10423 +static struct ipt_target ipt_tarpit_reg = { 
10424 +       .name = "TARPIT",
10425 +       .target = tarpit,
10426 +       .checkentry = check,
10427 +       .me = THIS_MODULE
10428 +};
10429 +
10430 +static int __init init(void)
10431 +{
10432 +       return ipt_register_target(&ipt_tarpit_reg);
10433 +}
10434 +
10435 +static void __exit fini(void)
10436 +{
10437 +       ipt_unregister_target(&ipt_tarpit_reg);
10438 +}
10439 +
10440 +module_init(init);
10441 +module_exit(fini);
10442 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.7/net/ipv4/netfilter/ipt_TRACE.c
10443 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TRACE.c      1970-01-01 01:00:00.000000000 +0100
10444 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TRACE.c  2004-06-25 12:21:30.341779088 +0200
10445 @@ -0,0 +1,64 @@
10446 +/* This is a module which is used for setting 
10447 + * the NFC_TRACE flag in the nfcache field of an skb. 
10448 + */
10449 +#include <linux/module.h>
10450 +#include <linux/skbuff.h>
10451 +
10452 +#include <linux/netfilter_ipv4/ip_tables.h>
10453 +
10454 +static unsigned int
10455 +target(struct sk_buff **pskb,
10456 +       const struct net_device *in,
10457 +       const struct net_device *out,
10458 +       unsigned int hooknum,
10459 +       const void *targinfo,
10460 +       void *userinfo)
10461 +{
10462 +       (*pskb)->nfcache |= NFC_TRACE;
10463 +       return IPT_CONTINUE;
10464 +}
10465 +
10466 +static int
10467 +checkentry(const char *tablename,
10468 +          const struct ipt_entry *e,
10469 +           void *targinfo,
10470 +           unsigned int targinfosize,
10471 +           unsigned int hook_mask)
10472 +{
10473 +       if (targinfosize != 0) {
10474 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
10475 +                      targinfosize);
10476 +               return 0;
10477 +       }
10478 +
10479 +       if (strcmp(tablename, "raw") != 0) {
10480 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
10481 +               return 0;
10482 +       }
10483 +
10484 +       return 1;
10485 +}
10486 +
10487 +static struct ipt_target ipt_trace_reg = { 
10488 +       .name = "TRACE", 
10489 +       .target = target, 
10490 +       .checkentry = checkentry, 
10491 +       .me = THIS_MODULE
10492 +};
10493 +
10494 +static int __init init(void)
10495 +{
10496 +       if (ipt_register_target(&ipt_trace_reg))
10497 +               return -EINVAL;
10498 +
10499 +       return 0;
10500 +}
10501 +
10502 +static void __exit fini(void)
10503 +{
10504 +       ipt_unregister_target(&ipt_trace_reg);
10505 +}
10506 +
10507 +module_init(init);
10508 +module_exit(fini);
10509 +MODULE_LICENSE("GPL");
10510 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c
10511 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c        1970-01-01 01:00:00.000000000 +0100
10512 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c    2004-06-25 12:21:07.942184344 +0200
10513 @@ -0,0 +1,120 @@
10514 +/* TTL modification target for IP tables
10515 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
10516 + *
10517 + * Version: $Revision$
10518 + *
10519 + * This software is distributed under the terms of GNU GPL
10520 + */
10521 +
10522 +#include <linux/module.h>
10523 +#include <linux/skbuff.h>
10524 +#include <linux/ip.h>
10525 +#include <net/checksum.h>
10526 +
10527 +#include <linux/netfilter_ipv4/ip_tables.h>
10528 +#include <linux/netfilter_ipv4/ipt_TTL.h>
10529 +
10530 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
10531 +MODULE_DESCRIPTION("IP tables TTL modification module");
10532 +MODULE_LICENSE("GPL");
10533 +
10534 +static unsigned int 
10535 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 
10536 +               const struct net_device *out, unsigned int hooknum, 
10537 +               const void *targinfo, void *userinfo)
10538 +{
10539 +       struct iphdr *iph;
10540 +       const struct ipt_TTL_info *info = targinfo;
10541 +       u_int16_t diffs[2];
10542 +       int new_ttl;
10543 +
10544 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
10545 +               return NF_DROP;
10546 +
10547 +       iph = (*pskb)->nh.iph;
10548 +                        
10549 +       switch (info->mode) {
10550 +               case IPT_TTL_SET:
10551 +                       new_ttl = info->ttl;
10552 +                       break;
10553 +               case IPT_TTL_INC:
10554 +                       new_ttl = iph->ttl + info->ttl;
10555 +                       if (new_ttl > 255)
10556 +                               new_ttl = 255;
10557 +                       break;
10558 +               case IPT_TTL_DEC:
10559 +                       new_ttl = iph->ttl + info->ttl;
10560 +                       if (new_ttl < 0)
10561 +                               new_ttl = 0;
10562 +                       break;
10563 +               default:
10564 +                       new_ttl = iph->ttl;
10565 +                       break;
10566 +       }
10567 +
10568 +       if (new_ttl != iph->ttl) {
10569 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
10570 +               iph->ttl = new_ttl;
10571 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
10572 +               iph->check = csum_fold(csum_partial((char *)diffs,
10573 +                                                   sizeof(diffs),
10574 +                                                   iph->check^0xFFFF));
10575 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
10576 +       }
10577 +
10578 +       return IPT_CONTINUE;
10579 +}
10580 +
10581 +static int ipt_ttl_checkentry(const char *tablename,
10582 +               const struct ipt_entry *e,
10583 +               void *targinfo,
10584 +               unsigned int targinfosize,
10585 +               unsigned int hook_mask)
10586 +{
10587 +       struct ipt_TTL_info *info = targinfo;
10588 +
10589 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
10590 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
10591 +                               targinfosize,
10592 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
10593 +               return 0;       
10594 +       }       
10595 +
10596 +       if (strcmp(tablename, "mangle")) {
10597 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
10598 +               return 0;
10599 +       }
10600 +
10601 +       if (info->mode > IPT_TTL_MAXMODE) {
10602 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
10603 +                       info->mode);
10604 +               return 0;
10605 +       }
10606 +
10607 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
10608 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
10609 +               return 0;
10610 +       }
10611 +       
10612 +       return 1;
10613 +}
10614 +
10615 +static struct ipt_target ipt_TTL = { 
10616 +       .name = "TTL",
10617 +       .target = ipt_ttl_target, 
10618 +       .checkentry = ipt_ttl_checkentry, 
10619 +       .me = THIS_MODULE 
10620 +};
10621 +
10622 +static int __init init(void)
10623 +{
10624 +       return ipt_register_target(&ipt_TTL);
10625 +}
10626 +
10627 +static void __exit fini(void)
10628 +{
10629 +       ipt_unregister_target(&ipt_TTL);
10630 +}
10631 +
10632 +module_init(init);
10633 +module_exit(fini);
10634 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.7/net/ipv4/netfilter/ipt_XOR.c
10635 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_XOR.c        1970-01-01 01:00:00.000000000 +0100
10636 +++ linux-2.6.7/net/ipv4/netfilter/ipt_XOR.c    2004-06-25 12:21:31.655579360 +0200
10637 @@ -0,0 +1,117 @@
10638 +/* XOR target for IP tables
10639 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
10640 + * Based on ipt_TTL.c
10641 + *
10642 + * Version 1.0
10643 + *
10644 + * This software is distributed under the terms of GNU GPL
10645 + */
10646 +
10647 +#include <linux/module.h>
10648 +#include <linux/skbuff.h>
10649 +#include <linux/ip.h>
10650 +#include <linux/tcp.h>
10651 +#include <linux/udp.h>
10652 +
10653 +#include <linux/netfilter_ipv4/ip_tables.h>
10654 +#include <linux/netfilter_ipv4/ipt_XOR.h>
10655 +
10656 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
10657 +MODULE_DESCRIPTION("IP tables XOR module");
10658 +MODULE_LICENSE("GPL");
10659 +
10660 +static unsigned int 
10661 +ipt_xor_target(struct sk_buff **pskb, 
10662 +               const struct net_device *in, const struct net_device *out, 
10663 +               unsigned int hooknum, const void *targinfo, void *userinfo)
10664 +{
10665 +       struct ipt_XOR_info *info = (void *) targinfo;
10666 +       struct iphdr *iph;
10667 +       struct tcphdr *tcph;
10668 +       struct udphdr *udph;
10669 +       int i, j, k;
10670 +
10671 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
10672 +               return NF_DROP;
10673 +
10674 +       iph = (*pskb)->nh.iph;
10675 +  
10676 +       if (iph->protocol == IPPROTO_TCP) {
10677 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
10678 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
10679 +                       for (k=0; k<=info->block_size; k++) {
10680 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
10681 +                                               info->key[j];
10682 +                               i++;
10683 +                       }
10684 +                       j++;
10685 +                       if (info->key[j] == 0x00)
10686 +                               j = 0;
10687 +               }
10688 +       } else if (iph->protocol == IPPROTO_UDP) {
10689 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
10690 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
10691 +                       for (k=0; k<=info->block_size; k++) {
10692 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
10693 +                                               info->key[j];
10694 +                               i++;
10695 +                       }
10696 +                       j++;
10697 +                       if (info->key[j] == 0x00)
10698 +                               j = 0;
10699 +               }
10700 +       }
10701 +  
10702 +       return IPT_CONTINUE;
10703 +}
10704 +
10705 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
10706 +               void *targinfo, unsigned int targinfosize, 
10707 +               unsigned int hook_mask)
10708 +{
10709 +       struct ipt_XOR_info *info = targinfo;
10710 +
10711 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
10712 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
10713 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
10714 +               return 0;
10715 +       }       
10716 +
10717 +       if (strcmp(tablename, "mangle")) {
10718 +               printk(KERN_WARNING "XOR: can only be called from"
10719 +                               "\"mangle\" table, not \"%s\"\n", tablename);
10720 +               return 0; 
10721 +       }
10722 +
10723 +       if (!strcmp(info->key, "")) {
10724 +               printk(KERN_WARNING "XOR: You must specify a key");
10725 +               return 0;
10726 +       }
10727 +
10728 +       if (info->block_size == 0) {
10729 +               printk(KERN_WARNING "XOR: You must specify a block-size");
10730 +               return 0;
10731 +       }
10732 +
10733 +       return 1;
10734 +}
10735 +
10736 +static struct ipt_target ipt_XOR = { 
10737 +       .name = "XOR",
10738 +       .target = ipt_xor_target, 
10739 +       .checkentry = ipt_xor_checkentry,
10740 +       .me = THIS_MODULE,
10741 +};
10742 +
10743 +static int __init init(void)
10744 +{
10745 +       return ipt_register_target(&ipt_XOR);
10746 +}
10747 +
10748 +static void __exit fini(void)
10749 +{
10750 +       ipt_unregister_target(&ipt_XOR);
10751 +}
10752 +
10753 +module_init(init);
10754 +module_exit(fini);
10755 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_account.c linux-2.6.7/net/ipv4/netfilter/ipt_account.c
10756 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_account.c    1970-01-01 01:00:00.000000000 +0100
10757 +++ linux-2.6.7/net/ipv4/netfilter/ipt_account.c        2004-06-25 12:21:32.614433592 +0200
10758 @@ -0,0 +1,617 @@
10759 +/* 
10760 + * accounting match (ipt_account.c)
10761 + * (C) 2003,2004 by Piotr Gasid³o (quaker@barbara.eu.org)
10762 + *
10763 + * Version: 0.1.5
10764 + *
10765 + * This software is distributed under the terms of GNU GPL
10766 + */
10767 +
10768 +#include <linux/module.h>
10769 +#include <linux/skbuff.h>
10770 +#include <linux/proc_fs.h>
10771 +#include <linux/spinlock.h>
10772 +#include <linux/vmalloc.h>
10773 +#include <linux/interrupt.h>
10774 +
10775 +#include <asm/uaccess.h>
10776 +
10777 +#include <linux/ip.h>
10778 +#include <linux/tcp.h>
10779 +#include <linux/udp.h>
10780 +
10781 +#include <linux/netfilter_ipv4/ip_tables.h>
10782 +#include <linux/netfilter_ipv4/ipt_account.h>
10783 +
10784 +static char version[] =
10785 +KERN_INFO "ipt_account 0.1.5 : Piotr Gasid³o <quaker@barbara.eu.org>, http://www.barbara.eu.org/~quaker/ipt_account/\n";
10786 +
10787 +/* default rights for files created in /proc/net/ipt_account/ */
10788 +static int ip_list_perms = 0644;
10789 +
10790 +/* 
10791 + * safe netmask, if you want account traffic for networks 
10792 + * bigger that /17 you must specify ip_list_max_hosts parameter 
10793 + * during load 
10794 + */
10795 +static int ip_list_max_mask = 17;
10796 +static int ip_list_max_hosts_count;
10797 +static int debug = 0;
10798 +
10799 +/* module information */
10800 +MODULE_AUTHOR("Piotr Gasid³o <quaker@barbara.eu.org>");
10801 +MODULE_DESCRIPTION("Traffic accounting modules");
10802 +MODULE_LICENSE("GPL");
10803 +MODULE_PARM(ip_list_perms,"i");
10804 +MODULE_PARM_DESC(ip_list_perms,"permissions on /proc/net/ipt_account/* files");
10805 +MODULE_PARM(ip_list_max_mask, "i");
10806 +MODULE_PARM_DESC(ip_list_max_mask, "maximum *save* size of one list (netmask)");
10807 +#ifdef DEBUG
10808 +MODULE_PARM(debug,"i");
10809 +MODULE_PARM_DESC(debug,"debugging level, defaults to 0");
10810 +#endif
10811 +
10812 +/* structure with statistics counters */
10813 +struct t_ipt_account_stat {
10814 +       u_int64_t b_all, b_tcp, b_udp, b_icmp, b_other;         /* byte counters for all/tcp/udp/icmp/other traffic  */
10815 +       u_int64_t p_all, p_tcp, p_udp, p_icmp, p_other;         /* packet counters for all/tcp/udp/icmp/other traffic */
10816 +};
10817
10818 +/* structure holding to/from statistics for single ip */
10819 +struct t_ipt_account_ip_list {
10820 +       struct t_ipt_account_stat src;
10821 +       struct t_ipt_account_stat dest;
10822 +};
10823 +
10824 +/* structure describing single table */
10825 +struct t_ipt_account_table {
10826 +       char name[IPT_ACCOUNT_NAME_LEN];        /* table name ( = filename in /proc/net/ipt_account/) */
10827 +       struct t_ipt_account_ip_list *ip_list;  /* table with statistics for each ip in network/netmask */
10828 +       struct t_ipt_account_table *next;
10829 +       u_int32_t network;                      /* network/netmask covered by table*/
10830 +       u_int32_t netmask;                                      
10831 +       int use_count;                          /* rules counter - counting number of rules using this table */
10832 +       spinlock_t ip_list_lock;
10833 +       struct proc_dir_entry *status_proc_64, *status_proc_32;
10834 +};
10835 +
10836 +/* we must use spinlocks to avoid parallel modifications of table list */
10837 +static spinlock_t ipt_account_tables_lock = SPIN_LOCK_UNLOCKED;
10838 +
10839 +static struct proc_dir_entry *proc_net_ipt_account = NULL;
10840 +
10841 +/* root pointer holding list of the tables */
10842 +static struct t_ipt_account_table *ipt_account_tables = NULL;
10843 +
10844 +static int ip_list_read_proc_64(char *buffer, char **start, off_t offset,
10845 +               int length, int *eof, void *data) {
10846 +       
10847 +       int len = 0, last_len = 0;
10848 +       off_t pos = 0, begin = 0;
10849 +
10850 +       u_int32_t address, index;       
10851 +
10852 +       struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
10853 +
10854 +       spin_lock(&table->ip_list_lock);
10855 +       for (address = table->network; (u_int32_t)(address & table->netmask) == (u_int32_t)(table->network); address++) {
10856 +               last_len = len;         
10857 +               index = address - table->network;
10858 +                       len += sprintf(buffer + len,
10859 +                               "ip = %u.%u.%u.%u bytes_src = %llu %llu %llu %llu %llu packets_src = %llu %llu %llu %llu %llu bytes_dest = %llu %llu %llu %llu %llu packets_dest = %llu %llu %llu %llu %llu\n",
10860 +                               HIPQUAD(address),
10861 +                               table->ip_list[index].src.b_all,
10862 +                               table->ip_list[index].src.b_tcp,
10863 +                               table->ip_list[index].src.b_udp,
10864 +                               table->ip_list[index].src.b_icmp,
10865 +                               table->ip_list[index].src.b_other,
10866 +                               
10867 +                               table->ip_list[index].src.p_all,
10868 +                               table->ip_list[index].src.p_tcp,
10869 +                               table->ip_list[index].src.p_udp,
10870 +                               table->ip_list[index].src.p_icmp,
10871 +                               table->ip_list[index].src.p_other,
10872 +                               
10873 +                               table->ip_list[index].dest.b_all,
10874 +                               table->ip_list[index].dest.b_tcp,
10875 +                               table->ip_list[index].dest.b_udp,
10876 +                               table->ip_list[index].dest.b_icmp,
10877 +                               table->ip_list[index].dest.b_other,                             
10878 +                               
10879 +                               table->ip_list[index].dest.p_all,
10880 +                               table->ip_list[index].dest.p_tcp,
10881 +                               table->ip_list[index].dest.p_udp,
10882 +                               table->ip_list[index].dest.p_icmp,
10883 +                               table->ip_list[index].dest.p_other
10884 +                               );
10885 +               pos = begin + len;
10886 +               if (pos < offset) {
10887 +                       len = 0;
10888 +                       begin = pos;
10889 +               }
10890 +               if (pos > offset + length) {
10891 +                       len = last_len;
10892 +                       break;
10893 +               }
10894 +       }
10895 +       spin_unlock(&table->ip_list_lock);
10896 +       *start = buffer + (offset - begin);
10897 +       len -= (offset - begin);
10898 +       if (len > length)
10899 +               len = length;
10900 +       return len;
10901 +}
10902 +
10903 +static int ip_list_read_proc_32(char *buffer, char **start, off_t offset,
10904 +               int length, int *eof, void *data) {
10905 +       
10906 +       int len = 0, last_len = 0;
10907 +       off_t pos = 0, begin = 0;
10908 +
10909 +       u_int32_t address, index;
10910 +
10911 +       struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
10912 +       
10913 +       spin_lock(&table->ip_list_lock);
10914 +       for (address = table->network; (u_int32_t)(address & table->netmask) == (u_int32_t)(table->network); address++) {
10915 +               last_len = len; 
10916 +               index = address - table->network;
10917 +               len += sprintf(buffer + len,
10918 +                               "ip = %u.%u.%u.%u bytes_src = %u %u %u %u %u packets_src = %u %u %u %u %u bytes_dest = %u %u %u %u %u packets_dest = %u %u %u %u %u\n",
10919 +                               HIPQUAD(address),
10920 +                               (u_int32_t)table->ip_list[index].src.b_all,
10921 +                               (u_int32_t)table->ip_list[index].src.b_tcp,
10922 +                               (u_int32_t)table->ip_list[index].src.b_udp,
10923 +                               (u_int32_t)table->ip_list[index].src.b_icmp,
10924 +                               (u_int32_t)table->ip_list[index].src.b_other,
10925 +                               
10926 +                               (u_int32_t)table->ip_list[index].src.p_all,
10927 +                               (u_int32_t)table->ip_list[index].src.p_tcp,
10928 +                               (u_int32_t)table->ip_list[index].src.p_udp,
10929 +                               (u_int32_t)table->ip_list[index].src.p_icmp,
10930 +                               (u_int32_t)table->ip_list[index].src.p_other,
10931 +                               
10932 +                               (u_int32_t)table->ip_list[index].dest.b_all,
10933 +                               (u_int32_t)table->ip_list[index].dest.b_tcp,
10934 +                               (u_int32_t)table->ip_list[index].dest.b_udp,
10935 +                               (u_int32_t)table->ip_list[index].dest.b_icmp,
10936 +                               (u_int32_t)table->ip_list[index].dest.b_other,
10937 +                               
10938 +                               (u_int32_t)table->ip_list[index].dest.p_all,
10939 +                               (u_int32_t)table->ip_list[index].dest.p_tcp,
10940 +                               (u_int32_t)table->ip_list[index].dest.p_udp,
10941 +                               (u_int32_t)table->ip_list[index].dest.p_icmp,
10942 +                               (u_int32_t)table->ip_list[index].dest.p_other
10943 +               
10944 +                       );
10945 +               pos = begin + len;
10946 +               if (pos < offset) {
10947 +                       len = 0;
10948 +                       begin = pos;
10949 +               }
10950 +               if (pos > offset + length) {
10951 +                       len = last_len;
10952 +                       break;
10953 +               }               
10954 +       }
10955 +       spin_unlock(&table->ip_list_lock);                              
10956 +       *start = buffer + (offset - begin);
10957 +       len -= (offset - begin);
10958 +       if (len > length)
10959 +               len = length;
10960 +       return len;
10961 +}
10962 +
10963 +static int ip_list_write_proc(struct file *file, const char *buffer, 
10964 +               unsigned long length, void *data) {
10965 +
10966 +       int len = (length > 1024) ? length : 1024;
10967 +       struct t_ipt_account_table *table = (struct t_ipt_account_table*)data;
10968 +       char kernel_buffer[1024];
10969 +       u_int32_t hosts_count = INADDR_BROADCAST - table->netmask + 1;
10970 +       
10971 +       copy_from_user(kernel_buffer, buffer, len);
10972 +       kernel_buffer[len - 1] = 0;
10973 +       
10974 +       /* echo "reset" > /proc/net/ipt_recent/table clears the table */
10975 +       if (!strncmp(kernel_buffer, "reset", len)) {
10976 +               spin_lock(&table->ip_list_lock);
10977 +               memset(table->ip_list, 0, sizeof(struct t_ipt_account_ip_list) * hosts_count);
10978 +               spin_unlock(&table->ip_list_lock);
10979 +       }
10980 +       
10981 +       return len;
10982 +}
10983 +
10984 +/* do raw accounting */
10985 +static void do_account(struct t_ipt_account_stat *stat, u_int8_t proto, u_int16_t pktlen) {
10986 +       
10987 +       /* update packet & bytes counters in *stat structure */
10988 +       stat->b_all += pktlen;
10989 +       stat->p_all++;
10990 +       
10991 +       switch (proto) {
10992 +               case IPPROTO_TCP:
10993 +                       stat->b_tcp += pktlen;
10994 +                       stat->p_tcp++;
10995 +                       break;
10996 +               case IPPROTO_UDP:
10997 +                       stat->b_udp += pktlen;
10998 +                       stat->p_udp++;
10999 +                       break;
11000 +               case IPPROTO_ICMP:
11001 +                       stat->b_icmp += pktlen;
11002 +                       stat->p_icmp++;
11003 +                       break;
11004 +               default:
11005 +                       stat->b_other += pktlen;
11006 +                       stat->p_other++;
11007 +       }
11008 +}
11009 +
11010 +static int match(const struct sk_buff *skb,
11011 +         const struct net_device *in,
11012 +         const struct net_device *out,
11013 +         const void *matchinfo,
11014 +         int offset,
11015 +         const void *hdr,
11016 +         u_int16_t datalen,
11017 +         int *hotdrop)
11018 +{
11019 +       
11020 +       const struct t_ipt_account_info *info = (struct t_ipt_account_info*)matchinfo;
11021 +       struct t_ipt_account_table *table;
11022 +       int ret;
11023 +
11024 +       u_int32_t address;
11025 +       u_int16_t pktlen;
11026 +       u_int8_t proto;
11027 +       
11028 +       if (debug) {
11029 +               printk(KERN_INFO "ipt_account: match() entering.\n");
11030 +               printk(KERN_INFO "ipt_account: match() match name = %s.\n", info->name);
11031 +       }
11032 +       
11033 +       spin_lock(&ipt_account_tables_lock);
11034 +       /* find the right table */
11035 +       table = ipt_account_tables;
11036 +       while (table && strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
11037 +       spin_unlock(&ipt_account_tables_lock);
11038 +
11039 +       if (table == NULL) {
11040 +               /* ups, no table with that name */
11041 +               if (debug)
11042 +                       printk(KERN_INFO "ipt_account: match() table %s not found. Leaving.\n", info->name);
11043 +               return 0;
11044 +       }
11045 +
11046 +       if (debug)
11047 +               printk(KERN_INFO "ipt_account: match() table found %s\n", table->name);
11048 +
11049 +       /* default: no match */
11050 +       ret = 0;
11051 +
11052 +       /* get packet protocol/length */
11053 +       pktlen = skb->len;
11054 +       proto = skb->nh.iph->protocol;
11055 +
11056 +       if (debug)
11057 +               printk(KERN_INFO "ipt_account: match() got packet src = %u.%u.%u.%u, dst = %u.%u.%u.%u, proto = %u.\n",
11058 +                                NIPQUAD(skb->nh.iph->saddr),
11059 +                                NIPQUAD(skb->nh.iph->daddr),
11060 +                                proto
11061 +                                );
11062 +
11063 +       /* check whether traffic from source ip address ... */
11064 +       address = ntohl(skb->nh.iph->saddr);
11065 +       
11066 +       /* ... is being accounted by this table */      
11067 +       if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {          
11068 +               if (debug)
11069 +                       printk(KERN_INFO "ipt_account: match() accounting packet src = %u.%u.%u.%u, proto = %u.\n",
11070 +                                        HIPQUAD(address),
11071 +                                        proto
11072 +                                        );
11073 +               /* yes, account this packet */
11074 +               spin_lock(&table->ip_list_lock);
11075 +               /* update counters this host */
11076 +               do_account(&table->ip_list[(u_int32_t)(address - table->network)].src, proto, pktlen);
11077 +               /* update counters for all hosts in this table (network address) */
11078 +               if (table->netmask != INADDR_BROADCAST)
11079 +                       do_account(&table->ip_list[0].src, proto, pktlen);
11080 +               spin_unlock(&table->ip_list_lock);
11081 +               /* yes, it's a match */
11082 +               ret = 1;
11083 +       }
11084 +
11085 +       /* do the same thing with destination ip address */
11086 +       address = ntohl(skb->nh.iph->daddr);
11087 +    if (address && ((u_int32_t)(address & table->netmask) == (u_int32_t)table->network)) {
11088 +               if (debug)
11089 +                       printk(KERN_INFO "ipt_account: match() accounting packet dst = %u.%u.%u.%u, proto = %u.\n",
11090 +                                       HIPQUAD(address),
11091 +                                       proto
11092 +                                       );
11093 +               spin_lock(&table->ip_list_lock);
11094 +               do_account(&table->ip_list[(u_int32_t)(address - table->network)].dest, proto, pktlen);
11095 +               if (table->netmask != INADDR_BROADCAST)
11096 +                       do_account(&table->ip_list[0].dest, proto, pktlen);
11097 +               spin_unlock(&table->ip_list_lock);
11098 +               ret = 1;
11099 +       
11100 +       }
11101 +
11102 +       if (debug)
11103 +               printk(KERN_INFO "ipt_account: match() leaving.\n");    
11104 +       
11105 +       return ret;
11106 +       
11107 +}
11108 +
11109 +static int checkentry(const char *tablename,
11110 +              const struct ipt_ip *ip,
11111 +              void *matchinfo,
11112 +              unsigned int matchinfosize,
11113 +              unsigned int hook_mask)
11114 +{
11115 +       const struct t_ipt_account_info *info = matchinfo;
11116 +       struct t_ipt_account_table *table;
11117 +
11118 +       char proc_entry_name[IPT_ACCOUNT_NAME_LEN + 3];
11119 +
11120 +       u_int32_t hosts_count;
11121 +
11122 +       if (debug)
11123 +               printk(KERN_INFO "ipt_account: checkentry() entering.\n");
11124 +
11125 +       if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info)))
11126 +               return 0;
11127 +       
11128 +       if (!info->name || !info->name[0])
11129 +               return 0;
11130 +
11131 +       /* find whether table with this name already exists */
11132 +       spin_lock(&ipt_account_tables_lock);
11133 +       table = ipt_account_tables;
11134 +       while (table && strncmp(info->name, table->name, IPT_ACCOUNT_NAME_LEN) && (table = table->next));
11135 +       
11136 +       if (table) {
11137 +               /* yes, table exists */
11138 +               if (info->network != table->network || info->netmask != table->netmask) {
11139 +                       /* 
11140 +                        * tried to do accounting in existing table, but network/netmask in iptable rule
11141 +                        * doesn't match network/netmask in table structure - deny adding the rule 
11142 +                        */
11143 +                       printk(KERN_ERR "ipt_account: checkentry() table %s found. But table netmask/network %u.%u.%u.%u/%u.%u.%u.%u differs from rule netmask/network %u.%u.%u.%u/%u.%u.%u.%u. Leaving without creating entry.\n", 
11144 +                                       table->name,
11145 +                                       HIPQUAD(table->network),
11146 +                                       HIPQUAD(table->netmask),
11147 +                                       HIPQUAD(info->network),
11148 +                                       HIPQUAD(info->netmask)
11149 +                                       );
11150 +                       spin_unlock(&ipt_account_tables_lock);
11151 +                       return 0;
11152 +               }                       
11153 +               if (debug)
11154 +                       printk(KERN_INFO "ipt_account: checkentry() table %s found. Incrementing use count (use_count = %i). Leaving.\n", table->name, table->use_count);
11155 +               /* increase table use count */          
11156 +               table->use_count++;
11157 +               spin_unlock(&ipt_account_tables_lock);
11158 +               /* everything went okey */
11159 +               return 1;
11160 +       };
11161 +       
11162 +       if (debug)
11163 +               printk(KERN_INFO "ipt_account: checkentry() table %s not found. Creating.\n", info->name);
11164 +       
11165 +       /* table doesn't exist - create one */
11166 +       table = vmalloc(sizeof(struct t_ipt_account_table));
11167 +       if (table == NULL) {
11168 +           if (debug)
11169 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (t_account_table) for table %s. Leaving.\n", info->name);
11170 +           spin_unlock(&ipt_account_tables_lock);
11171 +           return -ENOMEM;
11172 +       }
11173 +       
11174 +       /* set table parameters */
11175 +       strncpy(table->name, info->name, IPT_ACCOUNT_NAME_LEN);
11176 +       table->use_count = 1;   
11177 +       table->network = info->network;
11178 +       table->netmask = info->netmask;
11179 +       table->ip_list_lock = SPIN_LOCK_UNLOCKED;
11180 +       
11181 +       hosts_count = INADDR_BROADCAST - table->netmask + 1;
11182 +       
11183 +       if (debug)
11184 +               printk(KERN_INFO "ipt_account: checkentry() allocating memory for %u hosts (%u netmask).\n", hosts_count, info->netmask);
11185 +
11186 +       /* check whether table is not too big */
11187 +       if (hosts_count > ip_list_max_hosts_count) {
11188 +               printk(KERN_ERR "ipt_account: checkentry() unable allocate memory for %u hosts (%u netmask). Increase value of ip_list_max_mask parameter.\n", hosts_count, info->netmask);
11189 +               vfree(table);
11190 +               spin_unlock(&ipt_account_tables_lock);
11191 +               return -ENOMEM;
11192 +       }
11193 +
11194 +       table->ip_list = vmalloc(sizeof(struct t_ipt_account_ip_list) * hosts_count);
11195 +       if (table->ip_list == NULL) {
11196 +           if (debug)
11197 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (t_account_ip_list) for table %s. Leaving.\n", table->name);
11198 +           vfree(table);
11199 +           spin_unlock(&ipt_account_tables_lock);
11200 +           return -ENOMEM;
11201 +       }
11202 +
11203 +       memset(table->ip_list, 0, sizeof(struct t_ipt_account_ip_list) * hosts_count);
11204 +
11205 +       /* 
11206 +        * create entries in /proc/net/ipt_account: one with full 64-bit counters and
11207 +        * second with 32-bit ones. The second can be used in programs supporting only 32-bit numbers
11208 +        * (mrtg, rrdtool).
11209 +        */
11210 +       
11211 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11212 +       strncat(proc_entry_name, "_64", 4);
11213 +       
11214 +       table->status_proc_64 = create_proc_entry(proc_entry_name, ip_list_perms, proc_net_ipt_account);
11215 +       if (table->status_proc_64 == NULL) {        
11216 +           if (debug)
11217 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (status_proc_64) for table %s. Leaving.\n", table->name);
11218 +           vfree(table->ip_list);
11219 +           vfree(table);
11220 +           spin_unlock(&ipt_account_tables_lock);
11221 +           return -ENOMEM;
11222 +       }
11223 +
11224 +       table->status_proc_64->owner = THIS_MODULE;
11225 +       table->status_proc_64->read_proc = ip_list_read_proc_64;
11226 +       table->status_proc_64->write_proc = ip_list_write_proc;
11227 +       table->status_proc_64->data = table;    
11228 +
11229 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11230 +       strncat(proc_entry_name, "_32", 4);
11231 +       
11232 +       table->status_proc_32 = create_proc_entry(proc_entry_name, ip_list_perms, proc_net_ipt_account);
11233 +       if (table->status_proc_32 == NULL) {        
11234 +           if (debug)
11235 +                   printk(KERN_INFO "ipt_account: checkentry() unable to allocate memory (status_proc_32) for table %s. Leaving.\n", table->name);
11236 +           vfree(table->ip_list);
11237 +           vfree(table);
11238 +           spin_unlock(&ipt_account_tables_lock);
11239 +           return -ENOMEM;
11240 +       }
11241 +
11242 +       table->status_proc_32->owner = THIS_MODULE;
11243 +       table->status_proc_32->read_proc = ip_list_read_proc_32;
11244 +       table->status_proc_32->write_proc = ip_list_write_proc;
11245 +       table->status_proc_32->data = table;
11246 +       
11247 +       /* finaly, insert table into list */
11248 +       table->next = ipt_account_tables;
11249 +       ipt_account_tables = table;
11250 +
11251 +       if (debug)
11252 +               printk(KERN_INFO "ipt_account: checkentry() successfully created table %s (use_count = %i).\n", table->name, table->use_count);
11253 +
11254 +       spin_unlock(&ipt_account_tables_lock);
11255 +       
11256 +       if (debug)
11257 +               printk(KERN_INFO "ipt_account: checkentry() leaving.\n");
11258 +       return 1;
11259 +}
11260 +
11261 +static void destroy(void *matchinfo, 
11262 +            unsigned int matchinfosize)
11263 +{
11264 +       const struct t_ipt_account_info *info = matchinfo;
11265 +       struct t_ipt_account_table *table, *last_table;
11266 +       char proc_entry_name[IPT_ACCOUNT_NAME_LEN + 3];
11267 +       
11268 +       if (debug)
11269 +               printk(KERN_INFO "ipt_account: destroy() entered.\n");
11270 +       
11271 +       if (matchinfosize != IPT_ALIGN(sizeof(struct t_ipt_account_info)))
11272 +               return;
11273 +
11274 +       spin_lock(&ipt_account_tables_lock);
11275 +       table = ipt_account_tables;
11276 +
11277 +       if (table == NULL) {
11278 +               /* list is empty, sometheing is realy wrong! */
11279 +               if (debug)
11280 +                       printk(KERN_INFO "ipt_account: destroy() unable to found any tables (asked for %s). Leaving.\n", info->name);
11281 +               spin_unlock(&ipt_account_tables_lock);
11282 +               return;
11283 +       }
11284 +       
11285 +       /* find table combined with this rule - this code is taken for ipt_recent ;) */
11286 +       last_table = NULL;
11287 +       while (strncmp(table->name, info->name, IPT_ACCOUNT_NAME_LEN) && (last_table = table) && (table = table->next));
11288 +
11289 +       if (table == NULL) {
11290 +               printk(KERN_ERR "ipt_account: destroy() unable to found table %s. Leaving.\n", info->name);
11291 +               spin_unlock(&ipt_account_tables_lock);
11292 +               return;
11293 +       }
11294 +
11295 +       /* decrease table use counter */
11296 +       table->use_count--;
11297 +       if (table->use_count != 0) {
11298 +               /* table is used by other rule, can't remove it */
11299 +               if (debug)
11300 +                       printk(KERN_INFO "ipt_account: destroy() table %s is still used (use_count = %i). Leaving.\n", table->name, table->use_count);
11301 +               spin_unlock(&ipt_account_tables_lock);
11302 +               return;
11303 +       }
11304 +
11305 +       /* table is not used by any other tule - remove it */
11306 +       if (debug)
11307 +               printk(KERN_INFO "ipt_account: destroy() removing table %s (use_count = %i).\n", table->name, table->use_count);
11308 +       
11309 +       if (last_table)
11310 +               last_table->next = table->next;
11311 +       else
11312 +               ipt_account_tables = table->next;
11313 +       
11314 +       spin_lock(&table->ip_list_lock);
11315 +       spin_unlock(&table->ip_list_lock);
11316 +       
11317 +       /* remove procfs entries */
11318 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11319 +       strncat(proc_entry_name, "_64", 4);
11320 +       remove_proc_entry(proc_entry_name, proc_net_ipt_account);
11321 +       strncpy(proc_entry_name, table->name, IPT_ACCOUNT_NAME_LEN);
11322 +       strncat(proc_entry_name, "_32", 4);
11323 +       remove_proc_entry(proc_entry_name, proc_net_ipt_account);
11324 +       vfree(table->ip_list);
11325 +       vfree(table);
11326 +
11327 +       spin_unlock(&ipt_account_tables_lock);
11328 +       
11329 +       if (debug)
11330 +               printk(KERN_INFO "account: destroy() leaving.\n");
11331 +
11332 +       return;
11333 +}
11334 +
11335 +static struct ipt_match account_match = {
11336 +       { NULL, NULL },
11337 +       "account",
11338 +       &match,
11339 +       &checkentry,
11340 +       &destroy,
11341 +       THIS_MODULE
11342 +};
11343 +
11344 +static int __init init(void) 
11345 +{
11346 +       printk(version);        
11347 +       if (debug)
11348 +               printk(KERN_INFO "account: __init(): ip_list_perms = %i, ip_list_max_mask = %i\n", ip_list_perms, ip_list_max_mask);                            
11349 +       /* check params */
11350 +       if (ip_list_max_mask > 32 || ip_list_max_mask < 0) {
11351 +               printk(KERN_ERR "account: Wrong netmask given by ip_list_max_mask parameter (%u). Valid is 32 to 0.\n", ip_list_max_mask);
11352 +               return 0;
11353 +       }
11354 +
11355 +       ip_list_max_hosts_count = (1 << (32 - ip_list_max_mask)) + 1;
11356 +       
11357 +       /* create /proc/net/ipt_account directory */
11358 +       proc_net_ipt_account = proc_mkdir("ipt_account", proc_net);
11359 +       if (!proc_net_ipt_account)
11360 +               return -ENOMEM;
11361 +
11362 +       return ipt_register_match(&account_match);
11363 +}
11364 +
11365 +/* procedura usuwaj±ca modu³ */
11366 +static void __exit fini(void) 
11367 +{
11368 +       ipt_unregister_match(&account_match);
11369 +       /* remove /proc/net/ipt_account/ directory */
11370 +       remove_proc_entry("ipt_account", proc_net);
11371 +}
11372 +
11373 +module_init(init);
11374 +module_exit(fini);
11375 +
11376 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.7/net/ipv4/netfilter/ipt_connmark.c
11377 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_connmark.c   1970-01-01 01:00:00.000000000 +0100
11378 +++ linux-2.6.7/net/ipv4/netfilter/ipt_connmark.c       2004-06-25 12:21:25.486517200 +0200
11379 @@ -0,0 +1,81 @@
11380 +/* This kernel module matches connection mark values set by the
11381 + * CONNMARK target
11382 + *
11383 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
11384 + * by Henrik Nordstrom <hno@marasystems.com>
11385 + *
11386 + * This program is free software; you can redistribute it and/or modify
11387 + * it under the terms of the GNU General Public License as published by
11388 + * the Free Software Foundation; either version 2 of the License, or
11389 + * (at your option) any later version.
11390 + *
11391 + * This program is distributed in the hope that it will be useful,
11392 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11393 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11394 + * GNU General Public License for more details.
11395 + *
11396 + * You should have received a copy of the GNU General Public License
11397 + * along with this program; if not, write to the Free Software
11398 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
11399 + */
11400 +
11401 +#include <linux/module.h>
11402 +#include <linux/skbuff.h>
11403 +
11404 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
11405 +MODULE_DESCRIPTION("IP tables connmark match module");
11406 +MODULE_LICENSE("GPL");
11407 +
11408 +#include <linux/netfilter_ipv4/ip_tables.h>
11409 +#include <linux/netfilter_ipv4/ipt_connmark.h>
11410 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11411 +
11412 +static int
11413 +match(const struct sk_buff *skb,
11414 +      const struct net_device *in,
11415 +      const struct net_device *out,
11416 +      const void *matchinfo,
11417 +      int offset,
11418 +      int *hotdrop)
11419 +{
11420 +       const struct ipt_connmark_info *info = matchinfo;
11421 +       enum ip_conntrack_info ctinfo;
11422 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11423 +       if (!ct)
11424 +               return 0;
11425 +
11426 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
11427 +}
11428 +
11429 +static int
11430 +checkentry(const char *tablename,
11431 +          const struct ipt_ip *ip,
11432 +          void *matchinfo,
11433 +          unsigned int matchsize,
11434 +          unsigned int hook_mask)
11435 +{
11436 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
11437 +               return 0;
11438 +
11439 +       return 1;
11440 +}
11441 +
11442 +static struct ipt_match connmark_match = {
11443 +       .name = "connmark",
11444 +       .match = &match,
11445 +       .checkentry = &checkentry,
11446 +       .me = THIS_MODULE
11447 +};
11448 +
11449 +static int __init init(void)
11450 +{
11451 +       return ipt_register_match(&connmark_match);
11452 +}
11453 +
11454 +static void __exit fini(void)
11455 +{
11456 +       ipt_unregister_match(&connmark_match);
11457 +}
11458 +
11459 +module_init(init);
11460 +module_exit(fini);
11461 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c
11462 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c   1970-01-01 01:00:00.000000000 +0100
11463 +++ linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c       2004-06-25 12:21:08.429110320 +0200
11464 @@ -0,0 +1,690 @@
11465 +/* iptables match extension to limit the number of packets per second
11466 + * seperately for each destination.
11467 + *
11468 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
11469 + *
11470 + * $Id$
11471 + *
11472 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
11473 + *
11474 + * based on ipt_limit.c by:
11475 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
11476 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
11477 + * Rusty Russell       <rusty@rustcorp.com.au>
11478 + *
11479 + * The general idea is to create a hash table for every dstip and have a
11480 + * seperate limit counter per tuple.  This way you can do something like 'limit
11481 + * the number of syn packets for each of my internal addresses.
11482 + *
11483 + * Ideally this would just be implemented as a general 'hash' match, which would
11484 + * allow us to attach any iptables target to it's hash buckets.  But this is
11485 + * not possible in the current iptables architecture.  As always, pkttables for
11486 + * 2.7.x will help ;)
11487 + */
11488 +#include <linux/module.h>
11489 +#include <linux/skbuff.h>
11490 +#include <linux/spinlock.h>
11491 +#include <linux/random.h>
11492 +#include <linux/jhash.h>
11493 +#include <linux/slab.h>
11494 +#include <linux/vmalloc.h>
11495 +#include <linux/tcp.h>
11496 +#include <linux/udp.h>
11497 +#include <linux/proc_fs.h>
11498 +#include <linux/seq_file.h>
11499 +
11500 +#define ASSERT_READ_LOCK(x) 
11501 +#define ASSERT_WRITE_LOCK(x) 
11502 +#include <linux/netfilter_ipv4/lockhelp.h>
11503 +#include <linux/netfilter_ipv4/listhelp.h>
11504 +
11505 +#include <linux/netfilter_ipv4/ip_tables.h>
11506 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
11507 +
11508 +/* FIXME: this is just for IP_NF_ASSERRT */
11509 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11510 +
11511 +#define MS2JIFFIES(x) ((x*HZ)/1000)
11512 +
11513 +MODULE_LICENSE("GPL");
11514 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
11515 +MODULE_DESCRIPTION("iptables match for limiting per destination");
11516 +
11517 +/* need to declare this at the top */
11518 +static struct proc_dir_entry *dstlimit_procdir;
11519 +static struct file_operations dl_file_ops;
11520 +
11521 +/* hash table crap */
11522 +
11523 +struct dsthash_dst {
11524 +       u_int32_t src_ip;
11525 +       u_int32_t dst_ip;
11526 +       u_int16_t port;
11527 +};
11528 +
11529 +struct dsthash_ent {
11530 +       /* static / read-only parts in the beginning */
11531 +       struct list_head list;
11532 +       struct dsthash_dst dst;
11533 +
11534 +       /* modified structure members in the end */
11535 +       unsigned long expires;          /* precalculated expiry time */
11536 +       struct {
11537 +               unsigned long prev;     /* last modification */
11538 +               u_int32_t credit;
11539 +               u_int32_t credit_cap, cost;
11540 +       } rateinfo;
11541 +};
11542 +
11543 +struct ipt_dstlimit_htable {
11544 +       struct list_head list;          /* global list of all htables */
11545 +       atomic_t use;
11546 +
11547 +       struct dstlimit_cfg cfg;        /* config */
11548 +
11549 +       /* used internally */
11550 +       spinlock_t lock;                /* lock for list_head */
11551 +       u_int32_t rnd;                  /* random seed for hash */
11552 +       struct timer_list timer;        /* timer for gc */
11553 +       atomic_t count;                 /* number entries in table */
11554 +
11555 +       /* seq_file stuff */
11556 +       struct proc_dir_entry *pde;
11557 +
11558 +       struct list_head hash[0];       /* hashtable itself */
11559 +};
11560 +
11561 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
11562 +static LIST_HEAD(dstlimit_htables);
11563 +static kmem_cache_t *dstlimit_cachep;
11564 +
11565 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
11566 +{
11567 +       return (ent->dst.dst_ip == b->dst_ip 
11568 +               && ent->dst.port == b->port
11569 +               && ent->dst.src_ip == b->src_ip);
11570 +}
11571 +
11572 +static inline u_int32_t
11573 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
11574 +{
11575 +       return (jhash_3words(dst->dst_ip, dst->port, 
11576 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
11577 +}
11578 +
11579 +static inline struct dsthash_ent *
11580 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11581 +{
11582 +       struct dsthash_ent *ent;
11583 +       u_int32_t hash = hash_dst(ht, dst);
11584 +       MUST_BE_LOCKED(&ht->lock);
11585 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
11586 +       return ent;
11587 +}
11588 +
11589 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
11590 +static struct dsthash_ent *
11591 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11592 +{
11593 +       struct dsthash_ent *ent;
11594 +
11595 +       /* initialize hash with random val at the time we allocate
11596 +        * the first hashtable entry */
11597 +       if (!ht->rnd)
11598 +               get_random_bytes(&ht->rnd, 4);
11599 +
11600 +       if (ht->cfg.max &&
11601 +           atomic_read(&ht->count) >= ht->cfg.max) {
11602 +               /* FIXME: do something. question is what.. */
11603 +               if (net_ratelimit())
11604 +                       printk(KERN_WARNING 
11605 +                               "ipt_dstlimit: max count of %u reached\n", 
11606 +                               ht->cfg.max);
11607 +               return NULL;
11608 +       }
11609 +
11610 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
11611 +       if (!ent) {
11612 +               if (net_ratelimit())
11613 +                       printk(KERN_ERR 
11614 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
11615 +               return NULL;
11616 +       }
11617 +
11618 +       atomic_inc(&ht->count);
11619 +
11620 +       ent->dst.dst_ip = dst->dst_ip;
11621 +       ent->dst.port = dst->port;
11622 +       ent->dst.src_ip = dst->src_ip;
11623 +
11624 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
11625 +
11626 +       return ent;
11627 +}
11628 +
11629 +static inline void 
11630 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
11631 +{
11632 +       MUST_BE_LOCKED(&ht->lock);
11633 +
11634 +       list_del(&ent->list);
11635 +       kmem_cache_free(dstlimit_cachep, ent);
11636 +       atomic_dec(&ht->count);
11637 +}
11638 +static void htable_gc(unsigned long htlong);
11639 +
11640 +static int htable_create(struct ipt_dstlimit_info *minfo)
11641 +{
11642 +       int i;
11643 +       unsigned int size;
11644 +       struct ipt_dstlimit_htable *hinfo;
11645 +
11646 +       if (minfo->cfg.size)
11647 +               size = minfo->cfg.size;
11648 +       else {
11649 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
11650 +                        / sizeof(struct list_head));
11651 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
11652 +                       size = 8192;
11653 +               if (size < 16)
11654 +                       size = 16;
11655 +       }
11656 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
11657 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
11658 +                       + (sizeof(struct list_head) * size));
11659 +       if (!hinfo) {
11660 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
11661 +               return -1;
11662 +       }
11663 +       minfo->hinfo = hinfo;
11664 +
11665 +       /* copy match config into hashtable config */
11666 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
11667 +       hinfo->cfg.size = size;
11668 +       if (!hinfo->cfg.max)
11669 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
11670 +       else if (hinfo->cfg.max < hinfo->cfg.size)
11671 +               hinfo->cfg.max = hinfo->cfg.size;
11672 +
11673 +       for (i = 0; i < hinfo->cfg.size; i++)
11674 +               INIT_LIST_HEAD(&hinfo->hash[i]);
11675 +
11676 +       atomic_set(&hinfo->count, 0);
11677 +       atomic_set(&hinfo->use, 1);
11678 +       hinfo->rnd = 0;
11679 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
11680 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
11681 +       if (!hinfo->pde) {
11682 +               vfree(hinfo);
11683 +               return -1;
11684 +       }
11685 +       hinfo->pde->proc_fops = &dl_file_ops;
11686 +       hinfo->pde->data = hinfo;
11687 +
11688 +       init_timer(&hinfo->timer);
11689 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
11690 +       hinfo->timer.data = (unsigned long )hinfo;
11691 +       hinfo->timer.function = htable_gc;
11692 +       add_timer(&hinfo->timer);
11693 +
11694 +       WRITE_LOCK(&dstlimit_lock);
11695 +       list_add(&hinfo->list, &dstlimit_htables);
11696 +       WRITE_UNLOCK(&dstlimit_lock);
11697 +
11698 +       return 0;
11699 +}
11700 +
11701 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11702 +{
11703 +       return 1;
11704 +}
11705 +
11706 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11707 +{
11708 +       return (jiffies >= he->expires);
11709 +}
11710 +
11711 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
11712 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
11713 +                                             struct dsthash_ent *he))
11714 +{
11715 +       int i;
11716 +
11717 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
11718 +
11719 +       /* lock hash table and iterate over it */
11720 +       LOCK_BH(&ht->lock);
11721 +       for (i = 0; i < ht->cfg.size; i++) {
11722 +               struct dsthash_ent *dh, *n;
11723 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
11724 +                       if ((*select)(ht, dh))
11725 +                               __dsthash_free(ht, dh);
11726 +               }
11727 +       }
11728 +       UNLOCK_BH(&ht->lock);
11729 +}
11730 +
11731 +/* hash table garbage collector, run by timer */
11732 +static void htable_gc(unsigned long htlong)
11733 +{
11734 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
11735 +
11736 +       htable_selective_cleanup(ht, select_gc);
11737 +
11738 +       /* re-add the timer accordingly */
11739 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
11740 +       add_timer(&ht->timer);
11741 +}
11742 +
11743 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
11744 +{
11745 +       /* remove timer, if it is pending */
11746 +       if (timer_pending(&hinfo->timer))
11747 +               del_timer(&hinfo->timer);
11748 +
11749 +       /* remove proc entry */
11750 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
11751 +
11752 +       htable_selective_cleanup(hinfo, select_all);
11753 +       vfree(hinfo);
11754 +}
11755 +
11756 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
11757 +{
11758 +       struct ipt_dstlimit_htable *hinfo;
11759 +
11760 +       READ_LOCK(&dstlimit_lock);
11761 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
11762 +               if (!strcmp(name, hinfo->pde->name)) {
11763 +                       atomic_inc(&hinfo->use);
11764 +                       READ_UNLOCK(&dstlimit_lock);
11765 +                       return hinfo;
11766 +               }
11767 +       }
11768 +       READ_UNLOCK(&dstlimit_lock);
11769 +
11770 +       return NULL;
11771 +}
11772 +
11773 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
11774 +{
11775 +       if (atomic_dec_and_test(&hinfo->use)) {
11776 +               WRITE_LOCK(&dstlimit_lock);
11777 +               list_del(&hinfo->list);
11778 +               WRITE_UNLOCK(&dstlimit_lock);
11779 +               htable_destroy(hinfo);
11780 +       }
11781 +}
11782 +
11783 +
11784 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
11785 + * see net/sched/sch_tbf.c in the linux source tree
11786 + */
11787 +
11788 +/* Rusty: This is my (non-mathematically-inclined) understanding of
11789 +   this algorithm.  The `average rate' in jiffies becomes your initial
11790 +   amount of credit `credit' and the most credit you can ever have
11791 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
11792 +   test, `cost'.
11793 +
11794 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
11795 +   If you get credit balance more than this, the extra credit is
11796 +   discarded.  Every time the match passes, you lose `cost' credits;
11797 +   if you don't have that many, the test fails.
11798 +
11799 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
11800 +
11801 +   To get the maximum range, we multiply by this factor (ie. you get N
11802 +   credits per jiffy).  We want to allow a rate as low as 1 per day
11803 +   (slowest userspace tool allows), which means
11804 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
11805 +*/
11806 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
11807 +
11808 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
11809 + * us the power of 2 below the theoretical max, so GCC simply does a
11810 + * shift. */
11811 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
11812 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
11813 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
11814 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
11815 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
11816 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
11817 +
11818 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
11819 +
11820 +/* Precision saver. */
11821 +static inline u_int32_t
11822 +user2credits(u_int32_t user)
11823 +{
11824 +       /* If multiplying would overflow... */
11825 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
11826 +               /* Divide first. */
11827 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
11828 +
11829 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
11830 +}
11831 +
11832 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
11833 +{
11834 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
11835 +                                       * CREDITS_PER_JIFFY;
11836 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
11837 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
11838 +}
11839 +
11840 +static int
11841 +dstlimit_match(const struct sk_buff *skb,
11842 +               const struct net_device *in,
11843 +               const struct net_device *out,
11844 +               const void *matchinfo,
11845 +               int offset,
11846 +               int *hotdrop)
11847 +{
11848 +       struct ipt_dstlimit_info *r = 
11849 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
11850 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
11851 +       unsigned long now = jiffies;
11852 +       struct dsthash_ent *dh;
11853 +       struct dsthash_dst dst;
11854 +
11855 +       memset(&dst, 0, sizeof(dst));
11856 +
11857 +       /* dest ip is always in hash */
11858 +       dst.dst_ip = skb->nh.iph->daddr;
11859 +
11860 +       /* source ip only if respective hashmode, otherwise set to
11861 +        * zero */
11862 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
11863 +               dst.src_ip = skb->nh.iph->saddr;
11864 +
11865 +       /* dest port only if respective mode */
11866 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
11867 +               u16 ports[2];
11868 +
11869 +               /* Must not be a fragment. */
11870 +               if (offset)
11871 +                       return 0;
11872 +
11873 +               /* Must be big enough to read ports (both UDP and TCP have
11874 +                  them at the start). */
11875 +               if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
11876 +                       /* We've been asked to examine this packet, and we
11877 +                          can't.  Hence, no choice but to drop. */
11878 +                       *hotdrop = 1;
11879 +                       return 0;
11880 +               }
11881 +
11882 +               switch (skb->nh.iph->protocol) {
11883 +                       struct tcphdr *th;
11884 +                       struct udphdr *uh;
11885 +               case IPPROTO_TCP:
11886 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11887 +                       dst.port = th->dest;
11888 +                       break;
11889 +               case IPPROTO_UDP:
11890 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11891 +                       dst.port = uh->dest;
11892 +                       break;
11893 +               default:
11894 +                       break;
11895 +               }
11896 +       } 
11897 +
11898 +       LOCK_BH(&hinfo->lock);
11899 +       dh = __dsthash_find(hinfo, &dst);
11900 +       if (!dh) {
11901 +               dh = __dsthash_alloc_init(hinfo, &dst);
11902 +
11903 +               if (!dh) {
11904 +                       /* enomem... don't match == DROP */
11905 +                       if (net_ratelimit())
11906 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
11907 +                       UNLOCK_BH(&hinfo->lock);
11908 +                       return 0;
11909 +               }
11910 +
11911 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
11912 +
11913 +               dh->rateinfo.prev = jiffies;
11914 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
11915 +                                                       hinfo->cfg.burst);
11916 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
11917 +                                                       hinfo->cfg.burst);
11918 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
11919 +
11920 +               UNLOCK_BH(&hinfo->lock);
11921 +               return 1;
11922 +       }
11923 +
11924 +       /* update expiration timeout */
11925 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
11926 +
11927 +       rateinfo_recalc(dh, now);
11928 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
11929 +               /* We're underlimit. */
11930 +               dh->rateinfo.credit -= dh->rateinfo.cost;
11931 +               UNLOCK_BH(&hinfo->lock);
11932 +               return 1;
11933 +       }
11934 +
11935 +               UNLOCK_BH(&hinfo->lock);
11936 +
11937 +       /* default case: we're overlimit, thus don't match */
11938 +       return 0;
11939 +}
11940 +
11941 +static int
11942 +dstlimit_checkentry(const char *tablename,
11943 +                    const struct ipt_ip *ip,
11944 +                    void *matchinfo,
11945 +                    unsigned int matchsize,
11946 +                    unsigned int hook_mask)
11947 +{
11948 +       struct ipt_dstlimit_info *r = matchinfo;
11949 +
11950 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
11951 +               return 0;
11952 +
11953 +       /* Check for overflow. */
11954 +       if (r->cfg.burst == 0
11955 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
11956 +                                       user2credits(r->cfg.avg)) {
11957 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
11958 +                      r->cfg.avg, r->cfg.burst);
11959 +               return 0;
11960 +       }
11961 +
11962 +       if (r->cfg.mode == 0 
11963 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
11964 +                         |IPT_DSTLIMIT_HASH_DIP
11965 +                         |IPT_DSTLIMIT_HASH_SIP))
11966 +               return 0;
11967 +
11968 +       if (!r->cfg.gc_interval)
11969 +               return 0;
11970 +       
11971 +       if (!r->cfg.expire)
11972 +               return 0;
11973 +
11974 +       r->hinfo = htable_find_get(r->name);
11975 +       if (!r->hinfo && (htable_create(r) != 0)) {
11976 +               return 0;
11977 +       }
11978 +
11979 +       /* Ugly hack: For SMP, we only want to use one set */
11980 +       r->u.master = r;
11981 +
11982 +       return 1;
11983 +}
11984 +
11985 +static void
11986 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
11987 +{
11988 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
11989 +
11990 +       htable_put(r->hinfo);
11991 +}
11992 +
11993 +static struct ipt_match ipt_dstlimit = { 
11994 +       .list = { .prev = NULL, .next = NULL }, 
11995 +       .name = "dstlimit", 
11996 +       .match = dstlimit_match, 
11997 +       .checkentry = dstlimit_checkentry, 
11998 +       .destroy = dstlimit_destroy,
11999 +       .me = THIS_MODULE 
12000 +};
12001 +
12002 +/* PROC stuff */
12003 +
12004 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
12005 +{
12006 +       struct proc_dir_entry *pde = s->private;
12007 +       struct ipt_dstlimit_htable *htable = pde->data;
12008 +       unsigned int *bucket;
12009 +
12010 +       LOCK_BH(&htable->lock);
12011 +       if (*pos >= htable->cfg.size)
12012 +               return NULL;
12013 +
12014 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
12015 +       if (!bucket)
12016 +               return ERR_PTR(-ENOMEM);
12017 +
12018 +       *bucket = *pos;
12019 +       return bucket;
12020 +}
12021 +
12022 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
12023 +{
12024 +       struct proc_dir_entry *pde = s->private;
12025 +       struct ipt_dstlimit_htable *htable = pde->data;
12026 +       unsigned int *bucket = (unsigned int *)v;
12027 +
12028 +       *pos = ++(*bucket);
12029 +       if (*pos >= htable->cfg.size) {
12030 +               kfree(v);
12031 +               return NULL;
12032 +       }
12033 +       return bucket;
12034 +}
12035 +
12036 +static void dl_seq_stop(struct seq_file *s, void *v)
12037 +{
12038 +       struct proc_dir_entry *pde = s->private;
12039 +       struct ipt_dstlimit_htable *htable = pde->data;
12040 +       unsigned int *bucket = (unsigned int *)v;
12041 +
12042 +       kfree(bucket);
12043 +
12044 +       UNLOCK_BH(&htable->lock);
12045 +}
12046 +
12047 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
12048 +{
12049 +       /* recalculate to show accurate numbers */
12050 +       rateinfo_recalc(ent, jiffies);
12051 +
12052 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
12053 +                       (ent->expires - jiffies)/HZ,
12054 +                       NIPQUAD(ent->dst.src_ip),
12055 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
12056 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
12057 +                       ent->rateinfo.cost);
12058 +}
12059 +
12060 +static int dl_seq_show(struct seq_file *s, void *v)
12061 +{
12062 +       struct proc_dir_entry *pde = s->private;
12063 +       struct ipt_dstlimit_htable *htable = pde->data;
12064 +       unsigned int *bucket = (unsigned int *)v;
12065 +
12066 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
12067 +                     struct dsthash_ent *, s)) {
12068 +               /* buffer was filled and unable to print that tuple */
12069 +               return 1;
12070 +       }
12071 +       return 0;
12072 +}
12073 +
12074 +static struct seq_operations dl_seq_ops = {
12075 +       .start = dl_seq_start,
12076 +       .next  = dl_seq_next,
12077 +       .stop  = dl_seq_stop,
12078 +       .show  = dl_seq_show
12079 +};
12080 +
12081 +static int dl_proc_open(struct inode *inode, struct file *file)
12082 +{
12083 +       int ret = seq_open(file, &dl_seq_ops);
12084 +
12085 +       if (!ret) {
12086 +               struct seq_file *sf = file->private_data;
12087 +               sf->private = PDE(inode);
12088 +       }
12089 +       return ret;
12090 +}
12091 +
12092 +static struct file_operations dl_file_ops = {
12093 +       .owner   = THIS_MODULE,
12094 +       .open    = dl_proc_open,
12095 +       .read    = seq_read,
12096 +       .llseek  = seq_lseek,
12097 +       .release = seq_release
12098 +};
12099 +
12100 +static int init_or_fini(int fini)
12101 +{
12102 +       int ret = 0;
12103 +
12104 +       if (fini)
12105 +               goto cleanup;
12106 +
12107 +       if (ipt_register_match(&ipt_dstlimit)) {
12108 +               ret = -EINVAL;
12109 +               goto cleanup_nothing;
12110 +       }
12111 +
12112 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
12113 +        * quite small ? */
12114 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
12115 +                                           sizeof(struct dsthash_ent), 0,
12116 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
12117 +       if (!dstlimit_cachep) {
12118 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
12119 +               ret = -ENOMEM;
12120 +               goto cleanup_unreg_match;
12121 +       }
12122 +
12123 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
12124 +       if (!dstlimit_procdir) {
12125 +               printk(KERN_ERR "Unable to create proc dir entry\n");
12126 +               ret = -ENOMEM;
12127 +               goto cleanup_free_slab;
12128 +       }
12129 +
12130 +       return ret;
12131 +
12132 +cleanup:
12133 +       remove_proc_entry("ipt_dstlimit", proc_net);
12134 +cleanup_free_slab:
12135 +       kmem_cache_destroy(dstlimit_cachep);
12136 +cleanup_unreg_match:
12137 +       ipt_unregister_match(&ipt_dstlimit);
12138 +cleanup_nothing:
12139 +       return ret;
12140 +       
12141 +}
12142 +
12143 +static int __init init(void)
12144 +{
12145 +       return init_or_fini(0);
12146 +}
12147 +
12148 +static void __exit fini(void)
12149 +{
12150 +       init_or_fini(1);
12151 +}
12152 +
12153 +module_init(init);
12154 +module_exit(fini);
12155 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c
12156 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c      1970-01-01 01:00:00.000000000 +0100
12157 +++ linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c  2004-06-25 12:21:08.962029304 +0200
12158 @@ -0,0 +1,185 @@
12159 +/*
12160 + *  This module implements a simple TSK FLC 
12161 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
12162 + * to limit , in an adaptive and flexible way , the packet rate crossing 
12163 + * a given stream . It serves as an initial and very simple (but effective)
12164 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
12165 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
12166 + * into our code in a precise , adaptive and efficient manner. 
12167 + *  The goal is very similar to that of "limit" match , but using techniques of
12168 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
12169 + * avoiding over and undershoots - and stuff like that .
12170 + *
12171 + *
12172 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
12173 + * 2002-08-17  : Changed to eliminate floating point operations .
12174 + * 2002-08-23  : Coding style changes .
12175 +*/
12176 +
12177 +#include <linux/module.h>
12178 +#include <linux/skbuff.h>
12179 +#include <linux/ip.h>
12180 +#include <linux/random.h>
12181 +#include <net/tcp.h>
12182 +#include <linux/spinlock.h>
12183 +#include <linux/netfilter_ipv4/ip_tables.h>
12184 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
12185 +
12186 +/*
12187 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
12188 + Expressed in percentage
12189 +*/
12190 +
12191 +#define PAR_LOW                1/100
12192 +#define PAR_HIGH       1
12193 +
12194 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
12195 +
12196 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
12197 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
12198 +MODULE_LICENSE("GPL");
12199 +
12200 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12201 +{
12202 +       if (tx >= maxi)
12203 +               return 100;
12204 +
12205 +       if (tx <= mini)
12206 +               return 0;
12207 +
12208 +       return ( (100*(tx-mini)) / (maxi-mini) );
12209 +}
12210 +
12211 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
12212 +{
12213 +       if (tx <= mini)
12214 +               return 100;
12215 +
12216 +       if (tx >= maxi)
12217 +               return 0;
12218 +
12219 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
12220 +}
12221 +
12222 +static int
12223 +ipt_fuzzy_match(const struct sk_buff *pskb,
12224 +              const struct net_device *in,
12225 +              const struct net_device *out,
12226 +              const void *matchinfo,
12227 +              int offset,
12228 +              int *hotdrop)
12229 +{
12230 +       /* From userspace */
12231 +       
12232 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
12233 +
12234 +       u_int8_t random_number;
12235 +       unsigned long amount;
12236 +       u_int8_t howhigh, howlow;
12237 +       
12238 +
12239 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
12240 +
12241 +       info->bytes_total += pskb->len;
12242 +       info->packets_total++;
12243 +
12244 +       info->present_time = jiffies;
12245 +       
12246 +       if (info->present_time >= info->previous_time)
12247 +               amount = info->present_time - info->previous_time;
12248 +       else { 
12249 +               /* There was a transition : I choose to re-sample 
12250 +                  and keep the old acceptance rate...
12251 +               */
12252 +
12253 +               amount = 0;
12254 +               info->previous_time = info->present_time;
12255 +               info->bytes_total = info->packets_total = 0;
12256 +       };
12257 +       
12258 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
12259 +       {
12260 +
12261 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
12262 +                                       / amount );
12263 +
12264 +               info->previous_time = info->present_time;
12265 +               info->bytes_total = info->packets_total = 0;
12266 +
12267 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
12268 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
12269 +
12270 +               info->acceptance_rate = (u_int8_t) \
12271 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
12272 +
12273 +               /* In fact , the above defuzzification would require a denominator
12274 +                  proportional to (howhigh+howlow) but , in this particular case ,
12275 +                  that expression is constant .
12276 +                  An imediate consequence is that it isn't necessary to call 
12277 +                  both mf_high and mf_low - but to keep things understandable ,
12278 +                  I did so .  */ 
12279 +
12280 +       }
12281 +       
12282 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
12283 +
12284 +
12285 +       if ( info->acceptance_rate < 100 )
12286 +       {                
12287 +               get_random_bytes((void *)(&random_number), 1);
12288 +
12289 +               /*  If within the acceptance , it can pass => don't match */
12290 +               if (random_number <= (255 * info->acceptance_rate) / 100)
12291 +                       return 0;
12292 +               else
12293 +                       return 1; /* It can't pass ( It matches ) */
12294 +       } ;
12295 +
12296 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
12297 +       
12298 +}
12299 +
12300 +static int
12301 +ipt_fuzzy_checkentry(const char *tablename,
12302 +                  const struct ipt_ip *e,
12303 +                  void *matchinfo,
12304 +                  unsigned int matchsize,
12305 +                  unsigned int hook_mask)
12306 +{
12307 +       
12308 +       const struct ipt_fuzzy_info *info = matchinfo;
12309 +
12310 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
12311 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
12312 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
12313 +               return 0;
12314 +       }
12315 +
12316 +       if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
12317 +           || (info->minimum_rate >= info->maximum_rate )) {
12318 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
12319 +               return 0;
12320 +       }
12321 +
12322 +       return 1;
12323 +}
12324 +
12325 +static struct ipt_match ipt_fuzzy_reg = { 
12326 +       .name = "fuzzy",
12327 +       .match = ipt_fuzzy_match,
12328 +       .checkentry = ipt_fuzzy_checkentry,
12329 +       .me = THIS_MODULE
12330 +};
12331 +
12332 +static int __init init(void)
12333 +{
12334 +       return ipt_register_match(&ipt_fuzzy_reg);
12335 +}
12336 +
12337 +static void __exit fini(void)
12338 +{
12339 +       ipt_unregister_match(&ipt_fuzzy_reg);
12340 +}
12341 +
12342 +module_init(init);
12343 +module_exit(fini);
12344 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c
12345 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c        1970-01-01 01:00:00.000000000 +0100
12346 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c    2004-06-25 12:21:09.438956800 +0200
12347 @@ -0,0 +1,172 @@
12348 +/*
12349 +  This is a module which is used to match ipv4 options.
12350 +  This file is distributed under the terms of the GNU General Public
12351 +  License (GPL). Copies of the GPL can be obtained from:
12352 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
12353 +
12354 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
12355 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
12356 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
12357 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
12358 +  19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
12359 +*/
12360 +
12361 +#include <linux/module.h>
12362 +#include <linux/skbuff.h>
12363 +#include <net/ip.h>
12364 +
12365 +#include <linux/netfilter_ipv4/ip_tables.h>
12366 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
12367 +
12368 +MODULE_LICENSE("GPL");
12369 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12370 +
12371 +static int
12372 +match(const struct sk_buff *skb,
12373 +      const struct net_device *in,
12374 +      const struct net_device *out,
12375 +      const void *matchinfo,
12376 +      int offset,
12377 +      int *hotdrop)
12378 +{
12379 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
12380 +       const struct iphdr *iph = skb->nh.iph;
12381 +       const struct ip_options *opt;
12382 +
12383 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
12384 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
12385 +
12386 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
12387 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12388 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12389 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12390 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12391 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
12392 +                       return 0;
12393 +               return 1;
12394 +       }
12395 +       else {
12396 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
12397 +                       /* there are options, and we don't need to care which one */
12398 +                       return 1;
12399 +               else {
12400 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
12401 +                               /* there are options but we don't want any ! */
12402 +                               return 0;
12403 +               }
12404 +       }
12405 +
12406 +       opt = &(IPCB(skb)->opt);
12407 +
12408 +       /* source routing */
12409 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
12410 +               if (!((opt->srr) & (opt->is_strictroute)))
12411 +                       return 0;
12412 +       }
12413 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
12414 +               if (!((opt->srr) & (!opt->is_strictroute)))
12415 +                       return 0;
12416 +       }
12417 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
12418 +               if (opt->srr)
12419 +                       return 0;
12420 +       }
12421 +       /* record route */
12422 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
12423 +               if (!opt->rr)
12424 +                       return 0;
12425 +       }
12426 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
12427 +               if (opt->rr)
12428 +                       return 0;
12429 +       }
12430 +       /* timestamp */
12431 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
12432 +               if (!opt->ts)
12433 +                       return 0;
12434 +       }
12435 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
12436 +               if (opt->ts)
12437 +                       return 0;
12438 +       }
12439 +       /* router-alert option  */
12440 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
12441 +               if (!opt->router_alert)
12442 +                       return 0;
12443 +       }
12444 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
12445 +               if (opt->router_alert)
12446 +                       return 0;
12447 +       }
12448 +
12449 +       /* we match ! */
12450 +       return 1;
12451 +}
12452 +
12453 +static int
12454 +checkentry(const char *tablename,
12455 +          const struct ipt_ip *ip,
12456 +          void *matchinfo,
12457 +          unsigned int matchsize,
12458 +          unsigned int hook_mask)
12459 +{
12460 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
12461 +       /* Check the size */
12462 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
12463 +               return 0;
12464 +       /* Now check the coherence of the data ... */
12465 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
12466 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
12467 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
12468 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
12469 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
12470 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
12471 +               return 0; /* opposites */
12472 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
12473 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12474 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12475 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12476 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12477 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
12478 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
12479 +               return 0; /* opposites */
12480 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
12481 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
12482 +               return 0; /* cannot match in the same time loose and strict source routing */
12483 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12484 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
12485 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
12486 +               return 0; /* opposites */
12487 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
12488 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
12489 +               return 0; /* opposites */
12490 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
12491 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
12492 +               return 0; /* opposites */
12493 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
12494 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
12495 +               return 0; /* opposites */
12496 +
12497 +       /* everything looks ok. */
12498 +       return 1;
12499 +}
12500 +
12501 +static struct ipt_match ipv4options_match = { 
12502 +       .name = "ipv4options",
12503 +       .match = match,
12504 +       .checkentry = checkentry,
12505 +       .me = THIS_MODULE
12506 +};
12507 +
12508 +static int __init init(void)
12509 +{
12510 +       return ipt_register_match(&ipv4options_match);
12511 +}
12512 +
12513 +static void __exit fini(void)
12514 +{
12515 +       ipt_unregister_match(&ipv4options_match);
12516 +}
12517 +
12518 +module_init(init);
12519 +module_exit(fini);
12520 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.7/net/ipv4/netfilter/ipt_mport.c
12521 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c      1970-01-01 01:00:00.000000000 +0100
12522 +++ linux-2.6.7/net/ipv4/netfilter/ipt_mport.c  2004-06-25 12:21:09.926882624 +0200
12523 @@ -0,0 +1,116 @@
12524 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
12525 +   the same place so we can treat them as equal. */
12526 +#include <linux/module.h>
12527 +#include <linux/types.h>
12528 +#include <linux/udp.h>
12529 +#include <linux/skbuff.h>
12530 +
12531 +#include <linux/netfilter_ipv4/ipt_mport.h>
12532 +#include <linux/netfilter_ipv4/ip_tables.h>
12533 +
12534 +MODULE_LICENSE("GPL");
12535 +
12536 +#if 0
12537 +#define duprintf(format, args...) printk(format , ## args)
12538 +#else
12539 +#define duprintf(format, args...)
12540 +#endif
12541 +
12542 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
12543 +static inline int
12544 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
12545 +{
12546 +       unsigned int i;
12547 +        unsigned int m;
12548 +        u_int16_t pflags = minfo->pflags;
12549 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
12550 +                u_int16_t s, e;
12551 +
12552 +                if (pflags & m
12553 +                    && minfo->ports[i] == 65535)
12554 +                        return 0;
12555 +
12556 +                s = minfo->ports[i];
12557 +
12558 +                if (pflags & m) {
12559 +                        e = minfo->ports[++i];
12560 +                        m <<= 1;
12561 +                } else
12562 +                        e = s;
12563 +
12564 +                if (minfo->flags & IPT_MPORT_SOURCE
12565 +                    && src >= s && src <= e)
12566 +                        return 1;
12567 +
12568 +               if (minfo->flags & IPT_MPORT_DESTINATION
12569 +                   && dst >= s && dst <= e)
12570 +                       return 1;
12571 +       }
12572 +
12573 +       return 0;
12574 +}
12575 +
12576 +static int
12577 +match(const struct sk_buff *skb,
12578 +      const struct net_device *in,
12579 +      const struct net_device *out,
12580 +      const void *matchinfo,
12581 +      int offset,
12582 +      int *hotdrop)
12583 +{
12584 +       u16 ports[2];
12585 +       const struct ipt_mport *minfo = matchinfo;
12586 +
12587 +       if (offset)
12588 +               return 0;
12589 +
12590 +       /* Must be big enough to read ports (both UDP and TCP have
12591 +           them at the start). */
12592 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12593 +               /* We've been asked to examine this packet, and we
12594 +                  can't.  Hence, no choice but to drop. */
12595 +                       duprintf("ipt_multiport:"
12596 +                                " Dropping evil offset=0 tinygram.\n");
12597 +                       *hotdrop = 1;
12598 +                       return 0;
12599 +       }
12600 +
12601 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
12602 +}
12603 +
12604 +/* Called when user tries to insert an entry of this type. */
12605 +static int
12606 +checkentry(const char *tablename,
12607 +          const struct ipt_ip *ip,
12608 +          void *matchinfo,
12609 +          unsigned int matchsize,
12610 +          unsigned int hook_mask)
12611 +{
12612 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
12613 +               return 0;
12614 +
12615 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
12616 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
12617 +               && !(ip->invflags & IPT_INV_PROTO)
12618 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
12619 +}
12620 +
12621 +static struct ipt_match mport_match = { 
12622 +       .name = "mport",
12623 +       .match = &match,
12624 +       .checkentry = &checkentry,
12625 +       .me = THIS_MODULE
12626 +};
12627 +
12628 +static int __init init(void)
12629 +{
12630 +       return ipt_register_match(&mport_match);
12631 +}
12632 +
12633 +static void __exit fini(void)
12634 +{
12635 +       ipt_unregister_match(&mport_match);
12636 +}
12637 +
12638 +module_init(init);
12639 +module_exit(fini);
12640 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.7/net/ipv4/netfilter/ipt_nth.c
12641 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c        1970-01-01 01:00:00.000000000 +0100
12642 +++ linux-2.6.7/net/ipv4/netfilter/ipt_nth.c    2004-06-25 12:21:10.460801456 +0200
12643 @@ -0,0 +1,166 @@
12644 +/*
12645 +  This is a module which is used for match support for every Nth packet
12646 +  This file is distributed under the terms of the GNU General Public
12647 +  License (GPL). Copies of the GPL can be obtained from:
12648 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
12649 +
12650 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
12651 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
12652 +        * added support for multiple counters
12653 +        * added support for matching on individual packets
12654 +          in the counter cycle
12655 +  2004-02-19 Harald Welte <laforge@netfilter.org>
12656 +       * port to 2.6.x
12657 +
12658 +*/
12659 +
12660 +#include <linux/module.h>
12661 +#include <linux/skbuff.h>
12662 +#include <linux/ip.h>
12663 +#include <net/tcp.h>
12664 +#include <linux/spinlock.h>
12665 +#include <linux/netfilter_ipv4/ip_tables.h>
12666 +#include <linux/netfilter_ipv4/ipt_nth.h>
12667 +
12668 +MODULE_LICENSE("GPL");
12669 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12670 +
12671 +/*
12672 + * State information.
12673 + */
12674 +struct state {
12675 +       spinlock_t lock;
12676 +       u_int16_t number;
12677 +};
12678 +
12679 +static struct state states[IPT_NTH_NUM_COUNTERS];
12680 +
12681 +static int
12682 +ipt_nth_match(const struct sk_buff *pskb,
12683 +             const struct net_device *in,
12684 +             const struct net_device *out,
12685 +             const void *matchinfo,
12686 +             int offset,
12687 +             int *hotdrop)
12688 +{
12689 +       /* Parameters from userspace */
12690 +       const struct ipt_nth_info *info = matchinfo;
12691 +        unsigned counter = info->counter;
12692 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
12693 +       {
12694 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12695 +               return 0;
12696 +        };
12697 +
12698 +        spin_lock(&states[counter].lock);
12699 +
12700 +        /* Are we matching every nth packet?*/
12701 +        if (info->packet == 0xFF)
12702 +        {
12703 +               /* We're matching every nth packet and only every nth packet*/
12704 +               /* Do we match or invert match? */
12705 +               if (info->not == 0)
12706 +               {
12707 +                       if (states[counter].number == 0)
12708 +                       {
12709 +                               ++states[counter].number;
12710 +                               goto match;
12711 +                       }
12712 +                       if (states[counter].number >= info->every)
12713 +                               states[counter].number = 0; /* reset the counter */
12714 +                       else
12715 +                               ++states[counter].number;
12716 +                       goto dontmatch;
12717 +               }
12718 +               else
12719 +               {
12720 +                       if (states[counter].number == 0)
12721 +                       {
12722 +                               ++states[counter].number;
12723 +                               goto dontmatch;
12724 +                       }
12725 +                       if (states[counter].number >= info->every)
12726 +                               states[counter].number = 0;
12727 +                       else
12728 +                               ++states[counter].number;
12729 +                       goto match;
12730 +               }
12731 +        }
12732 +        else
12733 +        {
12734 +               /* We're using the --packet, so there must be a rule for every value */
12735 +               if (states[counter].number == info->packet)
12736 +               {
12737 +                       /* only increment the counter when a match happens */
12738 +                       if (states[counter].number >= info->every)
12739 +                               states[counter].number = 0; /* reset the counter */
12740 +                       else
12741 +                               ++states[counter].number;
12742 +                       goto match;
12743 +               }
12744 +               else
12745 +                       goto dontmatch;
12746 +       }
12747 +
12748 + dontmatch:
12749 +       /* don't match */
12750 +       spin_unlock(&states[counter].lock);
12751 +       return 0;
12752 +
12753 + match:
12754 +       spin_unlock(&states[counter].lock);
12755 +       return 1;
12756 +}
12757 +
12758 +static int
12759 +ipt_nth_checkentry(const char *tablename,
12760 +                  const struct ipt_ip *e,
12761 +                  void *matchinfo,
12762 +                  unsigned int matchsize,
12763 +                  unsigned int hook_mask)
12764 +{
12765 +       /* Parameters from userspace */
12766 +       const struct ipt_nth_info *info = matchinfo;
12767 +        unsigned counter = info->counter;
12768 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
12769 +       {
12770 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12771 +                       return 0;
12772 +               };
12773 +
12774 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
12775 +               printk("nth: matchsize %u != %u\n", matchsize,
12776 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
12777 +               return 0;
12778 +       }
12779 +
12780 +       states[counter].number = info->startat;
12781 +
12782 +       return 1;
12783 +}
12784 +
12785 +static struct ipt_match ipt_nth_reg = { 
12786 +       .name = "nth",
12787 +       .match = ipt_nth_match,
12788 +       .checkentry = ipt_nth_checkentry,
12789 +       .me = THIS_MODULE
12790 +};
12791 +
12792 +static int __init init(void)
12793 +{
12794 +       unsigned counter;
12795 +
12796 +       memset(&states, 0, sizeof(states));
12797 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
12798 +               spin_lock_init(&(states[counter].lock));
12799 +
12800 +       return ipt_register_match(&ipt_nth_reg);
12801 +}
12802 +
12803 +static void __exit fini(void)
12804 +{
12805 +       ipt_unregister_match(&ipt_nth_reg);
12806 +}
12807 +
12808 +module_init(init);
12809 +module_exit(fini);
12810 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.7/net/ipv4/netfilter/ipt_osf.c
12811 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c        1970-01-01 01:00:00.000000000 +0100
12812 +++ linux-2.6.7/net/ipv4/netfilter/ipt_osf.c    2004-06-25 12:21:10.972723632 +0200
12813 @@ -0,0 +1,865 @@
12814 +/*
12815 + * ipt_osf.c
12816 + *
12817 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
12818 + *
12819 + *
12820 + * This program is free software; you can redistribute it and/or modify
12821 + * it under the terms of the GNU General Public License as published by
12822 + * the Free Software Foundation; either version 2 of the License, or
12823 + * (at your option) any later version.
12824 + *
12825 + * This program is distributed in the hope that it will be useful,
12826 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12827 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12828 + * GNU General Public License for more details.
12829 + *
12830 + * You should have received a copy of the GNU General Public License
12831 + * along with this program; if not, write to the Free Software
12832 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12833 + */
12834 +
12835 +/*
12836 + * OS fingerprint matching module.
12837 + * It simply compares various parameters from SYN packet with
12838 + * some hardcoded ones.
12839 + *
12840 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
12841 + * for his p0f.
12842 + */
12843 +
12844 +#include <linux/config.h>
12845 +#include <linux/kernel.h>
12846 +#include <linux/types.h>
12847 +#include <linux/string.h>
12848 +#include <linux/smp.h>
12849 +#include <linux/module.h>
12850 +#include <linux/skbuff.h>
12851 +#include <linux/file.h>
12852 +#include <linux/ip.h>
12853 +#include <linux/proc_fs.h>
12854 +#include <linux/fs.h>
12855 +#include <linux/slab.h>
12856 +#include <linux/spinlock.h>
12857 +#include <linux/ctype.h>
12858 +#include <linux/list.h>
12859 +#include <linux/if.h>
12860 +
12861 +#include <net/sock.h>
12862 +#include <net/ip.h>
12863 +
12864 +#include <linux/netfilter_ipv4/ip_tables.h>
12865 +
12866 +#include <linux/netfilter_ipv4/ipt_osf.h>
12867 +
12868 +#define OSF_DEBUG
12869 +
12870 +#ifdef OSF_DEBUG
12871 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
12872 +#define loga(x...)             printk(x)
12873 +#else
12874 +#define log(x...)              do {} while(0)
12875 +#define loga(x...)             do {} while(0)
12876 +#endif
12877 +
12878 +#define FMATCH_WRONG           0
12879 +#define FMATCH_OK              1
12880 +#define FMATCH_OPT_WRONG       2
12881 +
12882 +#define OPTDEL                 ','
12883 +#define OSFPDEL                ':'
12884 +#define MAXOPTSTRLEN           128
12885 +#define OSFFLUSH               "FLUSH"
12886 +
12887 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
12888 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
12889 +static struct list_head        finger_list;    
12890 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
12891 +                     const void *, int, 
12892 +                     const void *, u_int16_t, 
12893 +                     int *);
12894 +static int checkentry(const char *, const struct ipt_ip *, void *,
12895 +                          unsigned int, unsigned int);
12896 +
12897 +static unsigned long seq, ipt_osf_groups = 1;
12898 +static struct sock *nts;
12899 +
12900 +static struct ipt_match osf_match = 
12901 +{ 
12902 +       { NULL, NULL }, 
12903 +       "osf", 
12904 +       &match, 
12905 +       &checkentry, 
12906 +       NULL, 
12907 +       THIS_MODULE 
12908 +};
12909 +
12910 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
12911 +{
12912 +       unsigned int size;
12913 +       struct sk_buff *skb;
12914 +       struct ipt_osf_nlmsg *data;
12915 +       struct nlmsghdr *nlh;
12916 +
12917 +       size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
12918 +
12919 +       skb = alloc_skb(size, GFP_ATOMIC);
12920 +       if (!skb)
12921 +       {
12922 +               log("skb_alloc() failed.\n");
12923 +               return;
12924 +       }
12925 +       
12926 +       nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
12927 +       
12928 +       data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
12929 +
12930 +       memcpy(&data->f, f, sizeof(struct osf_finger));
12931 +       memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
12932 +       memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
12933 +
12934 +       NETLINK_CB(skb).dst_groups = ipt_osf_groups;
12935 +       netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
12936 +
12937 +nlmsg_failure:
12938 +       return;
12939 +}
12940 +
12941 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
12942 +{
12943 +       struct iphdr *ip = skb->nh.iph;
12944 +
12945 +       if (flags & IPT_OSF_SMART)
12946 +       {
12947 +               struct in_device *in_dev = in_dev_get(skb->dev);
12948 +
12949 +               for_ifa(in_dev)
12950 +               {
12951 +                       if (inet_ifa_match(ip->saddr, ifa))
12952 +                       {
12953 +                               in_dev_put(in_dev);
12954 +                               return (ip->ttl == f_ttl);
12955 +                       }
12956 +               }
12957 +               endfor_ifa(in_dev);
12958 +               
12959 +               in_dev_put(in_dev);
12960 +               return (ip->ttl <= f_ttl);
12961 +       }
12962 +       else
12963 +               return (ip->ttl == f_ttl);
12964 +}
12965 +
12966 +static int
12967 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
12968 +      const void *matchinfo, int offset,
12969 +      const void *hdr, u_int16_t datalen,
12970 +      int *hotdrop)
12971 +{
12972 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
12973 +       struct iphdr *ip = skb->nh.iph;
12974 +       struct tcphdr *tcp;
12975 +       int fmatch = FMATCH_WRONG, fcount = 0;
12976 +       unsigned long totlen, optsize = 0, window;
12977 +       unsigned char df, *optp = NULL, *_optp = NULL;
12978 +       char check_WSS = 0;
12979 +       struct list_head *ent;
12980 +       struct osf_finger *f;
12981 +
12982 +       if (!ip || !info)
12983 +               return 0;
12984 +                               
12985 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
12986 +
12987 +       if (!tcp->syn)
12988 +               return 0;
12989 +       
12990 +       totlen = ntohs(ip->tot_len);
12991 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
12992 +       window = ntohs(tcp->window);
12993 +       
12994 +       if (tcp->doff*4 > sizeof(struct tcphdr))
12995 +       {
12996 +               _optp = optp = (char *)(tcp+1);
12997 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
12998 +       }
12999 +
13000 +       
13001 +       /* Actually we can create hash/table of all genres and search
13002 +        * only in appropriate part, but here is initial variant,
13003 +        * so will use slow path.
13004 +        */
13005 +       read_lock(&osf_lock);
13006 +       list_for_each(ent, &finger_list)
13007 +       {
13008 +               f = list_entry(ent, struct osf_finger, flist);
13009 +       
13010 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
13011 +                       continue;
13012 +
13013 +               optp = _optp;
13014 +               fmatch = FMATCH_WRONG;
13015 +
13016 +               if (totlen == f->ss && df == f->df && 
13017 +                       smart_dec(skb, info->flags, f->ttl))
13018 +               {
13019 +                       unsigned long foptsize;
13020 +                       int optnum;
13021 +                       unsigned short mss = 0;
13022 +
13023 +                       check_WSS = 0;
13024 +
13025 +                       switch (f->wss.wc)
13026 +                       {
13027 +                               case 0:   check_WSS = 0; break;
13028 +                               case 'S': check_WSS = 1; break;
13029 +                               case 'T': check_WSS = 2; break;
13030 +                               case '%': check_WSS = 3; break;
13031 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
13032 +                                                        f->wss.wc, f->genre, f->details);
13033 +                                        check_WSS = 4;
13034 +                                        break;
13035 +                       }
13036 +                       if (check_WSS == 4)
13037 +                               continue;
13038 +
13039 +                       /* Check options */
13040 +
13041 +                       foptsize = 0;
13042 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
13043 +                               foptsize += f->opt[optnum].length;
13044 +
13045 +                               
13046 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
13047 +                               continue;
13048 +
13049 +                       if (!optp)
13050 +                       {
13051 +                               fmatch = FMATCH_OK;
13052 +                               loga("\tYEP : matching without options.\n");
13053 +                               if ((info->flags & IPT_OSF_LOG) && 
13054 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13055 +                                       break;
13056 +                               else
13057 +                                       continue;
13058 +                       }
13059 +                       
13060 +
13061 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
13062 +                       {
13063 +                               if (f->opt[optnum].kind == (*optp)) 
13064 +                               {
13065 +                                       unsigned char len = f->opt[optnum].length;
13066 +                                       unsigned char *optend = optp + len;
13067 +                                       int loop_cont = 0;
13068 +
13069 +                                       fmatch = FMATCH_OK;
13070 +
13071 +
13072 +                                       switch (*optp)
13073 +                                       {
13074 +                                               case OSFOPT_MSS:
13075 +                                                       mss = ntohs(*(unsigned short *)(optp+2));
13076 +                                                       break;
13077 +                                               case OSFOPT_TS:
13078 +                                                       loop_cont = 1;
13079 +                                                       break;
13080 +                                       }
13081 +                                       
13082 +                                       if (loop_cont)
13083 +                                       {
13084 +                                               optp = optend;
13085 +                                               continue;
13086 +                                       }
13087 +                                       
13088 +                                       if (len != 1)
13089 +                                       {
13090 +                                               /* Skip kind and length fields*/
13091 +                                               optp += 2; 
13092 +
13093 +                                               if (f->opt[optnum].wc.val != 0)
13094 +                                               {
13095 +                                                       unsigned long tmp = 0;
13096 +                                                       
13097 +                                                       /* Hmmm... It looks a bit ugly. :) */
13098 +                                                       memcpy(&tmp, optp, 
13099 +                                                               (len > sizeof(unsigned long)?
13100 +                                                                       sizeof(unsigned long):len));
13101 +                                                       /* 2 + 2: optlen(2 bytes) + 
13102 +                                                        *      kind(1 byte) + length(1 byte) */
13103 +                                                       if (len == 4) 
13104 +                                                               tmp = ntohs(tmp);
13105 +                                                       else
13106 +                                                               tmp = ntohl(tmp);
13107 +
13108 +                                                       if (f->opt[optnum].wc.wc == '%')
13109 +                                                       {
13110 +                                                               if ((tmp % f->opt[optnum].wc.val) != 0)
13111 +                                                                       fmatch = FMATCH_OPT_WRONG;
13112 +                                                       }
13113 +                                                       else if (tmp != f->opt[optnum].wc.val)
13114 +                                                               fmatch = FMATCH_OPT_WRONG;
13115 +                                               }
13116 +                                       }
13117 +
13118 +                                       optp = optend;
13119 +                               }
13120 +                               else
13121 +                                       fmatch = FMATCH_OPT_WRONG;
13122 +
13123 +                               if (fmatch != FMATCH_OK)
13124 +                                       break;
13125 +                       }
13126 +
13127 +                       if (fmatch != FMATCH_OPT_WRONG)
13128 +                       {
13129 +                               fmatch = FMATCH_WRONG;
13130 +
13131 +                               switch (check_WSS)
13132 +                               {
13133 +                                       case 0:
13134 +                                               if (f->wss.val == 0 || window == f->wss.val)
13135 +                                                       fmatch = FMATCH_OK;
13136 +                                               break;
13137 +                                       case 1: /* MSS */
13138 +/* Lurked in OpenBSD */
13139 +#define SMART_MSS      1460
13140 +                                               if (window == f->wss.val*mss || 
13141 +                                                       window == f->wss.val*SMART_MSS)
13142 +                                                       fmatch = FMATCH_OK;
13143 +                                               break;
13144 +                                       case 2: /* MTU */
13145 +                                               if (window == f->wss.val*(mss+40) ||
13146 +                                                       window == f->wss.val*(SMART_MSS+40))
13147 +                                                       fmatch = FMATCH_OK;
13148 +                                               break;
13149 +                                       case 3: /* MOD */
13150 +                                               if ((window % f->wss.val) == 0)
13151 +                                                       fmatch = FMATCH_OK;
13152 +                                               break;
13153 +                               }
13154 +                       }
13155 +                                       
13156 +
13157 +                       if (fmatch == FMATCH_OK)
13158 +                       {
13159 +                               fcount++;
13160 +                               log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n", 
13161 +                                       f->genre, f->version,
13162 +                                       f->subtype, f->details,
13163 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
13164 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest),
13165 +                                       f->ttl - ip->ttl);
13166 +                               if (info->flags & IPT_OSF_NETLINK)
13167 +                               {
13168 +                                       spin_lock_bh(&ipt_osf_netlink_lock);
13169 +                                       ipt_osf_nlsend(f, skb);
13170 +                                       spin_unlock_bh(&ipt_osf_netlink_lock);
13171 +                               }
13172 +                               if ((info->flags & IPT_OSF_LOG) && 
13173 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
13174 +                                       break;
13175 +                       }
13176 +               }
13177 +       }
13178 +       if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
13179 +       {
13180 +               unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
13181 +               unsigned int i, optsize;
13182 +               struct osf_finger fg;
13183 +
13184 +               memset(&fg, 0, sizeof(fg));
13185 +
13186 +               if ((info->flags & IPT_OSF_LOG))
13187 +                       log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
13188 +               if (optp)
13189 +               {
13190 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
13191 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
13192 +                                         opt, optsize) < 0)
13193 +                       {
13194 +                               if (info->flags & IPT_OSF_LOG)
13195 +                                       loga("TRUNCATED");
13196 +                               if (info->flags & IPT_OSF_NETLINK)
13197 +                                       strcpy(fg.details, "TRUNCATED");
13198 +                       }
13199 +                       else
13200 +                       {
13201 +                               for (i = 0; i < optsize; i++)
13202 +                               {
13203 +                                       if (info->flags & IPT_OSF_LOG)
13204 +                                               loga("%02X", opt[i]);
13205 +                               }
13206 +                               if (info->flags & IPT_OSF_NETLINK)
13207 +                                       memcpy(fg.details, opt, MAXDETLEN);
13208 +                       }
13209 +               }
13210 +               if ((info->flags & IPT_OSF_LOG))
13211 +                       loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
13212 +                               NIPQUAD(ip->saddr), ntohs(tcp->source),
13213 +                               NIPQUAD(ip->daddr), ntohs(tcp->dest));
13214 +               
13215 +               if (info->flags & IPT_OSF_NETLINK)
13216 +               {
13217 +                       fg.wss.val      = window;
13218 +                       fg.ttl          = ip->ttl;
13219 +                       fg.df           = df;
13220 +                       fg.ss           = totlen;
13221 +                       strncpy(fg.genre, "Unknown", MAXGENRELEN);
13222 +
13223 +                       spin_lock_bh(&ipt_osf_netlink_lock);
13224 +                       ipt_osf_nlsend(&fg, skb);
13225 +                       spin_unlock_bh(&ipt_osf_netlink_lock);
13226 +               }
13227 +       }
13228 +
13229 +       read_unlock(&osf_lock);
13230 +
13231 +       return (fmatch == FMATCH_OK)?1:0;
13232 +}
13233 +
13234 +static int
13235 +checkentry(const char *tablename,
13236 +           const struct ipt_ip *ip,
13237 +           void *matchinfo,
13238 +           unsigned int matchsize,
13239 +           unsigned int hook_mask)
13240 +{
13241 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
13242 +               return 0;
13243 +       if (ip->proto != IPPROTO_TCP)
13244 +              return 0;
13245 +
13246 +       return 1;
13247 +}
13248 +
13249 +static char * osf_strchr(char *ptr, char c)
13250 +{
13251 +       char *tmp;
13252 +
13253 +       tmp = strchr(ptr, c);
13254 +
13255 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
13256 +               tmp++;
13257 +
13258 +       return tmp;
13259 +}
13260 +
13261 +static struct osf_finger * finger_alloc(void)
13262 +{
13263 +       struct osf_finger *f;
13264 +
13265 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
13266 +       if (f)
13267 +               memset(f, 0, sizeof(struct osf_finger));
13268 +       
13269 +       return f;
13270 +}
13271 +
13272 +static void finger_free(struct osf_finger *f)
13273 +{
13274 +       memset(f, 0, sizeof(struct osf_finger));
13275 +       kfree(f);
13276 +}
13277 +
13278 +
13279 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
13280 +{
13281 +       int i, op;
13282 +       char *ptr, wc;
13283 +       unsigned long val;
13284 +
13285 +       ptr = &obuf[0];
13286 +       i = 0;
13287 +       while (ptr != NULL && i < olen)
13288 +       {
13289 +               val = 0;
13290 +               op = 0;
13291 +               wc = 0;
13292 +               switch (obuf[i])
13293 +               {
13294 +                       case 'N': 
13295 +                               op = OSFOPT_NOP;
13296 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13297 +                               if (ptr)
13298 +                               {
13299 +                                       *ptr = '\0';
13300 +                                       ptr++;
13301 +                                       i += (int)(ptr-&obuf[i]);
13302 +
13303 +                               }
13304 +                               else
13305 +                                       i++;
13306 +                               break;
13307 +                       case 'S': 
13308 +                               op = OSFOPT_SACKP;
13309 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13310 +                               if (ptr)
13311 +                               {
13312 +                                       *ptr = '\0';
13313 +                                       ptr++;
13314 +                                       i += (int)(ptr-&obuf[i]);
13315 +
13316 +                               }
13317 +                               else
13318 +                                       i++;
13319 +                               break;
13320 +                       case 'T': 
13321 +                               op = OSFOPT_TS;
13322 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13323 +                               if (ptr)
13324 +                               {
13325 +                                       *ptr = '\0';
13326 +                                       ptr++;
13327 +                                       i += (int)(ptr-&obuf[i]);
13328 +
13329 +                               }
13330 +                               else
13331 +                                       i++;
13332 +                               break;
13333 +                       case 'W': 
13334 +                               op = OSFOPT_WSO;
13335 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13336 +                               if (ptr)
13337 +                               {
13338 +                                       switch (obuf[i+1])
13339 +                                       {
13340 +                                               case '%':       wc = '%'; break;
13341 +                                               case 'S':       wc = 'S'; break;
13342 +                                               case 'T':       wc = 'T'; break;
13343 +                                               default:        wc = 0; break;
13344 +                                       }
13345 +                                       
13346 +                                       *ptr = '\0';
13347 +                                       ptr++;
13348 +                                       if (wc)
13349 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
13350 +                                       else
13351 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
13352 +                                       i += (int)(ptr-&obuf[i]);
13353 +
13354 +                               }
13355 +                               else
13356 +                                       i++;
13357 +                               break;
13358 +                       case 'M': 
13359 +                               op = OSFOPT_MSS;
13360 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13361 +                               if (ptr)
13362 +                               {
13363 +                                       if (obuf[i+1] == '%')
13364 +                                               wc = '%';
13365 +                                       *ptr = '\0';
13366 +                                       ptr++;
13367 +                                       if (wc)
13368 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
13369 +                                       else
13370 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
13371 +                                       i += (int)(ptr-&obuf[i]);
13372 +
13373 +                               }
13374 +                               else
13375 +                                       i++;
13376 +                               break;
13377 +                       case 'E': 
13378 +                               op = OSFOPT_EOL;
13379 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13380 +                               if (ptr)
13381 +                               {
13382 +                                       *ptr = '\0';
13383 +                                       ptr++;
13384 +                                       i += (int)(ptr-&obuf[i]);
13385 +
13386 +                               }
13387 +                               else
13388 +                                       i++;
13389 +                               break;
13390 +                       default:
13391 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13392 +                               if (ptr)
13393 +                               {
13394 +                                       ptr++;
13395 +                                       i += (int)(ptr-&obuf[i]);
13396 +
13397 +                               }
13398 +                               else
13399 +                                       i++;
13400 +                               break;
13401 +               }
13402 +
13403 +               opt[*optnum].kind       = IANA_opts[op].kind;
13404 +               opt[*optnum].length     = IANA_opts[op].length;
13405 +               opt[*optnum].wc.wc      = wc;
13406 +               opt[*optnum].wc.val     = val;
13407 +
13408 +               (*optnum)++;
13409 +       }
13410 +}
13411 +
13412 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
13413 +{
13414 +       struct list_head *ent;
13415 +       struct osf_finger *f = NULL;
13416 +       int i;
13417 +       
13418 +       *eof = 1;
13419 +       count = 0;
13420 +
13421 +       read_lock_bh(&osf_lock);
13422 +       list_for_each(ent, &finger_list)
13423 +       {
13424 +               f = list_entry(ent, struct osf_finger, flist);
13425 +
13426 +               log("%s [%s]", f->genre, f->details);
13427 +               
13428 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
13429 +                                       f->genre, f->version,
13430 +                                       f->subtype, f->details);
13431 +               
13432 +               if (f->opt_num)
13433 +               {
13434 +                       loga(" OPT: ");
13435 +                       //count += sprintf(buf+count, " OPT: ");
13436 +                       for (i=0; i<f->opt_num; ++i)
13437 +                       {
13438 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
13439 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13440 +                               loga("%d.%c%lu; ", 
13441 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13442 +                       }
13443 +               }
13444 +               loga("\n");
13445 +               count += sprintf(buf+count, "\n");
13446 +       }
13447 +       read_unlock_bh(&osf_lock);
13448 +
13449 +       return count;
13450 +}
13451 +
13452 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
13453 +{
13454 +       int cnt;
13455 +       unsigned long i;
13456 +       char obuf[MAXOPTSTRLEN];
13457 +       struct osf_finger *finger;
13458 +       struct list_head *ent, *n;
13459 +
13460 +       char *pbeg, *pend;
13461 +
13462 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
13463 +       {
13464 +               int i = 0;
13465 +               write_lock_bh(&osf_lock);
13466 +               list_for_each_safe(ent, n, &finger_list)
13467 +               {
13468 +                       i++;
13469 +                       finger = list_entry(ent, struct osf_finger, flist);
13470 +                       list_del(&finger->flist);
13471 +                       finger_free(finger);
13472 +               }
13473 +               write_unlock_bh(&osf_lock);
13474 +       
13475 +               log("Flushed %d entries.\n", i);
13476 +               
13477 +               return count;
13478 +       }
13479 +
13480 +       
13481 +       cnt = 0;
13482 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
13483 +               if (buffer[i] == ':')
13484 +                       cnt++;
13485 +
13486 +       if (cnt != 8 || i != count)
13487 +       {
13488 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
13489 +                       cnt, i, count);
13490 +               return count;
13491 +       }
13492 +
13493 +       memset(obuf, 0, sizeof(obuf));
13494 +       
13495 +       finger = finger_alloc();
13496 +       if (!finger)
13497 +       {
13498 +               log("Failed to allocate new fingerprint entry.\n");
13499 +               return -ENOMEM;
13500 +       }
13501 +
13502 +       pbeg = (char *)buffer;
13503 +       pend = osf_strchr(pbeg, OSFPDEL);
13504 +       if (pend)
13505 +       {
13506 +               *pend = '\0';
13507 +               if (pbeg[0] == 'S')
13508 +               {
13509 +                       finger->wss.wc = 'S';
13510 +                       if (pbeg[1] == '%')
13511 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13512 +                       else if (pbeg[1] == '*')
13513 +                               finger->wss.val = 0;
13514 +                       else 
13515 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13516 +               }
13517 +               else if (pbeg[0] == 'T')
13518 +               {
13519 +                       finger->wss.wc = 'T';
13520 +                       if (pbeg[1] == '%')
13521 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13522 +                       else if (pbeg[1] == '*')
13523 +                               finger->wss.val = 0;
13524 +                       else 
13525 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13526 +               }
13527 +               else if (pbeg[0] == '%')
13528 +               {
13529 +                       finger->wss.wc = '%';
13530 +                       finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13531 +               }
13532 +               else if (isdigit(pbeg[0]))
13533 +               {
13534 +                       finger->wss.wc = 0;
13535 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
13536 +               }
13537 +
13538 +               pbeg = pend+1;
13539 +       }
13540 +       pend = osf_strchr(pbeg, OSFPDEL);
13541 +       if (pend)
13542 +       {
13543 +               *pend = '\0';
13544 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
13545 +               pbeg = pend+1;
13546 +       }
13547 +       pend = osf_strchr(pbeg, OSFPDEL);
13548 +       if (pend)
13549 +       {
13550 +               *pend = '\0';
13551 +               finger->df = simple_strtoul(pbeg, NULL, 10);
13552 +               pbeg = pend+1;
13553 +       }
13554 +       pend = osf_strchr(pbeg, OSFPDEL);
13555 +       if (pend)
13556 +       {
13557 +               *pend = '\0';
13558 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
13559 +               pbeg = pend+1;
13560 +       }
13561 +
13562 +       pend = osf_strchr(pbeg, OSFPDEL);
13563 +       if (pend)
13564 +       {
13565 +               *pend = '\0';
13566 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
13567 +               pbeg = pend+1;
13568 +       }
13569 +
13570 +       pend = osf_strchr(pbeg, OSFPDEL);
13571 +       if (pend)
13572 +       {
13573 +               *pend = '\0';
13574 +               if (pbeg[0] == '@' || pbeg[0] == '*')
13575 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
13576 +               else
13577 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
13578 +               pbeg = pend+1;
13579 +       }
13580 +       
13581 +       pend = osf_strchr(pbeg, OSFPDEL);
13582 +       if (pend)
13583 +       {
13584 +               *pend = '\0';
13585 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
13586 +               pbeg = pend+1;
13587 +       }
13588 +       
13589 +       pend = osf_strchr(pbeg, OSFPDEL);
13590 +       if (pend)
13591 +       {
13592 +               *pend = '\0';
13593 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
13594 +               pbeg = pend+1;
13595 +       }
13596 +
13597 +       cnt = snprintf(finger->details, 
13598 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
13599 +                       "%s", pbeg);
13600 +       
13601 +       log("%s - %s[%s] : %s\n", 
13602 +               finger->genre, finger->version,
13603 +               finger->subtype, finger->details);
13604 +       
13605 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
13606 +       
13607 +
13608 +       write_lock_bh(&osf_lock);
13609 +       list_add_tail(&finger->flist, &finger_list);
13610 +       write_unlock_bh(&osf_lock);
13611 +
13612 +       return count;
13613 +}
13614 +
13615 +static int __init osf_init(void)
13616 +{
13617 +       int err;
13618 +       struct proc_dir_entry *p;
13619 +
13620 +       log("Startng OS fingerprint matching module.\n");
13621 +
13622 +       INIT_LIST_HEAD(&finger_list);
13623 +       
13624 +       err = ipt_register_match(&osf_match);
13625 +       if (err)
13626 +       {
13627 +               log("Failed to register OS fingerprint matching module.\n");
13628 +               return -ENXIO;
13629 +       }
13630 +
13631 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
13632 +       if (!p)
13633 +       {
13634 +               ipt_unregister_match(&osf_match);
13635 +               return -ENXIO;
13636 +       }
13637 +
13638 +       p->write_proc = osf_proc_write;
13639 +       p->read_proc  = osf_proc_read;
13640 +       
13641 +       nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
13642 +       if (!nts)
13643 +       {
13644 +               log("netlink_kernel_create() failed\n");
13645 +               remove_proc_entry("sys/net/ipv4/osf", NULL);
13646 +               ipt_unregister_match(&osf_match);
13647 +               return -ENOMEM;
13648 +       }
13649 +
13650 +       return 0;
13651 +}
13652 +
13653 +static void __exit osf_fini(void)
13654 +{
13655 +       struct list_head *ent, *n;
13656 +       struct osf_finger *f;
13657 +       
13658 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
13659 +       ipt_unregister_match(&osf_match);
13660 +       if (nts && nts->socket)
13661 +               sock_release(nts->socket);
13662 +
13663 +       list_for_each_safe(ent, n, &finger_list)
13664 +       {
13665 +               f = list_entry(ent, struct osf_finger, flist);
13666 +               list_del(&f->flist);
13667 +               finger_free(f);
13668 +       }
13669 +       
13670 +       log("OS fingerprint matching module finished.\n");
13671 +}
13672 +
13673 +module_init(osf_init);
13674 +module_exit(osf_fini);
13675 +
13676 +MODULE_LICENSE("GPL");
13677 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
13678 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
13679 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.7/net/ipv4/netfilter/ipt_owner.c
13680 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_owner.c      2004-06-25 10:47:46.000000000 +0200
13681 +++ linux-2.6.7/net/ipv4/netfilter/ipt_owner.c  2004-06-25 12:23:16.003716032 +0200
13682 @@ -6,12 +6,19 @@
13683   * This program is free software; you can redistribute it and/or modify
13684   * it under the terms of the GNU General Public License version 2 as
13685   * published by the Free Software Foundation.
13686 + *
13687 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
13688   */
13689  
13690  #include <linux/module.h>
13691  #include <linux/skbuff.h>
13692  #include <linux/file.h>
13693 +#include <linux/ip.h>
13694 +#include <linux/tcp.h>
13695 +#include <linux/udp.h>
13696  #include <net/sock.h>
13697 +#include <net/tcp.h>
13698 +#include <net/udp.h>
13699  
13700  #include <linux/netfilter_ipv4/ipt_owner.h>
13701  #include <linux/netfilter_ipv4/ip_tables.h>
13702 @@ -21,7 +28,7 @@
13703  MODULE_DESCRIPTION("iptables owner match");
13704  
13705  static int
13706 -match_comm(const struct sk_buff *skb, const char *comm)
13707 +match_comm(const struct sock *sk, const char *comm)
13708  {
13709         struct task_struct *g, *p;
13710         struct files_struct *files;
13711 @@ -38,7 +45,7 @@
13712                         spin_lock(&files->file_lock);
13713                         for (i=0; i < files->max_fds; i++) {
13714                                 if (fcheck_files(files, i) ==
13715 -                                   skb->sk->sk_socket->file) {
13716 +                                   sk->sk_socket->file) {
13717                                         spin_unlock(&files->file_lock);
13718                                         task_unlock(p);
13719                                         read_unlock(&tasklist_lock);
13720 @@ -54,7 +61,7 @@
13721  }
13722  
13723  static int
13724 -match_pid(const struct sk_buff *skb, pid_t pid)
13725 +match_pid(const struct sock *sk, pid_t pid)
13726  {
13727         struct task_struct *p;
13728         struct files_struct *files;
13729 @@ -70,7 +77,7 @@
13730                 spin_lock(&files->file_lock);
13731                 for (i=0; i < files->max_fds; i++) {
13732                         if (fcheck_files(files, i) ==
13733 -                           skb->sk->sk_socket->file) {
13734 +                           sk->sk_socket->file) {
13735                                 spin_unlock(&files->file_lock);
13736                                 task_unlock(p);
13737                                 read_unlock(&tasklist_lock);
13738 @@ -86,10 +93,10 @@
13739  }
13740  
13741  static int
13742 -match_sid(const struct sk_buff *skb, pid_t sid)
13743 +match_sid(const struct sock *sk, pid_t sid)
13744  {
13745         struct task_struct *g, *p;
13746 -       struct file *file = skb->sk->sk_socket->file;
13747 +       struct file *file = sk->sk_socket->file;
13748         int i, found=0;
13749  
13750         read_lock(&tasklist_lock);
13751 @@ -129,41 +136,71 @@
13752        int *hotdrop)
13753  {
13754         const struct ipt_owner_info *info = matchinfo;
13755 +       struct iphdr *iph = skb->nh.iph;
13756 +       struct sock *sk = NULL;
13757 +       int ret = 0;
13758 +
13759 +       if (out) {
13760 +               sk = skb->sk;
13761 +       } else {
13762 +               if (iph->protocol == IPPROTO_TCP) {
13763 +                       struct tcphdr *tcph =
13764 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
13765 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
13766 +                                          iph->daddr, tcph->dest,
13767 +                                          skb->dev->ifindex);
13768 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
13769 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
13770 +                               return ret;
13771 +                       }
13772 +               } else if (iph->protocol == IPPROTO_UDP) {
13773 +                       struct udphdr *udph =
13774 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
13775 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
13776 +                                          udph->dest, skb->dev->ifindex);
13777 +               }
13778 +       }
13779  
13780 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
13781 -               return 0;
13782 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
13783 +               goto out;
13784  
13785         if(info->match & IPT_OWNER_UID) {
13786 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
13787 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
13788                     !!(info->invert & IPT_OWNER_UID))
13789 -                       return 0;
13790 +                       goto out;
13791         }
13792  
13793         if(info->match & IPT_OWNER_GID) {
13794 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
13795 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
13796                     !!(info->invert & IPT_OWNER_GID))
13797 -                       return 0;
13798 +                       goto out;
13799         }
13800  
13801         if(info->match & IPT_OWNER_PID) {
13802 -               if (!match_pid(skb, info->pid) ^
13803 +               if (!match_pid(sk, info->pid) ^
13804                     !!(info->invert & IPT_OWNER_PID))
13805 -                       return 0;
13806 +                       goto out;
13807         }
13808  
13809         if(info->match & IPT_OWNER_SID) {
13810 -               if (!match_sid(skb, info->sid) ^
13811 +               if (!match_sid(sk, info->sid) ^
13812                     !!(info->invert & IPT_OWNER_SID))
13813 -                       return 0;
13814 +                       goto out;
13815         }
13816  
13817         if(info->match & IPT_OWNER_COMM) {
13818 -               if (!match_comm(skb, info->comm) ^
13819 +               if (!match_comm(sk, info->comm) ^
13820                     !!(info->invert & IPT_OWNER_COMM))
13821 -                       return 0;
13822 +                       goto out;
13823         }
13824  
13825 -       return 1;
13826 +       ret = 1;
13827 +
13828 +out:
13829 +       if (in && sk)
13830 +               sock_put(sk);
13831 +
13832 +       return ret;
13833  }
13834  
13835  static int
13836 @@ -173,11 +210,19 @@
13837             unsigned int matchsize,
13838             unsigned int hook_mask)
13839  {
13840 -        if (hook_mask
13841 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
13842 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
13843 -                return 0;
13844 -        }
13845 +       if (hook_mask
13846 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
13847 +           (1 << NF_IP_LOCAL_IN))) {
13848 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
13849 +                      "or POST_ROUTING.\n");
13850 +               return 0;
13851 +       }
13852 +
13853 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
13854 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
13855 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
13856 +               return 0;
13857 +       }
13858  
13859         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
13860                 printk("Matchsize %u != %Zu\n", matchsize,
13861 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.7/net/ipv4/netfilter/ipt_policy.c
13862 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_policy.c     1970-01-01 01:00:00.000000000 +0100
13863 +++ linux-2.6.7/net/ipv4/netfilter/ipt_policy.c 2004-03-08 05:19:04.000000000 +0100
13864 @@ -0,0 +1,176 @@
13865 +/* IP tables module for matching IPsec policy
13866 + *
13867 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
13868 + *
13869 + * This program is free software; you can redistribute it and/or modify
13870 + * it under the terms of the GNU General Public License version 2 as
13871 + * published by the Free Software Foundation.
13872 + */
13873 +
13874 +#include <linux/kernel.h>
13875 +#include <linux/config.h>
13876 +#include <linux/module.h>
13877 +#include <linux/skbuff.h>
13878 +#include <linux/init.h>
13879 +#include <net/xfrm.h>
13880 +
13881 +#include <linux/netfilter_ipv4.h>
13882 +#include <linux/netfilter_ipv4/ipt_policy.h>
13883 +#include <linux/netfilter_ipv4/ip_tables.h>
13884 +
13885 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
13886 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
13887 +MODULE_LICENSE("GPL");
13888 +
13889 +
13890 +static inline int
13891 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
13892 +{
13893 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
13894 +
13895 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
13896 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
13897 +           MISMATCH(proto, x->id.proto) ||
13898 +           MISMATCH(mode, x->props.mode) ||
13899 +           MISMATCH(spi, x->id.spi) ||
13900 +           MISMATCH(reqid, x->props.reqid))
13901 +               return 0;
13902 +       return 1;
13903 +}
13904 +
13905 +static int
13906 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
13907 +{
13908 +       const struct ipt_policy_elem *e;
13909 +       struct sec_path *sp = skb->sp;
13910 +       int strict = info->flags & POLICY_MATCH_STRICT;
13911 +       int i, pos;
13912 +
13913 +       if (sp == NULL)
13914 +               return -1;
13915 +       if (strict && info->len != sp->len)
13916 +               return 0;
13917 +
13918 +       for (i = sp->len - 1; i >= 0; i--) {
13919 +               pos = strict ? i - sp->len + 1 : 0;
13920 +               if (pos >= info->len)
13921 +                       return 0;
13922 +               e = &info->pol[pos];
13923 +
13924 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
13925 +                       if (!strict)
13926 +                               return 1;
13927 +               } else if (strict)
13928 +                       return 0;
13929 +       }
13930 +
13931 +       return strict ? 1 : 0;
13932 +}
13933 +
13934 +static int
13935 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
13936 +{
13937 +       const struct ipt_policy_elem *e;
13938 +       struct dst_entry *dst = skb->dst;
13939 +       int strict = info->flags & POLICY_MATCH_STRICT;
13940 +       int i, pos;
13941 +
13942 +       if (dst->xfrm == NULL)
13943 +               return -1;
13944 +
13945 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
13946 +               pos = strict ? i : 0;
13947 +               if (pos >= info->len)
13948 +                       return 0;
13949 +               e = &info->pol[pos];
13950 +
13951 +               if (match_xfrm_state(dst->xfrm, e)) {
13952 +                       if (!strict)
13953 +                               return 1;
13954 +               } else if (strict)
13955 +                       return 0;
13956 +       }
13957 +
13958 +       return strict ? 1 : 0;
13959 +}
13960 +
13961 +static int match(const struct sk_buff *skb,
13962 +                 const struct net_device *in,
13963 +                 const struct net_device *out,
13964 +                 const void *matchinfo, int offset, int *hotdrop)
13965 +{
13966 +       const struct ipt_policy_info *info = matchinfo;
13967 +       int ret;
13968 +
13969 +       if (info->flags & POLICY_MATCH_IN)
13970 +               ret = match_policy_in(skb, info);
13971 +       else
13972 +               ret = match_policy_out(skb, info);
13973 +
13974 +       if (ret < 0) {
13975 +               if (info->flags & POLICY_MATCH_NONE)
13976 +                       ret = 1;
13977 +               else
13978 +                       ret = 0;
13979 +       } else if (info->flags & POLICY_MATCH_NONE)
13980 +               ret = 0;
13981 +
13982 +       return ret;
13983 +}
13984 +
13985 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
13986 +                      void *matchinfo, unsigned int matchsize,
13987 +                      unsigned int hook_mask)
13988 +{
13989 +       struct ipt_policy_info *info = matchinfo;
13990 +
13991 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
13992 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
13993 +                      matchsize, IPT_ALIGN(sizeof(*info)));
13994 +               return 0;
13995 +       }
13996 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
13997 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
13998 +                               "outgoing policy selected\n");
13999 +               return 0;
14000 +       }
14001 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
14002 +           && info->flags & POLICY_MATCH_OUT) {
14003 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
14004 +                               "PRE_ROUTING and INPUT\n");
14005 +               return 0;
14006 +       }
14007 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
14008 +           && info->flags & POLICY_MATCH_IN) {
14009 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
14010 +                               "POST_ROUTING and OUTPUT\n");
14011 +               return 0;
14012 +       }
14013 +       if (info->len > POLICY_MAX_ELEM) {
14014 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
14015 +               return 0;
14016 +       }
14017 +
14018 +       return 1;
14019 +}
14020 +
14021 +static struct ipt_match policy_match =
14022 +{
14023 +       .name           = "policy",
14024 +       .match          = match,
14025 +       .checkentry     = checkentry,
14026 +       .me             = THIS_MODULE,
14027 +};
14028 +
14029 +static int __init init(void)
14030 +{
14031 +       return ipt_register_match(&policy_match);
14032 +}
14033 +
14034 +static void __exit fini(void)
14035 +{
14036 +       ipt_unregister_match(&policy_match);
14037 +}
14038 +
14039 +module_init(init);
14040 +module_exit(fini);
14041 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.7/net/ipv4/netfilter/ipt_pool.c
14042 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_pool.c       1970-01-01 01:00:00.000000000 +0100
14043 +++ linux-2.6.7/net/ipv4/netfilter/ipt_pool.c   2004-06-25 12:21:11.468648240 +0200
14044 @@ -0,0 +1,71 @@
14045 +/* Kernel module to match an IP address pool. */
14046 +
14047 +#include <linux/module.h>
14048 +#include <linux/ip.h>
14049 +#include <linux/skbuff.h>
14050 +
14051 +#include <linux/netfilter_ipv4/ip_tables.h>
14052 +#include <linux/netfilter_ipv4/ip_pool.h>
14053 +#include <linux/netfilter_ipv4/ipt_pool.h>
14054 +
14055 +static inline int match_pool(
14056 +       ip_pool_t index,
14057 +       __u32 addr,
14058 +       int inv
14059 +) {
14060 +       if (ip_pool_match(index, ntohl(addr)))
14061 +               inv = !inv;
14062 +       return inv;
14063 +}
14064 +
14065 +static int match(
14066 +       const struct sk_buff *skb,
14067 +       const struct net_device *in,
14068 +       const struct net_device *out,
14069 +       const void *matchinfo,
14070 +       int offset,
14071 +       const void *hdr,
14072 +       u_int16_t datalen,
14073 +       int *hotdrop
14074 +) {
14075 +       const struct ipt_pool_info *info = matchinfo;
14076 +       const struct iphdr *iph = skb->nh.iph;
14077 +
14078 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
14079 +                                               info->flags&IPT_POOL_INV_SRC))
14080 +               return 0;
14081 +
14082 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
14083 +                                               info->flags&IPT_POOL_INV_DST))
14084 +               return 0;
14085 +
14086 +       return 1;
14087 +}
14088 +
14089 +static int checkentry(
14090 +       const char *tablename,
14091 +       const struct ipt_ip *ip,
14092 +       void *matchinfo,
14093 +       unsigned int matchsize,
14094 +       unsigned int hook_mask
14095 +) {
14096 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
14097 +               return 0;
14098 +       return 1;
14099 +}
14100 +
14101 +static struct ipt_match pool_match
14102 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
14103 +
14104 +static int __init init(void)
14105 +{
14106 +       return ipt_register_match(&pool_match);
14107 +}
14108 +
14109 +static void __exit fini(void)
14110 +{
14111 +       ipt_unregister_match(&pool_match);
14112 +}
14113 +
14114 +module_init(init);
14115 +module_exit(fini);
14116 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.7/net/ipv4/netfilter/ipt_psd.c
14117 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c        1970-01-01 01:00:00.000000000 +0100
14118 +++ linux-2.6.7/net/ipv4/netfilter/ipt_psd.c    2004-06-25 12:21:11.947575432 +0200
14119 @@ -0,0 +1,358 @@
14120 +/*
14121 +  This is a module which is used for PSD (portscan detection)
14122 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
14123 +  and LOG target module.
14124 +
14125 +  Copyright (C) 2000,2001 astaro AG
14126 +
14127 +  This file is distributed under the terms of the GNU General Public
14128 +  License (GPL). Copies of the GPL can be obtained from:
14129 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
14130 +
14131 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
14132 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
14133 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
14134 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
14135 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
14136 +  2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
14137 +*/
14138 +
14139 +#include <linux/module.h>
14140 +#include <linux/skbuff.h>
14141 +#include <linux/ip.h>
14142 +#include <net/tcp.h>
14143 +#include <linux/spinlock.h>
14144 +#include <linux/netfilter_ipv4/ip_tables.h>
14145 +#include <linux/netfilter_ipv4/ipt_psd.h>
14146 +
14147 +#if 0
14148 +#define DEBUGP printk
14149 +#else
14150 +#define DEBUGP(format, args...)
14151 +#endif
14152 +
14153 +MODULE_LICENSE("GPL");
14154 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
14155 +
14156 +#define HF_DADDR_CHANGING   0x01
14157 +#define HF_SPORT_CHANGING   0x02
14158 +#define HF_TOS_CHANGING            0x04
14159 +#define HF_TTL_CHANGING            0x08
14160 +
14161 +/*
14162 + * Information we keep per each target port
14163 + */
14164 +struct port {
14165 +       u_int16_t number;      /* port number */
14166 +       u_int8_t proto;        /* protocol number */
14167 +       u_int8_t and_flags;    /* tcp ANDed flags */
14168 +       u_int8_t or_flags;     /* tcp ORed flags */
14169 +};
14170 +
14171 +/*
14172 + * Information we keep per each source address.
14173 + */
14174 +struct host {
14175 +       struct host *next;              /* Next entry with the same hash */
14176 +       clock_t timestamp;              /* Last update time */
14177 +       struct in_addr src_addr;        /* Source address */
14178 +       struct in_addr dest_addr;       /* Destination address */
14179 +       unsigned short src_port;        /* Source port */
14180 +       int count;                      /* Number of ports in the list */
14181 +       int weight;                     /* Total weight of ports in the list */
14182 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
14183 +       unsigned char tos;              /* TOS */
14184 +       unsigned char ttl;              /* TTL */
14185 +       unsigned char flags;            /* HF_ flags bitmask */
14186 +};
14187 +
14188 +/*
14189 + * State information.
14190 + */
14191 +static struct {
14192 +       spinlock_t lock;
14193 +       struct host list[LIST_SIZE];    /* List of source addresses */
14194 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
14195 +       int index;                      /* Oldest entry to be replaced */
14196 +} state;
14197 +
14198 +/*
14199 + * Convert an IP address into a hash table index.
14200 + */
14201 +static inline int hashfunc(struct in_addr addr)
14202 +{
14203 +       unsigned int value;
14204 +       int hash;
14205 +
14206 +       value = addr.s_addr;
14207 +       hash = 0;
14208 +       do {
14209 +               hash ^= value;
14210 +       } while ((value >>= HASH_LOG));
14211 +
14212 +       return hash & (HASH_SIZE - 1);
14213 +}
14214 +
14215 +static int
14216 +ipt_psd_match(const struct sk_buff *pskb,
14217 +             const struct net_device *in,
14218 +             const struct net_device *out,
14219 +             const void *matchinfo,
14220 +             int offset,
14221 +             int *hotdrop)
14222 +{
14223 +       struct iphdr *ip_hdr;
14224 +       struct tcphdr *tcp_hdr;
14225 +       struct in_addr addr;
14226 +       u_int16_t src_port,dest_port;
14227 +       u_int8_t tcp_flags, proto;
14228 +       clock_t now;
14229 +       struct host *curr, *last, **head;
14230 +       int hash, index, count;
14231 +
14232 +       /* Parameters from userspace */
14233 +       const struct ipt_psd_info *psdinfo = matchinfo;
14234 +
14235 +       /* IP header */
14236 +       ip_hdr = pskb->nh.iph;
14237 +
14238 +       /* Sanity check */
14239 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
14240 +               DEBUGP("PSD: sanity check failed\n");
14241 +               return 0;
14242 +       }
14243 +
14244 +       /* TCP or UDP ? */
14245 +       proto = ip_hdr->protocol;
14246 +
14247 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
14248 +               DEBUGP("PSD: protocol not supported\n");
14249 +               return 0;
14250 +       }
14251 +
14252 +       /* Get the source address, source & destination ports, and TCP flags */
14253 +
14254 +       addr.s_addr = ip_hdr->saddr;
14255 +
14256 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
14257 +
14258 +       /* Yep, it´s dirty */
14259 +       src_port = tcp_hdr->source;
14260 +       dest_port = tcp_hdr->dest;
14261 +
14262 +       if (proto == IPPROTO_TCP) {
14263 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
14264 +       }
14265 +       else {
14266 +               tcp_flags = 0x00;
14267 +       }
14268 +
14269 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
14270 +        * them spoof us. [DHCP needs this feature - HW] */
14271 +       if (!addr.s_addr) {
14272 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
14273 +               return 0;
14274 +       }
14275 +
14276 +       /* Use jiffies here not to depend on someone setting the time while we're
14277 +        * running; we need to be careful with possible return value overflows. */
14278 +       now = jiffies;
14279 +
14280 +       spin_lock(&state.lock);
14281 +
14282 +       /* Do we know this source address already? */
14283 +       count = 0;
14284 +       last = NULL;
14285 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
14286 +               do {
14287 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
14288 +                       count++;
14289 +                       if (curr->next) last = curr;
14290 +               } while ((curr = curr->next));
14291 +
14292 +       if (curr) {
14293 +
14294 +               /* We know this address, and the entry isn't too old. Update it. */
14295 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
14296 +                   time_after_eq(now, curr->timestamp)) {
14297 +
14298 +                       /* Just update the appropriate list entry if we've seen this port already */
14299 +                       for (index = 0; index < curr->count; index++) {
14300 +                               if (curr->ports[index].number == dest_port) {
14301 +                                       curr->ports[index].proto = proto;
14302 +                                       curr->ports[index].and_flags &= tcp_flags;
14303 +                                       curr->ports[index].or_flags |= tcp_flags;
14304 +                                       goto out_no_match;
14305 +                               }
14306 +                       }
14307 +
14308 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
14309 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
14310 +                               goto out_no_match;
14311 +
14312 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
14313 +                       curr->timestamp = now;
14314 +
14315 +                       /* Logged this scan already? Then drop the packet. */
14316 +                       if (curr->weight >= psdinfo->weight_threshold)
14317 +                               goto out_match;
14318 +
14319 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
14320 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
14321 +                               curr->flags |= HF_DADDR_CHANGING;
14322 +                       if (curr->src_port != src_port)
14323 +                               curr->flags |= HF_SPORT_CHANGING;
14324 +                       if (curr->tos != ip_hdr->tos)
14325 +                               curr->flags |= HF_TOS_CHANGING;
14326 +                       if (curr->ttl != ip_hdr->ttl)
14327 +                               curr->flags |= HF_TTL_CHANGING;
14328 +
14329 +                       /* Update the total weight */
14330 +                       curr->weight += (ntohs(dest_port) < 1024) ?
14331 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14332 +
14333 +                       /* Got enough destination ports to decide that this is a scan? */
14334 +                       /* Then log it and drop the packet. */
14335 +                       if (curr->weight >= psdinfo->weight_threshold)
14336 +                               goto out_match;
14337 +
14338 +                       /* Remember the new port */
14339 +                       if (curr->count < SCAN_MAX_COUNT) {
14340 +                               curr->ports[curr->count].number = dest_port;
14341 +                               curr->ports[curr->count].proto = proto;
14342 +                               curr->ports[curr->count].and_flags = tcp_flags;
14343 +                               curr->ports[curr->count].or_flags = tcp_flags;
14344 +                               curr->count++;
14345 +                       }
14346 +
14347 +                       goto out_no_match;
14348 +               }
14349 +
14350 +               /* We know this address, but the entry is outdated. Mark it unused, and
14351 +                * remove from the hash table. We'll allocate a new entry instead since
14352 +                * this one might get re-used too soon. */
14353 +               curr->src_addr.s_addr = 0;
14354 +               if (last)
14355 +                       last->next = last->next->next;
14356 +               else if (*head)
14357 +                       *head = (*head)->next;
14358 +               last = NULL;
14359 +       }
14360 +
14361 +       /* We don't need an ACK from a new source address */
14362 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
14363 +               goto out_no_match;
14364 +
14365 +       /* Got too many source addresses with the same hash value? Then remove the
14366 +        * oldest one from the hash table, so that they can't take too much of our
14367 +        * CPU time even with carefully chosen spoofed IP addresses. */
14368 +       if (count >= HASH_MAX && last) last->next = NULL;
14369 +
14370 +       /* We're going to re-use the oldest list entry, so remove it from the hash
14371 +        * table first (if it is really already in use, and isn't removed from the
14372 +        * hash table already because of the HASH_MAX check above). */
14373 +
14374 +       /* First, find it */
14375 +       if (state.list[state.index].src_addr.s_addr)
14376 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
14377 +       else
14378 +               head = &last;
14379 +       last = NULL;
14380 +       if ((curr = *head))
14381 +       do {
14382 +               if (curr == &state.list[state.index]) break;
14383 +               last = curr;
14384 +       } while ((curr = curr->next));
14385 +
14386 +       /* Then, remove it */
14387 +       if (curr) {
14388 +               if (last)
14389 +                       last->next = last->next->next;
14390 +               else if (*head)
14391 +                       *head = (*head)->next;
14392 +       }
14393 +
14394 +       /* Get our list entry */
14395 +       curr = &state.list[state.index++];
14396 +       if (state.index >= LIST_SIZE) state.index = 0;
14397 +
14398 +       /* Link it into the hash table */
14399 +       head = &state.hash[hash];
14400 +       curr->next = *head;
14401 +       *head = curr;
14402 +
14403 +       /* And fill in the fields */
14404 +       curr->timestamp = now;
14405 +       curr->src_addr = addr;
14406 +       curr->dest_addr.s_addr = ip_hdr->daddr;
14407 +       curr->src_port = src_port;
14408 +       curr->count = 1;
14409 +       curr->weight = (ntohs(dest_port) < 1024) ?
14410 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14411 +       curr->ports[0].number = dest_port;
14412 +       curr->ports[0].proto = proto;
14413 +       curr->ports[0].and_flags = tcp_flags;
14414 +       curr->ports[0].or_flags = tcp_flags;
14415 +       curr->tos = ip_hdr->tos;
14416 +       curr->ttl = ip_hdr->ttl;
14417 +
14418 +out_no_match:
14419 +       spin_unlock(&state.lock);
14420 +       return 0;
14421 +
14422 +out_match:
14423 +       spin_unlock(&state.lock);
14424 +       return 1;
14425 +}
14426 +
14427 +static int ipt_psd_checkentry(const char *tablename,
14428 +                             const struct ipt_ip *e,
14429 +                             void *matchinfo,
14430 +                             unsigned int matchsize,
14431 +                             unsigned int hook_mask)
14432 +{
14433 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
14434 +
14435 +       /* we accept TCP only */
14436 +/*     if (e->ip.proto != IPPROTO_TCP) { */
14437 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
14438 +/*             return 0; */
14439 +/*     } */
14440 +
14441 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
14442 +               DEBUGP("PSD: matchsize %u != %u\n",
14443 +                      matchsize,
14444 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
14445 +               return 0;
14446 +       }
14447 +
14448 +       return 1;
14449 +}
14450 +
14451 +static struct ipt_match ipt_psd_reg = {
14452 +       .name = "psd",
14453 +       .match = ipt_psd_match,
14454 +       .checkentry = ipt_psd_checkentry,
14455 +       .me = THIS_MODULE };
14456 +
14457 +static int __init init(void)
14458 +{
14459 +       if (ipt_register_match(&ipt_psd_reg))
14460 +               return -EINVAL;
14461 +
14462 +       memset(&state, 0, sizeof(state));
14463 +
14464 +       spin_lock_init(&(state.lock));
14465 +
14466 +       printk("netfilter PSD loaded - (c) astaro AG\n");
14467 +       return 0;
14468 +}
14469 +
14470 +static void __exit fini(void)
14471 +{
14472 +       ipt_unregister_match(&ipt_psd_reg);
14473 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
14474 +}
14475 +
14476 +module_init(init);
14477 +module_exit(fini);
14478 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.7/net/ipv4/netfilter/ipt_quota.c
14479 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c      1970-01-01 01:00:00.000000000 +0100
14480 +++ linux-2.6.7/net/ipv4/netfilter/ipt_quota.c  2004-06-25 12:21:12.435501256 +0200
14481 @@ -0,0 +1,91 @@
14482 +/* 
14483 + * netfilter module to enforce network quotas
14484 + *
14485 + * Sam Johnston <samj@samj.net>
14486 + */
14487 +#include <linux/module.h>
14488 +#include <linux/skbuff.h>
14489 +#include <linux/spinlock.h>
14490 +#include <linux/interrupt.h>
14491 +
14492 +#include <linux/netfilter_ipv4/ip_tables.h>
14493 +#include <linux/netfilter_ipv4/ipt_quota.h>
14494 +
14495 +MODULE_LICENSE("GPL");
14496 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
14497 +
14498 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
14499 +
14500 +static int
14501 +match(const struct sk_buff *skb,
14502 +      const struct net_device *in,
14503 +      const struct net_device *out,
14504 +      const void *matchinfo,
14505 +      int offset, int *hotdrop)
14506 +{
14507 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
14508 +       unsigned int datalen;
14509 +
14510 +       if (skb->len < sizeof(struct iphdr))
14511 +               return NF_ACCEPT;
14512 +       
14513 +       datalen = skb->len - skb->nh.iph->ihl*4;
14514 +
14515 +        spin_lock_bh(&quota_lock);
14516 +
14517 +        if (q->quota >= datalen) {
14518 +                /* we can afford this one */
14519 +                q->quota -= datalen;
14520 +                spin_unlock_bh(&quota_lock);
14521 +
14522 +#ifdef DEBUG_IPT_QUOTA
14523 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
14524 +#endif
14525 +                return 1;
14526 +        }
14527 +
14528 +        /* so we do not allow even small packets from now on */
14529 +        q->quota = 0;
14530 +
14531 +#ifdef DEBUG_IPT_QUOTA
14532 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
14533 +#endif
14534 +
14535 +        spin_unlock_bh(&quota_lock);
14536 +        return 0;
14537 +}
14538 +
14539 +static int
14540 +checkentry(const char *tablename,
14541 +           const struct ipt_ip *ip,
14542 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
14543 +{
14544 +        /* TODO: spinlocks? sanity checks? */
14545 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
14546 +                return 0;
14547 +
14548 +        return 1;
14549 +}
14550 +
14551 +static struct ipt_match quota_match = {
14552 +       .name = "quota",
14553 +       .match = match,
14554 +       .checkentry = checkentry,
14555 +       .me = THIS_MODULE
14556 +};
14557 +
14558 +static int __init
14559 +init(void)
14560 +{
14561 +        return ipt_register_match(&quota_match);
14562 +}
14563 +
14564 +static void __exit
14565 +fini(void)
14566 +{
14567 +        ipt_unregister_match(&quota_match);
14568 +}
14569 +
14570 +module_init(init);
14571 +module_exit(fini);
14572 +
14573 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_random.c linux-2.6.7/net/ipv4/netfilter/ipt_random.c
14574 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_random.c     1970-01-01 01:00:00.000000000 +0100
14575 +++ linux-2.6.7/net/ipv4/netfilter/ipt_random.c 2004-06-25 12:21:12.938424800 +0200
14576 @@ -0,0 +1,96 @@
14577 +/*
14578 +  This is a module which is used for a "random" match support.
14579 +  This file is distributed under the terms of the GNU General Public
14580 +  License (GPL). Copies of the GPL can be obtained from:
14581 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
14582 +
14583 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14584 +*/
14585 +
14586 +#include <linux/module.h>
14587 +#include <linux/skbuff.h>
14588 +#include <linux/ip.h>
14589 +#include <linux/random.h>
14590 +#include <net/tcp.h>
14591 +#include <linux/spinlock.h>
14592 +#include <linux/netfilter_ipv4/ip_tables.h>
14593 +#include <linux/netfilter_ipv4/ipt_random.h>
14594 +
14595 +MODULE_LICENSE("GPL");
14596 +
14597 +static int
14598 +ipt_rand_match(const struct sk_buff *pskb,
14599 +              const struct net_device *in,
14600 +              const struct net_device *out,
14601 +              const void *matchinfo,
14602 +              int offset,
14603 +              const void *hdr,
14604 +              u_int16_t datalen,
14605 +              int *hotdrop)
14606 +{
14607 +       /* Parameters from userspace */
14608 +       const struct ipt_rand_info *info = matchinfo;
14609 +       u_int8_t random_number;
14610 +
14611 +       /* get 1 random number from the kernel random number generation routine */
14612 +       get_random_bytes((void *)(&random_number), 1);
14613 +
14614 +       /* Do we match ? */
14615 +       if (random_number <= info->average)
14616 +               return 1;
14617 +       else
14618 +               return 0;
14619 +}
14620 +
14621 +static int
14622 +ipt_rand_checkentry(const char *tablename,
14623 +                  const struct ipt_ip *e,
14624 +                  void *matchinfo,
14625 +                  unsigned int matchsize,
14626 +                  unsigned int hook_mask)
14627 +{
14628 +       /* Parameters from userspace */
14629 +       const struct ipt_rand_info *info = matchinfo;
14630 +
14631 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
14632 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
14633 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
14634 +               return 0;
14635 +       }
14636 +
14637 +       /* must be  1 <= average % <= 99 */
14638 +       /* 1  x 2.55 = 2   */
14639 +       /* 99 x 2.55 = 252 */
14640 +       if ((info->average < 2) || (info->average > 252)) {
14641 +               printk("ipt_random:  invalid average %u\n", info->average);
14642 +               return 0;
14643 +       }
14644 +
14645 +       return 1;
14646 +}
14647 +
14648 +static struct ipt_match ipt_rand_reg = { 
14649 +       {NULL, NULL},
14650 +       "random",
14651 +       ipt_rand_match,
14652 +       ipt_rand_checkentry,
14653 +       NULL,
14654 +       THIS_MODULE };
14655 +
14656 +static int __init init(void)
14657 +{
14658 +       if (ipt_register_match(&ipt_rand_reg))
14659 +               return -EINVAL;
14660 +
14661 +       printk("ipt_random match loaded\n");
14662 +       return 0;
14663 +}
14664 +
14665 +static void __exit fini(void)
14666 +{
14667 +       ipt_unregister_match(&ipt_rand_reg);
14668 +       printk("ipt_random match unloaded\n");
14669 +}
14670 +
14671 +module_init(init);
14672 +module_exit(fini);
14673 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c
14674 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c       1970-01-01 01:00:00.000000000 +0100
14675 +++ linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c   2004-06-25 12:21:13.447347432 +0200
14676 @@ -0,0 +1,199 @@
14677 +#include <linux/module.h>
14678 +#include <linux/skbuff.h>
14679 +#include <net/ip.h>
14680 +#include <linux/sctp.h>
14681 +
14682 +#include <linux/netfilter_ipv4/ip_tables.h>
14683 +#include <linux/netfilter_ipv4/ipt_sctp.h>
14684 +
14685 +#if 0
14686 +#define duprintf(format, args...) printk(format , ## args)
14687 +#else
14688 +#define duprintf(format, args...)
14689 +#endif
14690 +
14691 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
14692 +                                             || (!!((invflag) & (option)) ^ (cond)))
14693 +
14694 +static int
14695 +match_flags(const struct ipt_sctp_flag_info *flag_info,
14696 +           const int flag_count,
14697 +           u_int8_t chunktype,
14698 +           u_int8_t chunkflags)
14699 +{
14700 +       int i;
14701 +
14702 +       for (i = 0; i < flag_count; i++) {
14703 +               if (flag_info[i].chunktype == chunktype) {
14704 +                       return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
14705 +               }
14706 +       }
14707 +
14708 +       return 1;
14709 +}
14710 +
14711 +static int
14712 +match_packet(const struct sk_buff *skb,
14713 +            const u_int32_t *chunkmap,
14714 +            int chunk_match_type,
14715 +            const struct ipt_sctp_flag_info *flag_info,
14716 +            const int flag_count,
14717 +            int *hotdrop)
14718 +{
14719 +       int offset;
14720 +       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
14721 +       sctp_chunkhdr_t sch;
14722 +
14723 +       int i = 0;
14724 +
14725 +       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
14726 +               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
14727 +       }
14728 +
14729 +       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
14730 +       do {
14731 +               if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
14732 +                       duprintf("Dropping invalid SCTP packet.\n");
14733 +                       *hotdrop = 1;
14734 +                       return 0;
14735 +               }
14736 +
14737 +               duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
14738 +                               ++i, offset, sch.type, htons(sch.length), sch.flags);
14739 +
14740 +               offset += (htons(sch.length) + 3) & ~3;
14741 +
14742 +               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
14743 +
14744 +               if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
14745 +                       switch (chunk_match_type) {
14746 +                       case SCTP_CHUNK_MATCH_ANY:
14747 +                               if (match_flags(flag_info, flag_count, 
14748 +                                       sch.type, sch.flags)) {
14749 +                                       return 1;
14750 +                               }
14751 +                               break;
14752 +
14753 +                       case SCTP_CHUNK_MATCH_ALL:
14754 +                               if (match_flags(flag_info, flag_count, 
14755 +                                       sch.type, sch.flags)) {
14756 +                                       SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
14757 +                               }
14758 +                               break;
14759 +
14760 +                       case SCTP_CHUNK_MATCH_ONLY:
14761 +                               if (!match_flags(flag_info, flag_count, 
14762 +                                       sch.type, sch.flags)) {
14763 +                                       return 0;
14764 +                               }
14765 +                               break;
14766 +                       }
14767 +               } else {
14768 +                       switch (chunk_match_type) {
14769 +                       case SCTP_CHUNK_MATCH_ONLY:
14770 +                               return 0;
14771 +                       }
14772 +               }
14773 +       } while (offset < skb->len);
14774 +
14775 +       switch (chunk_match_type) {
14776 +       case SCTP_CHUNK_MATCH_ALL:
14777 +               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
14778 +       case SCTP_CHUNK_MATCH_ANY:
14779 +               return 0;
14780 +       case SCTP_CHUNK_MATCH_ONLY:
14781 +               return 1;
14782 +       }
14783 +
14784 +       /* This will never be reached, but required to stop compiler whine */
14785 +       return 0;
14786 +}
14787 +
14788 +static int
14789 +match(const struct sk_buff *skb,
14790 +      const struct net_device *in,
14791 +      const struct net_device *out,
14792 +      const void *matchinfo,
14793 +      int offset,
14794 +      int *hotdrop)
14795 +{
14796 +       const struct ipt_sctp_info *info;
14797 +       sctp_sctphdr_t sh;
14798 +
14799 +       info = (const struct ipt_sctp_info *)matchinfo;
14800 +
14801 +       if (offset) {
14802 +               duprintf("Dropping non-first fragment.. FIXME\n");
14803 +               return 0;
14804 +       }
14805 +       
14806 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
14807 +               duprintf("Dropping evil TCP offset=0 tinygram.\n");
14808 +               *hotdrop = 1;
14809 +               return 0;
14810 +               }
14811 +       duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
14812 +
14813 +       return  SCCHECK(((ntohs(sh.source) >= info->spts[0]) 
14814 +                       && (ntohs(sh.source) <= info->spts[1])), 
14815 +                       IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
14816 +               && SCCHECK(((ntohs(sh.dest) >= info->dpts[0]) 
14817 +                       && (ntohs(sh.dest) <= info->dpts[1])), 
14818 +                       IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
14819 +               && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
14820 +                                       info->flag_info, info->flag_count, 
14821 +                                       hotdrop),
14822 +                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
14823 +}
14824 +
14825 +static int
14826 +checkentry(const char *tablename,
14827 +          const struct ipt_ip *ip,
14828 +          void *matchinfo,
14829 +          unsigned int matchsize,
14830 +          unsigned int hook_mask)
14831 +{
14832 +       const struct ipt_sctp_info *info;
14833 +
14834 +       info = (const struct ipt_sctp_info *)matchinfo;
14835 +
14836 +       return ip->proto == IPPROTO_SCTP
14837 +               && !(ip->invflags & IPT_INV_PROTO)
14838 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
14839 +               && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
14840 +               && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
14841 +               && !(info->invflags & ~info->flags)
14842 +               && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
14843 +                       (info->chunk_match_type &
14844 +                               (SCTP_CHUNK_MATCH_ALL 
14845 +                               | SCTP_CHUNK_MATCH_ANY
14846 +                               | SCTP_CHUNK_MATCH_ONLY)));
14847 +}
14848 +
14849 +static struct ipt_match sctp_match = 
14850 +{ 
14851 +       .list = { NULL, NULL},
14852 +       .name = "sctp",
14853 +       .match = &match,
14854 +       .checkentry = &checkentry,
14855 +       .destroy = NULL,
14856 +       .me = THIS_MODULE
14857 +};
14858 +
14859 +static int __init init(void)
14860 +{
14861 +       return ipt_register_match(&sctp_match);
14862 +}
14863 +
14864 +static void __exit fini(void)
14865 +{
14866 +       ipt_unregister_match(&sctp_match);
14867 +}
14868 +
14869 +module_init(init);
14870 +module_exit(fini);
14871 +
14872 +MODULE_LICENSE("GPL");
14873 +MODULE_AUTHOR("Kiran Kumar Immidi");
14874 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
14875 +
14876 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_string.c linux-2.6.7/net/ipv4/netfilter/ipt_string.c
14877 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_string.c     1970-01-01 01:00:00.000000000 +0100
14878 +++ linux-2.6.7/net/ipv4/netfilter/ipt_string.c 2004-06-25 12:28:38.572678096 +0200
14879 @@ -0,0 +1,183 @@
14880 +/* Kernel module to match a string into a packet.
14881 + *
14882 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
14883 + * 
14884 + * ChangeLog
14885 + *     24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
14886 + *             Initial 2.6 port
14887 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
14888 + *             Fixed SMP re-entrancy problem using per-cpu data areas
14889 + *             for the skip/shift tables.
14890 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14891 + *             Fixed kernel panic, due to overrunning boyer moore string
14892 + *             tables. Also slightly tweaked heuristic for deciding what
14893 + *             search algo to use.
14894 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14895 + *             Implemented Boyer Moore Sublinear search algorithm
14896 + *             alongside the existing linear search based on memcmp().
14897 + *             Also a quick check to decide which method to use on a per
14898 + *             packet basis.
14899 + */
14900 +
14901 +#include <linux/smp.h>
14902 +#include <linux/percpu.h>
14903 +#include <linux/module.h>
14904 +#include <linux/skbuff.h>
14905 +#include <linux/file.h>
14906 +#include <net/sock.h>
14907 +
14908 +#include <linux/netfilter_ipv4/ip_tables.h>
14909 +#include <linux/netfilter_ipv4/ipt_string.h>
14910 +
14911 +MODULE_LICENSE("GPL");
14912 +
14913 +struct string_per_cpu {
14914 +       int skip[BM_MAX_HLEN];
14915 +       int shift[BM_MAX_HLEN];
14916 +       int len[BM_MAX_HLEN];
14917 +};
14918 +
14919 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
14920 +
14921 +
14922 +/* Boyer Moore Sublinear string search - VERY FAST */
14923 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
14924 +{
14925 +       int M1, right_end, sk, sh;  
14926 +       int ended, j, i;
14927 +
14928 +       int *skip, *shift, *len;
14929 +       
14930 +       /* use data suitable for this CPU */
14931 +       shift=__get_cpu_var(bm_string_data).shift;
14932 +       skip=__get_cpu_var(bm_string_data).skip;
14933 +       len=__get_cpu_var(bm_string_data).len;
14934 +       
14935 +       /* Setup skip/shift tables */
14936 +       M1 = right_end = needle_len-1;
14937 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
14938 +       for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
14939 +
14940 +       for (i = 1; i < needle_len; i++) {   
14941 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
14942 +               len[i] = j;  
14943 +       }  
14944 +
14945 +       shift[0] = 1;  
14946 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
14947 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
14948 +       ended = 0;  
14949 +       
14950 +       for (i = 0; i < needle_len; i++) {  
14951 +               if (len[i] == M1 - i) ended = i;  
14952 +               if (ended) shift[i] = ended;  
14953 +       }  
14954 +
14955 +       /* Do the search*/  
14956 +       while (right_end < haystack_len)
14957 +       {
14958 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
14959 +               if (i == needle_len) {
14960 +                       return haystack+(right_end - M1);
14961 +               }
14962 +               
14963 +               sk = skip[(int)haystack[right_end - i]];  
14964 +               sh = shift[i];
14965 +               right_end = max(right_end - i + sk, right_end + sh);  
14966 +       }
14967 +
14968 +       return NULL;
14969 +}  
14970 +
14971 +/* Linear string search based on memcmp() */
14972 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
14973 +{
14974 +       char *k = haystack + (haystack_len-needle_len);
14975 +       char *t = haystack;
14976 +       
14977 +       while ( t <= k ) {
14978 +               if (memcmp(t, needle, needle_len) == 0)
14979 +                       return t;
14980 +               t++;
14981 +       }
14982 +
14983 +       return NULL;
14984 +}
14985 +
14986 +static int
14987 +match(const struct sk_buff *skb,
14988 +      const struct net_device *in,
14989 +      const struct net_device *out,
14990 +      const void *matchinfo,
14991 +      int offset,
14992 +      int *hotdrop)
14993 +{
14994 +       const struct ipt_string_info *info = matchinfo;
14995 +       struct iphdr *ip = skb->nh.iph;
14996 +       int hlen, nlen;
14997 +       char *needle, *haystack;
14998 +       proc_ipt_search search=search_linear;
14999 +
15000 +       if ( !ip ) return 0;
15001 +
15002 +       /* get lenghts, and validate them */
15003 +       nlen=info->len;
15004 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
15005 +       if ( nlen > hlen ) return 0;
15006 +
15007 +       needle=(char *)&info->string;
15008 +       haystack=(char *)ip+(ip->ihl*4);
15009 +
15010 +       /* The sublinear search comes in to its own
15011 +        * on the larger packets */
15012 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
15013 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
15014 +               if ( hlen < BM_MAX_HLEN ) {
15015 +                       search=search_sublinear;
15016 +               }else{
15017 +                       if (net_ratelimit())
15018 +                               printk(KERN_INFO "ipt_string: Packet too big "
15019 +                                       "to attempt sublinear string search "
15020 +                                       "(%d bytes)\n", hlen );
15021 +               }
15022 +       }
15023 +       
15024 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
15025 +}
15026 +
15027 +static int
15028 +checkentry(const char *tablename,
15029 +           const struct ipt_ip *ip,
15030 +           void *matchinfo,
15031 +           unsigned int matchsize,
15032 +           unsigned int hook_mask)
15033 +{
15034 +
15035 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
15036 +               return 0;
15037 +
15038 +       return 1;
15039 +}
15040 +
15041 +static struct ipt_match string_match = {
15042 +    .name = "string",
15043 +    .match = &match,
15044 +    .checkentry = &checkentry,
15045 +    .me = THIS_MODULE
15046 +};
15047 +
15048 +
15049 +static int __init init(void)
15050 +{
15051 +       return ipt_register_match(&string_match);
15052 +}
15053 +
15054 +static void __exit fini(void)
15055 +{
15056 +       ipt_unregister_match(&string_match);
15057 +}
15058 +
15059 +module_init(init);
15060 +module_exit(fini);
15061 +
15062 +
15063 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c linux-2.6.7/net/ipv4/netfilter/ipt_time.c
15064 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c       1970-01-01 01:00:00.000000000 +0100
15065 +++ linux-2.6.7/net/ipv4/netfilter/ipt_time.c   2004-06-25 12:21:13.934273408 +0200
15066 @@ -0,0 +1,189 @@
15067 +/*
15068 +  This is a module which is used for time matching
15069 +  It is using some modified code from dietlibc (localtime() function)
15070 +  that you can find at http://www.fefe.de/dietlibc/
15071 +  This file is distributed under the terms of the GNU General Public
15072 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
15073 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
15074 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
15075 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
15076 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
15077 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
15078 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
15079 +  2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
15080 +*/
15081 +
15082 +#include <linux/module.h>
15083 +#include <linux/skbuff.h>
15084 +#include <linux/netfilter_ipv4/ip_tables.h>
15085 +#include <linux/netfilter_ipv4/ipt_time.h>
15086 +#include <linux/time.h>
15087 +
15088 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
15089 +MODULE_DESCRIPTION("Match arrival timestamp/date");
15090 +MODULE_LICENSE("GPL");
15091 +
15092 +struct tm
15093 +{
15094 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
15095 +       int tm_min;                   /* Minutes.     [0-59] */
15096 +       int tm_hour;                  /* Hours.       [0-23] */
15097 +       int tm_mday;                  /* Day.         [1-31] */
15098 +       int tm_mon;                   /* Month.       [0-11] */
15099 +       int tm_year;                  /* Year - 1900.  */
15100 +       int tm_wday;                  /* Day of week. [0-6] */
15101 +       int tm_yday;                  /* Days in year.[0-365] */
15102 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
15103 +
15104 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
15105 +       const char *tm_zone;          /* we don't care, we count from GMT */
15106 +};
15107 +
15108 +void
15109 +localtime(const time_t *timepr, struct tm *r);
15110 +
15111 +static int
15112 +match(const struct sk_buff *skb,
15113 +      const struct net_device *in,
15114 +      const struct net_device *out,
15115 +      const void *matchinfo,
15116 +      int offset,
15117 +      const void *hdr,
15118 +      u_int16_t datalen,
15119 +      int *hotdrop)
15120 +{
15121 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
15122 +       struct tm currenttime;                          /* time human readable */
15123 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
15124 +       u_int16_t packet_time;
15125 +       struct timeval kerneltimeval;
15126 +       time_t packet_local_time;
15127 +
15128 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
15129 +       if (info->kerneltime)
15130 +       {
15131 +               do_gettimeofday(&kerneltimeval);
15132 +               packet_local_time = kerneltimeval.tv_sec;
15133 +       }
15134 +       else
15135 +               packet_local_time = skb->stamp.tv_sec;
15136 +
15137 +       /* First we make sure we are in the date start-stop boundaries */
15138 +       if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
15139 +               return 0; /* We are outside the date boundaries */
15140 +
15141 +       /* Transform the timestamp of the packet, in a human readable form */
15142 +       localtime(&packet_local_time, &currenttime);
15143 +
15144 +       /* check if we match this timestamp, we start by the days... */
15145 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
15146 +               return 0; /* the day doesn't match */
15147 +
15148 +       /* ... check the time now */
15149 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
15150 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
15151 +               return 0;
15152 +
15153 +       /* here we match ! */
15154 +       return 1;
15155 +}
15156 +
15157 +static int
15158 +checkentry(const char *tablename,
15159 +           const struct ipt_ip *ip,
15160 +           void *matchinfo,
15161 +           unsigned int matchsize,
15162 +           unsigned int hook_mask)
15163 +{
15164 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
15165 +
15166 +       /* First, check that we are in the correct hooks */
15167 +       if (hook_mask
15168 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15169 +       {
15170 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
15171 +               return 0;
15172 +       }
15173 +       /* we use the kerneltime if we are in forward or output */
15174 +       info->kerneltime = 1;
15175 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
15176 +               /* we use the skb time */
15177 +               info->kerneltime = 0;
15178 +
15179 +       /* Check the size */
15180 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
15181 +               return 0;
15182 +       /* Now check the coherence of the data ... */
15183 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
15184 +           (info->time_stop  > 1439))
15185 +       {
15186 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
15187 +               return 0;
15188 +       }
15189 +
15190 +       return 1;
15191 +}
15192 +
15193 +static struct ipt_match time_match
15194 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
15195 +
15196 +static int __init init(void)
15197 +{
15198 +       printk("ipt_time loading\n");
15199 +       return ipt_register_match(&time_match);
15200 +}
15201 +
15202 +static void __exit fini(void)
15203 +{
15204 +       ipt_unregister_match(&time_match);
15205 +       printk("ipt_time unloaded\n");
15206 +}
15207 +
15208 +module_init(init);
15209 +module_exit(fini);
15210 +
15211 +
15212 +/* The part below is borowed and modified from dietlibc */
15213 +
15214 +/* seconds per day */
15215 +#define SPD 24*60*60
15216 +
15217 +void
15218 +localtime(const time_t *timepr, struct tm *r) {
15219 +       time_t i;
15220 +       time_t timep;
15221 +       extern struct timezone sys_tz;
15222 +       const unsigned int __spm[12] =
15223 +               { 0,
15224 +                 (31),
15225 +                 (31+28),
15226 +                 (31+28+31),
15227 +                 (31+28+31+30),
15228 +                 (31+28+31+30+31),
15229 +                 (31+28+31+30+31+30),
15230 +                 (31+28+31+30+31+30+31),
15231 +                 (31+28+31+30+31+30+31+31),
15232 +                 (31+28+31+30+31+30+31+31+30),
15233 +                 (31+28+31+30+31+30+31+31+30+31),
15234 +                 (31+28+31+30+31+30+31+31+30+31+30),
15235 +               };
15236 +       register time_t work;
15237 +
15238 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
15239 +       work=timep%(SPD);
15240 +       r->tm_sec=work%60; work/=60;
15241 +       r->tm_min=work%60; r->tm_hour=work/60;
15242 +       work=timep/(SPD);
15243 +       r->tm_wday=(4+work)%7;
15244 +       for (i=1970; ; ++i) {
15245 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
15246 +               if (work>k)
15247 +                       work-=k;
15248 +               else
15249 +                       break;
15250 +       }
15251 +       r->tm_year=i-1900;
15252 +       for (i=11; i && __spm[i]>work; --i) ;
15253 +       r->tm_mon=i;
15254 +       r->tm_mday=work-__spm[i]+1;
15255 +}
15256 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.7/net/ipv4/netfilter/ipt_u32.c
15257 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c        1970-01-01 01:00:00.000000000 +0100
15258 +++ linux-2.6.7/net/ipv4/netfilter/ipt_u32.c    2004-06-25 12:21:14.422199232 +0200
15259 @@ -0,0 +1,211 @@
15260 +/* Kernel module to match u32 packet content. */
15261 +
15262 +/* 
15263 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
15264 +have specified values.  The specification of what to extract is general 
15265 +enough to find data at given offsets from tcp headers or payloads.
15266 +
15267 + --u32 tests
15268 + The argument amounts to a program in a small language described below.
15269 + tests := location = value |  tests && location = value
15270 + value := range | value , range
15271 + range := number | number : number
15272 +  a single number, n, is interpreted the same as n:n
15273 +  n:m is interpreted as the range of numbers >=n and <=m
15274 + location := number | location operator number
15275 + operator := & | << | >> | @
15276 +
15277 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
15278 + membership operator and the value syntax describes a set.  The @ operator
15279 + is what allows moving to the next header and is described further below.
15280 +
15281 + *** Until I can find out how to avoid it, there are some artificial limits
15282 + on the size of the tests:
15283 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
15284 + - no more than 10 ranges (and 9 commas) per value
15285 + - no more than 10 numbers (and 9 operators) per location
15286 +
15287 + To describe the meaning of location, imagine the following machine that
15288 + interprets it.  There are three registers:
15289 +  A is of type char*, initially the address of the IP header
15290 +  B and C are unsigned 32 bit integers, initially zero
15291 +
15292 +  The instructions are:
15293 +   number      B = number;
15294 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
15295 +   &number     C = C&number
15296 +   <<number    C = C<<number
15297 +   >>number    C = C>>number
15298 +   @number     A = A+C; then do the instruction number
15299 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
15300 +  Otherwise the result of the computation is the final value of C.
15301 +
15302 + Whitespace is allowed but not required in the tests.
15303 + However the characters that do occur there are likely to require
15304 + shell quoting, so it's a good idea to enclose the arguments in quotes.
15305 +
15306 +Example:
15307 + match IP packets with total length >= 256
15308 + The IP header contains a total length field in bytes 2-3.
15309 + --u32 "0&0xFFFF=0x100:0xFFFF" 
15310 + read bytes 0-3
15311 + AND that with FFFF (giving bytes 2-3),
15312 + and test whether that's in the range [0x100:0xFFFF]
15313 +
15314 +Example: (more realistic, hence more complicated)
15315 + match icmp packets with icmp type 0
15316 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
15317 + --u32 "6&0xFF=1 && ...
15318 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
15319 + Next test that it's not a fragment.
15320 +  (If so it might be part of such a packet but we can't always tell.)
15321 +  n.b. This test is generally needed if you want to match anything
15322 +  beyond the IP header.
15323 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
15324 + packet (not a fragment).  Alternatively, you can allow first fragments
15325 + by only testing the last 5 bits of byte 6.
15326 + ... 4&0x3FFF=0 && ...
15327 + Last test: the first byte past the IP header (the type) is 0
15328 + This is where we have to use the @syntax.  The length of the IP header
15329 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
15330 + IP header itself.
15331 + ... 0>>22&0x3C@0>>24=0"
15332 + The first 0 means read bytes 0-3,
15333 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
15334 +   the first byte, so only 22 bits is four times that plus a few more bits.
15335 + &3C then eliminates the two extra bits on the right and the first four 
15336 + bits of the first byte.
15337 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
15338 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
15339 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
15340 + @ means to use this number as a new offset into the packet, and read
15341 + four bytes starting from there.  This is the first 4 bytes of the icmp
15342 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
15343 + the value 24 to the right to throw out all but the first byte and compare
15344 + the result with 0.
15345 +
15346 +Example: 
15347 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
15348 + First we test that the packet is a tcp packet (similar to icmp).
15349 + --u32 "6&0xFF=6 && ...
15350 + Next, test that it's not a fragment (same as above).
15351 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
15352 + 0>>22&3C as above computes the number of bytes in the IP header.
15353 + @ makes this the new offset into the packet, which is the start of the
15354 + tcp header.  The length of the tcp header (again in 32 bit words) is
15355 + the left half of byte 12 of the tcp header.  The 12>>26&3C
15356 + computes this length in bytes (similar to the IP header before).
15357 + @ makes this the new offset, which is the start of the tcp payload.
15358 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
15359 + result is any of 1, 2, 5 or 8
15360 +*/
15361 +
15362 +#include <linux/module.h>
15363 +#include <linux/skbuff.h>
15364 +
15365 +#include <linux/netfilter_ipv4/ipt_u32.h>
15366 +#include <linux/netfilter_ipv4/ip_tables.h>
15367 +
15368 +/* #include <asm-i386/timex.h> for timing */
15369 +
15370 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
15371 +MODULE_DESCRIPTION("IP tables u32 matching module");
15372 +MODULE_LICENSE("GPL");
15373 +
15374 +static int
15375 +match(const struct sk_buff *skb,
15376 +      const struct net_device *in,
15377 +      const struct net_device *out,
15378 +      const void *matchinfo,
15379 +      int offset,
15380 +      const void *hdr,
15381 +      u_int16_t datalen,
15382 +      int *hotdrop)
15383 +{
15384 +       const struct ipt_u32 *data = matchinfo;
15385 +       int testind, i;
15386 +       unsigned char* origbase = (char*)skb->nh.iph;
15387 +       unsigned char* base = origbase;
15388 +       unsigned char* head = skb->head;
15389 +       unsigned char* end = skb->end;
15390 +       int nnums, nvals;
15391 +       u_int32_t pos, val;
15392 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
15393 +          cycles1 = get_cycles(); */
15394 +
15395 +       for (testind=0; testind < data->ntests; testind++) {
15396 +               base = origbase; /* reset for each test */
15397 +               pos = data->tests[testind].location[0].number;
15398 +               if (base+pos+3 > end || base+pos < head) 
15399 +                       return 0;
15400 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
15401 +                       (base[pos+2]<<8) + base[pos+3];
15402 +               nnums = data->tests[testind].nnums;
15403 +               for (i=1; i < nnums; i++) {
15404 +                       u_int32_t number = data->tests[testind].location[i].number;
15405 +                       switch (data->tests[testind].location[i].nextop) {
15406 +                       case IPT_U32_AND: 
15407 +                               val = val & number; 
15408 +                               break;
15409 +                       case IPT_U32_LEFTSH: 
15410 +                               val = val << number;
15411 +                               break;
15412 +                       case IPT_U32_RIGHTSH: 
15413 +                               val = val >> number; 
15414 +                               break;
15415 +                       case IPT_U32_AT:
15416 +                               base = base + val;
15417 +                               pos = number;
15418 +                               if (base+pos+3 > end || base+pos < head) 
15419 +                                       return 0;
15420 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
15421 +                                       (base[pos+2]<<8) + base[pos+3];
15422 +                               break;
15423 +                       }
15424 +               }
15425 +               nvals = data->tests[testind].nvalues;
15426 +               for (i=0; i < nvals; i++) {
15427 +                       if ((data->tests[testind].value[i].min <= val) &&
15428 +                           (val <= data->tests[testind].value[i].max)) {
15429 +                               break;
15430 +                       }
15431 +               }
15432 +               if (i >= data->tests[testind].nvalues) {
15433 +                       /* cycles2 = get_cycles(); 
15434 +                          printk("failed %d in %d cycles\n", testind, 
15435 +                                 cycles2-cycles1); */
15436 +                       return 0;
15437 +               }
15438 +       }
15439 +       /* cycles2 = get_cycles();
15440 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
15441 +       return 1;
15442 +}
15443 +
15444 +static int
15445 +checkentry(const char *tablename,
15446 +           const struct ipt_ip *ip,
15447 +           void *matchinfo,
15448 +           unsigned int matchsize,
15449 +           unsigned int hook_mask)
15450 +{
15451 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
15452 +               return 0;
15453 +       return 1;
15454 +}
15455 +
15456 +static struct ipt_match u32_match
15457 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
15458 +
15459 +static int __init init(void)
15460 +{
15461 +       return ipt_register_match(&u32_match);
15462 +}
15463 +
15464 +static void __exit fini(void)
15465 +{
15466 +       ipt_unregister_match(&u32_match);
15467 +}
15468 +
15469 +module_init(init);
15470 +module_exit(fini);
15471 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.7/net/ipv4/netfilter/ipt_unclean.c
15472 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_unclean.c    1970-01-01 01:00:00.000000000 +0100
15473 +++ linux-2.6.7/net/ipv4/netfilter/ipt_unclean.c        2004-06-25 12:28:34.799251744 +0200
15474 @@ -0,0 +1,604 @@
15475 +/* Kernel module to match suspect packets. */
15476 +#include <linux/module.h>
15477 +#include <linux/skbuff.h>
15478 +#include <linux/ip.h>
15479 +#include <linux/udp.h>
15480 +#include <linux/tcp.h>
15481 +#include <linux/icmp.h>
15482 +#include <net/checksum.h>
15483 +
15484 +#include <linux/netfilter_ipv4/ip_tables.h>
15485 +
15486 +#define limpk(format, args...)                                          \
15487 +do {                                                                    \
15488 +       if (net_ratelimit())                                             \
15489 +               printk("ipt_unclean: %s" format,                         \
15490 +                      embedded ? "(embedded packet) " : "" , ## args);  \
15491 +} while(0)
15492 +
15493 +enum icmp_error_status
15494 +{
15495 +       ICMP_MAY_BE_ERROR,
15496 +       ICMP_IS_ERROR,
15497 +       ICMP_NOT_ERROR
15498 +};
15499 +
15500 +struct icmp_info
15501 +{
15502 +       size_t min_len, max_len;
15503 +       enum icmp_error_status err;
15504 +       u_int8_t min_code, max_code;
15505 +};
15506 +
15507 +static int
15508 +check_ip(struct iphdr *iph, size_t length, int embedded);
15509 +
15510 +/* ICMP-specific checks. */
15511 +static int
15512 +check_icmp(const struct icmphdr *icmph,
15513 +          u_int16_t datalen,
15514 +          unsigned int offset,
15515 +          int more_frags,
15516 +          int embedded)
15517 +{
15518 +       static struct icmp_info info[]
15519 +               = { [ICMP_ECHOREPLY]
15520 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15521 +                   [ICMP_DEST_UNREACH]
15522 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
15523 +                   [ICMP_SOURCE_QUENCH]
15524 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
15525 +                   [ICMP_REDIRECT]
15526 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
15527 +                   [ICMP_ECHO]
15528 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0  },
15529 +                   /* Router advertisement. */
15530 +                   [9]
15531 +                   = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
15532 +                   /* Router solicitation. */
15533 +                   [10]
15534 +                   = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
15535 +                   [ICMP_TIME_EXCEEDED]
15536 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1  },
15537 +                   [ICMP_PARAMETERPROB]
15538 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
15539 +                   [ICMP_TIMESTAMP]
15540 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15541 +                   [ICMP_TIMESTAMPREPLY]
15542 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15543 +                   [ICMP_INFO_REQUEST]
15544 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15545 +                   [ICMP_INFO_REPLY]
15546 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15547 +                   [ICMP_ADDRESS]
15548 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
15549 +                   [ICMP_ADDRESSREPLY]
15550 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
15551 +
15552 +       /* Can't do anything if it's a fragment. */
15553 +       if (offset)
15554 +               return 1;
15555 +
15556 +       /* Must cover type and code. */
15557 +       if (datalen < 2) {
15558 +               limpk("ICMP len=%u too short\n", datalen);
15559 +               return 0;
15560 +       }
15561 +
15562 +       /* If not embedded. */
15563 +       if (!embedded) {
15564 +               /* Bad checksum?  Don't print, just ignore. */
15565 +               if (!more_frags
15566 +                   && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
15567 +                       return 0;
15568 +
15569 +               /* CHECK: Truncated ICMP (even if first fragment). */
15570 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15571 +                   && info[icmph->type].min_len != 0
15572 +                   && datalen < info[icmph->type].min_len) {
15573 +                       limpk("ICMP type %u len %u too short\n",
15574 +                             icmph->type, datalen);
15575 +                       return 0;
15576 +               }
15577 +
15578 +               /* CHECK: Check within known error ICMPs. */
15579 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15580 +                   && info[icmph->type].err == ICMP_IS_ERROR) {
15581 +                       /* CHECK: Embedded packet must be at least
15582 +                          length of iph + 8 bytes. */
15583 +                       struct iphdr *inner = (void *)icmph + 8;
15584 +
15585 +                       /* datalen > 8 since all ICMP_IS_ERROR types
15586 +                           have min length > 8 */
15587 +                       if (datalen - 8 < sizeof(struct iphdr)) {
15588 +                               limpk("ICMP error internal way too short\n");
15589 +                               return 0;
15590 +                       }
15591 +                       if (datalen - 8 < inner->ihl*4 + 8) {
15592 +                               limpk("ICMP error internal too short\n");
15593 +                               return 0;
15594 +                       }
15595 +                       if (!check_ip(inner, datalen - 8, 1))
15596 +                               return 0;
15597 +               }
15598 +       } else {
15599 +               /* CHECK: Can't embed ICMP unless known non-error. */
15600 +               if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
15601 +                   || info[icmph->type].err != ICMP_NOT_ERROR) {
15602 +                       limpk("ICMP type %u not embeddable\n",
15603 +                             icmph->type);
15604 +                       return 0;
15605 +               }
15606 +       }
15607 +
15608 +       /* CHECK: Invalid ICMP codes. */
15609 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15610 +           && (icmph->code < info[icmph->type].min_code
15611 +               || icmph->code > info[icmph->type].max_code)) {
15612 +               limpk("ICMP type=%u code=%u\n",
15613 +                     icmph->type, icmph->code);
15614 +               return 0;
15615 +       }
15616 +
15617 +       /* CHECK: Above maximum length. */
15618 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15619 +           && info[icmph->type].max_len != 0
15620 +           && datalen > info[icmph->type].max_len) {
15621 +               limpk("ICMP type=%u too long: %u bytes\n",
15622 +                     icmph->type, datalen);
15623 +               return 0;
15624 +       }
15625 +
15626 +       switch (icmph->type) {
15627 +       case ICMP_PARAMETERPROB: {
15628 +               /* CHECK: Problem param must be within error packet's
15629 +                * IP header. */
15630 +               struct iphdr *iph = (void *)icmph + 8;
15631 +               u_int32_t arg = ntohl(icmph->un.gateway);
15632 +
15633 +               if (icmph->code == 0) {
15634 +                       /* Code 0 means that upper 8 bits is pointer
15635 +                           to problem. */
15636 +                       if ((arg >> 24) >= iph->ihl*4) {
15637 +                               limpk("ICMP PARAMETERPROB ptr = %u\n",
15638 +                                     ntohl(icmph->un.gateway) >> 24);
15639 +                               return 0;
15640 +                       }
15641 +                       arg &= 0x00FFFFFF;
15642 +               }
15643 +
15644 +               /* CHECK: Rest must be zero. */
15645 +               if (arg) {
15646 +                       limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
15647 +                             arg);
15648 +                       return 0;
15649 +               }
15650 +               break;
15651 +       }
15652 +
15653 +       case ICMP_TIME_EXCEEDED:
15654 +       case ICMP_SOURCE_QUENCH:
15655 +               /* CHECK: Unused must be zero. */
15656 +               if (icmph->un.gateway != 0) {
15657 +                       limpk("ICMP type=%u unused = %u\n",
15658 +                             icmph->type, ntohl(icmph->un.gateway));
15659 +                       return 0;
15660 +               }
15661 +               break;
15662 +       }
15663 +
15664 +       return 1;
15665 +}
15666 +
15667 +/* UDP-specific checks. */
15668 +static int
15669 +check_udp(const struct iphdr *iph,
15670 +         const struct udphdr *udph,
15671 +         u_int16_t datalen,
15672 +         unsigned int offset,
15673 +         int more_frags,
15674 +         int embedded)
15675 +{
15676 +       /* Can't do anything if it's a fragment. */
15677 +       if (offset)
15678 +               return 1;
15679 +
15680 +       /* CHECK: Must cover UDP header. */
15681 +       if (datalen < sizeof(struct udphdr)) {
15682 +               limpk("UDP len=%u too short\n", datalen);
15683 +               return 0;
15684 +       }
15685 +
15686 +       /* Bad checksum?  Don't print, just say it's unclean. */
15687 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
15688 +       if (!more_frags && !embedded && udph->check
15689 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
15690 +                                csum_partial((char *)udph, datalen, 0)) != 0)
15691 +               return 0;
15692 +
15693 +       /* CHECK: Destination port can't be zero. */
15694 +       if (!udph->dest) {
15695 +               limpk("UDP zero destination port\n");
15696 +               return 0;
15697 +       }
15698 +
15699 +       if (!more_frags) {
15700 +               if (!embedded) {
15701 +                       /* CHECK: UDP length must match. */
15702 +                       if (ntohs(udph->len) != datalen) {
15703 +                               limpk("UDP len too short %u vs %u\n",
15704 +                                     ntohs(udph->len), datalen);
15705 +                               return 0;
15706 +                       }
15707 +               } else {
15708 +                       /* CHECK: UDP length be >= this truncated pkt. */
15709 +                       if (ntohs(udph->len) < datalen) {
15710 +                               limpk("UDP len too long %u vs %u\n",
15711 +                                     ntohs(udph->len), datalen);
15712 +                               return 0;
15713 +                       }
15714 +               }
15715 +       } else {
15716 +               /* CHECK: UDP length must be > this frag's length. */
15717 +               if (ntohs(udph->len) <= datalen) {
15718 +                       limpk("UDP fragment len too short %u vs %u\n",
15719 +                             ntohs(udph->len), datalen);
15720 +                       return 0;
15721 +               }
15722 +       }
15723 +
15724 +       return 1;
15725 +}
15726 +
15727 +#define        TH_FIN  0x01
15728 +#define        TH_SYN  0x02
15729 +#define        TH_RST  0x04
15730 +#define        TH_PUSH 0x08
15731 +#define        TH_ACK  0x10
15732 +#define        TH_URG  0x20
15733 +#define        TH_ECE  0x40
15734 +#define        TH_CWR  0x80
15735 +
15736 +/* table of valid flag combinations - ECE and CWR are always valid */
15737 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
15738 +{
15739 +       [TH_SYN]                        = 1,
15740 +       [TH_SYN|TH_ACK]                 = 1,
15741 +       [TH_RST]                        = 1,
15742 +       [TH_RST|TH_ACK]                 = 1,
15743 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
15744 +       [TH_FIN|TH_ACK]                 = 1,
15745 +       [TH_ACK]                        = 1,
15746 +       [TH_ACK|TH_PUSH]                = 1,
15747 +       [TH_ACK|TH_URG]                 = 1,
15748 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
15749 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
15750 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
15751 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
15752 +};
15753 +
15754 +/* TCP-specific checks. */
15755 +static int
15756 +check_tcp(const struct iphdr *iph,
15757 +         const struct tcphdr *tcph,
15758 +         u_int16_t datalen,
15759 +         unsigned int offset,
15760 +         int more_frags,
15761 +         int embedded)
15762 +{
15763 +       u_int8_t *opt = (u_int8_t *)tcph;
15764 +       u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
15765 +       u_int8_t tcpflags;
15766 +       int end_of_options = 0;
15767 +       size_t i;
15768 +
15769 +       /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
15770 +       /* In fact, this is caught below (offset < 516). */
15771 +
15772 +       /* Can't do anything if it's a fragment. */
15773 +       if (offset)
15774 +               return 1;
15775 +
15776 +       /* CHECK: Smaller than minimal TCP hdr. */
15777 +       if (datalen < sizeof(struct tcphdr)) {
15778 +               if (!embedded) {
15779 +                       limpk("Packet length %u < TCP header.\n", datalen);
15780 +                       return 0;
15781 +               }
15782 +               /* Must have ports available (datalen >= 8), from
15783 +                   check_icmp which set embedded = 1 */
15784 +               /* CHECK: TCP ports inside ICMP error */
15785 +               if (!tcph->source || !tcph->dest) {
15786 +                       limpk("Zero TCP ports %u/%u.\n",
15787 +                             htons(tcph->source), htons(tcph->dest));
15788 +                       return 0;
15789 +               }
15790 +               return 1;
15791 +       }
15792 +
15793 +       /* CHECK: Smaller than actual TCP hdr. */
15794 +       if (datalen < tcph->doff * 4) {
15795 +               if (!embedded) {
15796 +                       limpk("Packet length %u < actual TCP header.\n",
15797 +                             datalen);
15798 +                       return 0;
15799 +               } else
15800 +                       return 1;
15801 +       }
15802 +
15803 +       /* Bad checksum?  Don't print, just say it's unclean. */
15804 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
15805 +       if (!more_frags && !embedded
15806 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
15807 +                                csum_partial((char *)tcph, datalen, 0)) != 0)
15808 +               return 0;
15809 +
15810 +       /* CHECK: TCP ports non-zero */
15811 +       if (!tcph->source || !tcph->dest) {
15812 +               limpk("Zero TCP ports %u/%u.\n",
15813 +                     htons(tcph->source), htons(tcph->dest));
15814 +               return 0;
15815 +       }
15816 +
15817 +       /* CHECK: TCP reserved bits zero. */
15818 +       if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
15819 +               limpk("TCP reserved bits not zero\n");
15820 +               return 0;
15821 +       }
15822 +
15823 +       /* CHECK: TCP flags. */
15824 +       tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
15825 +       if (!tcp_valid_flags[tcpflags]) {
15826 +               limpk("TCP flags bad: %u\n", tcpflags);
15827 +               return 0;
15828 +       }
15829 +
15830 +       for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
15831 +               switch (opt[i]) {
15832 +               case 0:
15833 +                       end_of_options = 1;
15834 +                       i++;
15835 +                       break;
15836 +               case 1:
15837 +                       i++;
15838 +                       break;
15839 +               default:
15840 +                       /* CHECK: options after EOO. */
15841 +                       if (end_of_options) {
15842 +                               limpk("TCP option %u after end\n",
15843 +                                     opt[i]);
15844 +                               return 0;
15845 +                       }
15846 +                       /* CHECK: options at tail. */
15847 +                       else if (i+1 >= tcph->doff * 4) {
15848 +                               limpk("TCP option %u at tail\n",
15849 +                                     opt[i]);
15850 +                               return 0;
15851 +                       }
15852 +                       /* CHECK: zero-length options. */
15853 +                       else if (opt[i+1] == 0) {
15854 +                               limpk("TCP option %u 0 len\n",
15855 +                                     opt[i]);
15856 +                               return 0;
15857 +                       }
15858 +                       /* CHECK: oversize options. */
15859 +                       else if (&opt[i] + opt[i+1] > endhdr) {
15860 +                               limpk("TCP option %u at %Zu too long\n",
15861 +                                     (unsigned int) opt[i], i);
15862 +                               return 0;
15863 +                       }
15864 +                       /* Move to next option */
15865 +                       i += opt[i+1];
15866 +               }
15867 +       }
15868 +
15869 +       return 1;
15870 +}
15871 +
15872 +/* Returns 1 if ok */
15873 +/* Standard IP checks. */
15874 +static int
15875 +check_ip(struct iphdr *iph, size_t length, int embedded)
15876 +{
15877 +       u_int8_t *opt = (u_int8_t *)iph;
15878 +       u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
15879 +       int end_of_options = 0;
15880 +       void *protoh;
15881 +       size_t datalen;
15882 +       unsigned int i;
15883 +       unsigned int offset;
15884 +
15885 +       /* Should only happen for local outgoing raw-socket packets. */
15886 +       /* CHECK: length >= ip header. */
15887 +       if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
15888 +               limpk("Packet length %Zu < IP header.\n", length);
15889 +               return 0;
15890 +       }
15891 +
15892 +       offset = ntohs(iph->frag_off) & IP_OFFSET;
15893 +       protoh = (void *)iph + iph->ihl * 4;
15894 +       datalen = length - iph->ihl * 4;
15895 +
15896 +       /* CHECK: Embedded fragment. */
15897 +       if (embedded && offset) {
15898 +               limpk("Embedded fragment.\n");
15899 +               return 0;
15900 +       }
15901 +
15902 +       for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
15903 +               switch (opt[i]) {
15904 +               case 0:
15905 +                       end_of_options = 1;
15906 +                       i++;
15907 +                       break;
15908 +               case 1:
15909 +                       i++;
15910 +                       break;
15911 +               default:
15912 +                       /* CHECK: options after EOO. */
15913 +                       if (end_of_options) {
15914 +                               limpk("IP option %u after end\n",
15915 +                                     opt[i]);
15916 +                               return 0;
15917 +                       }
15918 +                       /* CHECK: options at tail. */
15919 +                       else if (i+1 >= iph->ihl * 4) {
15920 +                               limpk("IP option %u at tail\n",
15921 +                                     opt[i]);
15922 +                               return 0;
15923 +                       }
15924 +                       /* CHECK: zero-length or one-length options. */
15925 +                       else if (opt[i+1] < 2) {
15926 +                               limpk("IP option %u %u len\n",
15927 +                                     opt[i], opt[i+1]);
15928 +                               return 0;
15929 +                       }
15930 +                       /* CHECK: oversize options. */
15931 +                       else if (&opt[i] + opt[i+1] > endhdr) {
15932 +                               limpk("IP option %u at %u too long\n",
15933 +                                     opt[i], i);
15934 +                               return 0;
15935 +                       }
15936 +                       /* Move to next option */
15937 +                       i += opt[i+1];
15938 +               }
15939 +       }
15940 +
15941 +       /* Fragment checks. */
15942 +
15943 +       /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
15944 +       if ((ntohs(iph->frag_off) & IP_MF)
15945 +           && (ntohs(iph->tot_len) % 8) != 0) {
15946 +               limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
15947 +               return 0;
15948 +       }
15949 +
15950 +       /* CHECK: Oversize fragment a-la Ping of Death. */
15951 +       if (offset * 8 + datalen > 65535) {
15952 +               limpk("Oversize fragment to %u.\n", offset * 8);
15953 +               return 0;
15954 +       }
15955 +
15956 +       /* CHECK: DF set and offset or MF set. */
15957 +       if ((ntohs(iph->frag_off) & IP_DF)
15958 +           && (offset || (ntohs(iph->frag_off) & IP_MF))) {
15959 +               limpk("DF set and offset=%u, MF=%u.\n",
15960 +                     offset, ntohs(iph->frag_off) & IP_MF);
15961 +               return 0;
15962 +       }
15963 +
15964 +       /* CHECK: Zero-sized fragments. */
15965 +       if ((offset || (ntohs(iph->frag_off) & IP_MF))
15966 +           && datalen == 0) {
15967 +               limpk("Zero size fragment offset=%u\n", offset);
15968 +               return 0;
15969 +       }
15970 +
15971 +       /* Note: we can have even middle fragments smaller than this:
15972 +          consider a large packet passing through a 600MTU then
15973 +          576MTU link: this gives a fragment of 24 data bytes.  But
15974 +          everyone packs fragments largest first, hence a fragment
15975 +          can't START before 576 - MAX_IP_HEADER_LEN. */
15976 +
15977 +       /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
15978 +          down to 128 (576 taken from RFC 791: All hosts must be
15979 +          prepared to accept datagrams of up to 576 octets).  Use 128
15980 +          here. */
15981 +#define MIN_LIKELY_MTU 128
15982 +       /* CHECK: Min size of first frag = 128. */
15983 +       if ((ntohs(iph->frag_off) & IP_MF)
15984 +           && offset == 0
15985 +           && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
15986 +               limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
15987 +                     MIN_LIKELY_MTU);
15988 +               return 0;
15989 +       }
15990 +
15991 +       /* CHECK: Min offset of frag = 128 - IP hdr len. */
15992 +       if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
15993 +               limpk("Fragment starts at %u < %u\n", offset * 8,
15994 +                     MIN_LIKELY_MTU - iph->ihl * 4);
15995 +               return 0;
15996 +       }
15997 +
15998 +       /* CHECK: Protocol specification non-zero. */
15999 +       if (iph->protocol == 0) {
16000 +               limpk("Zero protocol\n");
16001 +               return 0;
16002 +       }
16003 +
16004 +       /* CHECK: Do not use what is unused.
16005 +        * First bit of fragmentation flags should be unused.
16006 +        * May be used by OS fingerprinting tools.
16007 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
16008 +        */
16009 +       if (ntohs(iph->frag_off)>>15) {
16010 +               limpk("IP unused bit set\n");
16011 +               return 0;
16012 +       }
16013 +
16014 +       /* Per-protocol checks. */
16015 +       switch (iph->protocol) {
16016 +       case IPPROTO_ICMP:
16017 +               return check_icmp(protoh, datalen, offset,
16018 +                                 (ntohs(iph->frag_off) & IP_MF),
16019 +                                 embedded);
16020 +
16021 +       case IPPROTO_UDP:
16022 +               return check_udp(iph, protoh, datalen, offset,
16023 +                                (ntohs(iph->frag_off) & IP_MF),
16024 +                                embedded);
16025 +
16026 +       case IPPROTO_TCP:
16027 +               return check_tcp(iph, protoh, datalen, offset,
16028 +                                (ntohs(iph->frag_off) & IP_MF),
16029 +                                embedded);
16030 +       default:
16031 +               /* Ignorance is bliss. */
16032 +               return 1;
16033 +       }
16034 +}
16035 +
16036 +static int
16037 +match(const struct sk_buff *skb,
16038 +      const struct net_device *in,
16039 +      const struct net_device *out,
16040 +      const void *matchinfo,
16041 +      int offset,
16042 +      const void *hdr,
16043 +      u_int16_t datalen,
16044 +      int *hotdrop)
16045 +{
16046 +       return !check_ip(skb->nh.iph, skb->len, 0);
16047 +}
16048 +
16049 +/* Called when user tries to insert an entry of this type. */
16050 +static int
16051 +checkentry(const char *tablename,
16052 +          const struct ipt_ip *ip,
16053 +          void *matchinfo,
16054 +          unsigned int matchsize,
16055 +          unsigned int hook_mask)
16056 +{
16057 +       if (matchsize != IPT_ALIGN(0))
16058 +               return 0;
16059 +
16060 +       return 1;
16061 +}
16062 +
16063 +static struct ipt_match unclean_match
16064 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
16065 +
16066 +static int __init init(void)
16067 +{
16068 +       return ipt_register_match(&unclean_match);
16069 +}
16070 +
16071 +static void __exit fini(void)
16072 +{
16073 +       ipt_unregister_match(&unclean_match);
16074 +}
16075 +
16076 +module_init(init);
16077 +module_exit(fini);
16078 +MODULE_LICENSE("GPL");
16079 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/string.2.6.patch linux-2.6.7/net/ipv4/netfilter/string.2.6.patch
16080 --- linux-2.6.7.org/net/ipv4/netfilter/string.2.6.patch 1970-01-01 01:00:00.000000000 +0100
16081 +++ linux-2.6.7/net/ipv4/netfilter/string.2.6.patch     2004-06-25 12:28:38.580676880 +0200
16082 @@ -0,0 +1,152 @@
16083 +--- ipt_string.c.old    Mon Mar 29 06:00:23 2004
16084 ++++ ipt_string.c    Mon Mar 29 06:01:04 2004
16085 +@@ -3,6 +3,8 @@
16086 +  * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
16087 +  * 
16088 +  * ChangeLog
16089 ++ *     24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
16090 ++ *             Initial 2.6 port
16091 +  *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
16092 +  *             Fixed SMP re-entrancy problem using per-cpu data areas
16093 +  *             for the skip/shift tables.
16094 +@@ -18,6 +20,7 @@
16095 +  */
16096
16097 + #include <linux/smp.h>
16098 ++#include <linux/percpu.h>
16099 + #include <linux/module.h>
16100 + #include <linux/skbuff.h>
16101 + #include <linux/file.h>
16102 +@@ -29,12 +32,13 @@
16103 + MODULE_LICENSE("GPL");
16104
16105 + struct string_per_cpu {
16106 +-       int *skip;
16107 +-       int *shift;
16108 +-       int *len;
16109 ++       int skip[BM_MAX_HLEN];
16110 ++       int shift[BM_MAX_HLEN];
16111 ++       int len[BM_MAX_HLEN];
16112 + };
16113
16114 +-struct string_per_cpu *bm_string_data=NULL;
16115 ++static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
16116 ++
16117
16118 + /* Boyer Moore Sublinear string search - VERY FAST */
16119 + char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
16120 +@@ -45,14 +49,14 @@
16121 +        int *skip, *shift, *len;
16122 +        
16123 +        /* use data suitable for this CPU */
16124 +-       shift=bm_string_data[smp_processor_id()].shift;
16125 +-       skip=bm_string_data[smp_processor_id()].skip;
16126 +-       len=bm_string_data[smp_processor_id()].len;
16127 ++       shift=__get_cpu_var(bm_string_data).shift;
16128 ++       skip=__get_cpu_var(bm_string_data).skip;
16129 ++       len=__get_cpu_var(bm_string_data).len;
16130 +        
16131 +        /* Setup skip/shift tables */
16132 +        M1 = right_end = needle_len-1;
16133 +        for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
16134 +-       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
16135 ++       for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
16136
16137 +        for (i = 1; i < needle_len; i++) {   
16138 +                for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
16139 +@@ -77,7 +81,7 @@
16140 +                        return haystack+(right_end - M1);
16141 +                }
16142 +                
16143 +-               sk = skip[haystack[right_end - i]];  
16144 ++               sk = skip[(int)haystack[right_end - i]];  
16145 +                sh = shift[i];
16146 +                right_end = max(right_end - i + sk, right_end + sh);  
16147 +        }
16148 +@@ -100,15 +104,12 @@
16149 +        return NULL;
16150 + }
16151
16152 +-
16153 + static int
16154 + match(const struct sk_buff *skb,
16155 +       const struct net_device *in,
16156 +       const struct net_device *out,
16157 +       const void *matchinfo,
16158 +       int offset,
16159 +-      const void *hdr,
16160 +-      u_int16_t datalen,
16161 +       int *hotdrop)
16162 + {
16163 +        const struct ipt_string_info *info = matchinfo;
16164 +@@ -158,61 +159,25 @@
16165 +        return 1;
16166 + }
16167
16168 +-void string_freeup_data(void)
16169 +-{
16170 +-       int c;
16171 +-       
16172 +-       if ( bm_string_data ) {
16173 +-               for(c=0; c<smp_num_cpus; c++) {
16174 +-                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
16175 +-                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
16176 +-                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
16177 +-               }
16178 +-               kfree(bm_string_data);
16179 +-       }
16180 +-}
16181 ++static struct ipt_match string_match = {
16182 ++    .name = "string",
16183 ++    .match = &match,
16184 ++    .checkentry = &checkentry,
16185 ++    .me = THIS_MODULE
16186 ++};
16187
16188 +-static struct ipt_match string_match
16189 +-= { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
16190
16191 + static int __init init(void)
16192 + {
16193 +-       int c;
16194 +-       size_t tlen;
16195 +-       size_t alen;
16196 +-
16197 +-       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
16198 +-       alen=sizeof(int)*BM_MAX_HLEN;
16199 +-       
16200 +-       /* allocate array of structures */
16201 +-       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
16202 +-               return 0;
16203 +-       }
16204 +-       
16205 +-       memset(bm_string_data, 0, tlen);
16206 +-       
16207 +-       /* allocate our skip/shift tables */
16208 +-       for(c=0; c<smp_num_cpus; c++) {
16209 +-               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
16210 +-                       goto alloc_fail;
16211 +-               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
16212 +-                       goto alloc_fail;
16213 +-               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
16214 +-                       goto alloc_fail;
16215 +-       }
16216 +-       
16217 +        return ipt_register_match(&string_match);
16218 +-
16219 +-alloc_fail:
16220 +-       string_freeup_data();
16221 +-       return 0;
16222 + }
16223
16224 + static void __exit fini(void)
16225 + {
16226 +        ipt_unregister_match(&string_match);
16227 +-       string_freeup_data();
16228 + }
16229
16230 + module_init(init);
16231 + module_exit(fini);
16232 ++
16233 ++
16234 +
16235 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/raw.c linux-2.6.7/net/ipv4/raw.c
16236 --- linux-2.6.7.org/net/ipv4/raw.c      2004-06-16 07:19:36.000000000 +0200
16237 +++ linux-2.6.7/net/ipv4/raw.c  2004-06-25 12:21:38.705507608 +0200
16238 @@ -249,6 +249,7 @@
16239                 kfree_skb(skb);
16240                 return NET_RX_DROP;
16241         }
16242 +       nf_reset(skb);
16243  
16244         skb_push(skb, skb->data - skb->nh.raw);
16245  
16246 @@ -307,7 +308,7 @@
16247         }
16248  
16249         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
16250 -                     dst_output);
16251 +                     ip_dst_output);
16252         if (err > 0)
16253                 err = inet->recverr ? net_xmit_errno(err) : 0;
16254         if (err)
16255 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/tcp_ipv4.c linux-2.6.7/net/ipv4/tcp_ipv4.c
16256 --- linux-2.6.7.org/net/ipv4/tcp_ipv4.c 2004-06-25 10:47:46.000000000 +0200
16257 +++ linux-2.6.7/net/ipv4/tcp_ipv4.c     2004-06-25 12:23:16.012714664 +0200
16258 @@ -1785,6 +1785,7 @@
16259  
16260         if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
16261                 goto discard_and_relse;
16262 +       nf_reset(skb);
16263  
16264         if (sk_filter(sk, skb, 0))
16265                 goto discard_and_relse;
16266 @@ -2640,6 +2641,7 @@
16267  EXPORT_SYMBOL(tcp_v4_connect);
16268  EXPORT_SYMBOL(tcp_v4_do_rcv);
16269  EXPORT_SYMBOL(tcp_v4_lookup_listener);
16270 +EXPORT_SYMBOL(tcp_v4_lookup);
16271  EXPORT_SYMBOL(tcp_v4_rebuild_header);
16272  EXPORT_SYMBOL(tcp_v4_remember_stamp);
16273  EXPORT_SYMBOL(tcp_v4_send_check);
16274 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/udp.c linux-2.6.7/net/ipv4/udp.c
16275 --- linux-2.6.7.org/net/ipv4/udp.c      2004-06-16 07:18:59.000000000 +0200
16276 +++ linux-2.6.7/net/ipv4/udp.c  2004-06-25 12:23:16.018713752 +0200
16277 @@ -1045,6 +1045,7 @@
16278                 kfree_skb(skb);
16279                 return -1;
16280         }
16281 +       nf_reset(skb);
16282  
16283         if (up->encap_type) {
16284                 /*
16285 @@ -1210,6 +1211,7 @@
16286  
16287         if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
16288                 goto drop;
16289 +       nf_reset(skb);
16290  
16291         /* No socket. Drop packet silently, if checksum is wrong */
16292         if (udp_checksum_complete(skb))
16293 @@ -1558,6 +1560,7 @@
16294  EXPORT_SYMBOL(udp_port_rover);
16295  EXPORT_SYMBOL(udp_prot);
16296  EXPORT_SYMBOL(udp_sendmsg);
16297 +EXPORT_SYMBOL(udp_v4_lookup);
16298  
16299  #ifdef CONFIG_PROC_FS
16300  EXPORT_SYMBOL(udp_proc_register);
16301 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/xfrm4_tunnel.c linux-2.6.7/net/ipv4/xfrm4_tunnel.c
16302 --- linux-2.6.7.org/net/ipv4/xfrm4_tunnel.c     2004-06-25 10:47:46.000000000 +0200
16303 +++ linux-2.6.7/net/ipv4/xfrm4_tunnel.c 2004-06-25 12:21:37.109750200 +0200
16304 @@ -77,6 +77,7 @@
16305                 err = -EHOSTUNREACH;
16306                 goto error_nolock;
16307         }
16308 +       IPCB(*pskb)->flags |= IPSKB_XFRM_TRANSFORMED;
16309         return NET_XMIT_BYPASS;
16310  
16311  error_nolock:
16312 @@ -171,6 +172,7 @@
16313         .handler        =       ipip_rcv,
16314         .err_handler    =       ipip_err,
16315         .no_policy      =       1,
16316 +       .xfrm_prot      =       1,
16317  };
16318  
16319  static int __init ipip_init(void)
16320 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/K linux-2.6.7/net/ipv6/netfilter/K
16321 --- linux-2.6.7.org/net/ipv6/netfilter/K        1970-01-01 01:00:00.000000000 +0100
16322 +++ linux-2.6.7/net/ipv6/netfilter/K    2004-05-07 18:20:57.000000000 +0200
16323 @@ -0,0 +1,9 @@
16324 +config IP6_NF_MATCH_POLICY
16325 +       tristate "IPsec policy match support"
16326 +       depends on IP6_NF_IPTABLES && XFRM
16327 +       help
16328 +         Policy matching allows you to match packets based on the
16329 +         IPsec policy that was used during decapsulation/will
16330 +         be used during encapsulation.
16331 +
16332 +         To compile it as a module, choose M here.  If unsure, say N.
16333 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Kconfig linux-2.6.7/net/ipv6/netfilter/Kconfig
16334 --- linux-2.6.7.org/net/ipv6/netfilter/Kconfig  2004-06-16 07:19:52.000000000 +0200
16335 +++ linux-2.6.7/net/ipv6/netfilter/Kconfig      2004-06-25 12:27:59.398633456 +0200
16336 @@ -230,5 +230,107 @@
16337           <file:Documentation/modules.txt>.  If unsure, say `N'.
16338           help
16339  
16340 +config IP6_NF_TARGET_HL
16341 +       tristate  'HL target support'
16342 +       depends on IP6_NF_MANGLE
16343 +       help
16344 +         This option adds a `HL' target, which allows you to modify the value of
16345 +         IPv6 Hop Limit field.
16346 +       
16347 +         If you want to compile it as a module, say M here and read
16348 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16349 +
16350 +config IP6_NF_TARGET_REJECT
16351 +       tristate  'REJECT target support'
16352 +       depends on IP6_NF_FILTER
16353 +       help
16354 +         The REJECT target allows a filtering rule to specify that an ICMPv6
16355 +         error should be issued in response to an incoming packet, rather
16356 +         than silently being dropped.
16357 +       
16358 +         If you want to compile it as a module, say M here and read
16359 +         Documentation/modules.txt.  If unsure, say `N'.
16360 +
16361 +config IP6_NF_MATCH_POLICY
16362 +       tristate "IPsec policy match support"
16363 +       depends on IP6_NF_IPTABLES && XFRM
16364 +       help
16365 +         Policy matching allows you to match packets based on the
16366 +         IPsec policy that was used during decapsulation/will
16367 +         be used during encapsulation.
16368 +
16369 +         To compile it as a module, choose M here.  If unsure, say N.
16370 +
16371 +config IP6_NF_MATCH_FUZZY
16372 +       tristate  'Fuzzy match support'
16373 +       depends on IP6_NF_FILTER
16374 +       help
16375 +         This option adds a `fuzzy' match, which allows you to match
16376 +         packets according to a fuzzy logic based law.
16377 +       
16378 +         If you want to compile it as a module, say M here and read
16379 +         Documentation/modules.txt.  If unsure, say `N'.
16380 +
16381 +config IP6_NF_MATCH_NTH
16382 +       tristate  'Nth match support'
16383 +       depends on IP6_NF_IPTABLES
16384 +       help
16385 +         This option adds a `Nth' match, which allow you to make
16386 +         rules that match every Nth packet.  By default there are 
16387 +         16 different counters.
16388 +       
16389 +         [options]
16390 +          --every     Nth              Match every Nth packet
16391 +         [--counter]  num              Use counter 0-15 (default:0)
16392 +         [--start]    num              Initialize the counter at the number 'num'
16393 +                                       instead of 0. Must be between 0 and Nth-1
16394 +         [--packet]   num              Match on 'num' packet. Must be between 0
16395 +                                       and Nth-1.
16396 +       
16397 +                                       If --packet is used for a counter than
16398 +                                       there must be Nth number of --packet
16399 +                                       rules, covering all values between 0 and
16400 +                                       Nth-1 inclusively.
16401 +        
16402 +         If you want to compile it as a module, say M here and read
16403 +         Documentation/modules.txt.  If unsure, say `N'.
16404 +
16405 +config IP6_NF_MATCH_RANDOM
16406 +       tristate  'Random match support'
16407 +       depends on IP6_NF_IPTABLES
16408 +       help
16409 +         This option adds a `random' match,
16410 +         which allow you to match packets randomly
16411 +         following a given probability.
16412 +        
16413 +         If you want to compile it as a module, say M here and read
16414 +         Documentation/modules.txt.  If unsure, say `N'.
16415 +
16416 +config IP6_NF_TARGET_ROUTE
16417 +       tristate '    ROUTE target support'
16418 +       depends on IP6_NF_MANGLE
16419 +       help
16420 +         This option adds a `ROUTE' target, which enables you to setup unusual
16421 +         routes. The ROUTE target is also able to change the incoming interface
16422 +         of a packet.
16423 +       
16424 +         The target can be or not a final target. It has to be used inside the 
16425 +         mangle table.
16426 +         
16427 +         Not working as a module.
16428 +
16429 +config IP6_NF_TARGET_TRACE
16430 +       tristate  'TRACE target support'
16431 +       depends on IP6_NF_RAW
16432 +       help
16433 +         The TRACE target allows packets to be traced as those
16434 +         matches any subsequent rule in any table/rule. The matched
16435 +         rule and the packet is logged with the prefix
16436 +       
16437 +         TRACE: tablename/chainname/rulenum  
16438 +       
16439 +         If you want to compile it as a module, say M here and read
16440 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16441 +
16442  endmenu
16443  
16444 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Kconfig~ linux-2.6.7/net/ipv6/netfilter/Kconfig~
16445 --- linux-2.6.7.org/net/ipv6/netfilter/Kconfig~ 1970-01-01 01:00:00.000000000 +0100
16446 +++ linux-2.6.7/net/ipv6/netfilter/Kconfig~     2004-06-25 12:21:30.376773768 +0200
16447 @@ -0,0 +1,326 @@
16448 +#
16449 +# IP netfilter configuration
16450 +#
16451 +
16452 +menu "IPv6: Netfilter Configuration"
16453 +       depends on INET && IPV6 && NETFILTER
16454 +
16455 +#tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
16456 +#if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
16457 +#  dep_tristate '  FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK
16458 +#fi
16459 +config IP6_NF_QUEUE
16460 +       tristate "Userspace queueing via NETLINK"
16461 +       ---help---
16462 +
16463 +         This option adds a queue handler to the kernel for IPv6
16464 +         packets which lets us to receive the filtered packets
16465 +         with QUEUE target using libiptc as we can do with
16466 +         the IPv4 now.
16467 +
16468 +         (C) Fernando Anton 2001
16469 +         IPv64 Project - Work based in IPv64 draft by Arturo Azcorra.
16470 +         Universidad Carlos III de Madrid
16471 +         Universidad Politecnica de Alcala de Henares
16472 +         email: <fanton@it.uc3m.es>.
16473 +
16474 +         To compile it as a module, choose M here.  If unsure, say N.
16475 +
16476 +config IP6_NF_IPTABLES
16477 +       tristate "IP6 tables support (required for filtering/masq/NAT)"
16478 +       help
16479 +         ip6tables is a general, extensible packet identification framework.
16480 +         Currently only the packet filtering and packet mangling subsystem
16481 +         for IPv6 use this, but connection tracking is going to follow.
16482 +         Say 'Y' or 'M' here if you want to use either of those.
16483 +
16484 +         To compile it as a module, choose M here.  If unsure, say N.
16485 +
16486 +# The simple matches.
16487 +config IP6_NF_MATCH_LIMIT
16488 +       tristate "limit match support"
16489 +       depends on IP6_NF_IPTABLES
16490 +       help
16491 +         limit matching allows you to control the rate at which a rule can be
16492 +         matched: mainly useful in combination with the LOG target ("LOG
16493 +         target support", below) and to avoid some Denial of Service attacks.
16494 +
16495 +         To compile it as a module, choose M here.  If unsure, say N.
16496 +
16497 +config IP6_NF_MATCH_MAC
16498 +       tristate "MAC address match support"
16499 +       depends on IP6_NF_IPTABLES
16500 +       help
16501 +         mac matching allows you to match packets based on the source
16502 +         Ethernet address of the packet.
16503 +
16504 +         To compile it as a module, choose M here.  If unsure, say N.
16505 +
16506 +config IP6_NF_MATCH_RT
16507 +       tristate "Routing header match support"
16508 +       depends on IP6_NF_IPTABLES
16509 +       help
16510 +         rt matching allows you to match packets based on the routing
16511 +         header of the packet.
16512 +
16513 +         To compile it as a module, choose M here.  If unsure, say N.
16514 +
16515 +config IP6_NF_MATCH_OPTS
16516 +       tristate "Hop-by-hop and Dst opts header match support"
16517 +       depends on IP6_NF_IPTABLES
16518 +       help
16519 +         This allows one to match packets based on the hop-by-hop
16520 +         and destination options headers of a packet.
16521 +
16522 +         To compile it as a module, choose M here.  If unsure, say N.
16523 +
16524 +config IP6_NF_MATCH_FRAG
16525 +       tristate "Fragmentation header match support"
16526 +       depends on IP6_NF_IPTABLES
16527 +       help
16528 +         frag matching allows you to match packets based on the fragmentation
16529 +         header of the packet.
16530 +
16531 +         To compile it as a module, choose M here.  If unsure, say N.
16532 +
16533 +config IP6_NF_MATCH_HL
16534 +       tristate "HL match support"
16535 +       depends on IP6_NF_IPTABLES
16536 +       help
16537 +         HL matching allows you to match packets based on the hop
16538 +         limit of the packet.
16539 +
16540 +         To compile it as a module, choose M here.  If unsure, say N.
16541 +
16542 +config IP6_NF_MATCH_MULTIPORT
16543 +       tristate "Multiple port match support"
16544 +       depends on IP6_NF_IPTABLES
16545 +       help
16546 +         Multiport matching allows you to match TCP or UDP packets based on
16547 +         a series of source or destination ports: normally a rule can only
16548 +         match a single range of ports.
16549 +
16550 +         To compile it as a module, choose M here.  If unsure, say N.
16551 +
16552 +config IP6_NF_MATCH_OWNER
16553 +       tristate "Owner match support"
16554 +       depends on IP6_NF_IPTABLES
16555 +       help
16556 +         Packet owner matching allows you to match locally-generated packets
16557 +         based on who created them: the user, group, process or session.
16558 +
16559 +         To compile it as a module, choose M here.  If unsure, say N.
16560 +
16561 +#  dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
16562 +config IP6_NF_MATCH_MARK
16563 +       tristate "netfilter MARK match support"
16564 +       depends on IP6_NF_IPTABLES
16565 +       help
16566 +         Netfilter mark matching allows you to match packets based on the
16567 +         `nfmark' value in the packet.  This can be set by the MARK target
16568 +         (see below).
16569 +
16570 +         To compile it as a module, choose M here.  If unsure, say N.
16571 +
16572 +config IP6_NF_MATCH_IPV6HEADER
16573 +       tristate "IPv6 Extension Headers Match"
16574 +       depends on IP6_NF_IPTABLES
16575 +       help
16576 +         This module allows one to match packets based upon
16577 +         the ipv6 extension headers.
16578 +
16579 +         To compile it as a module, choose M here.  If unsure, say N.
16580 +
16581 +config IP6_NF_MATCH_AHESP
16582 +       tristate "AH/ESP match support"
16583 +       depends on IP6_NF_IPTABLES
16584 +       help
16585 +         This module allows one to match AH and ESP packets.
16586 +
16587 +         To compile it as a module, choose M here.  If unsure, say N.
16588 +
16589 +config IP6_NF_MATCH_LENGTH
16590 +       tristate "Packet Length match support"
16591 +       depends on IP6_NF_IPTABLES
16592 +       help
16593 +         This option allows you to match the length of a packet against a
16594 +         specific value or range of values.
16595 +
16596 +         To compile it as a module, choose M here.  If unsure, say N.
16597 +
16598 +config IP6_NF_MATCH_EUI64
16599 +       tristate "EUI64 address check"
16600 +       depends on IP6_NF_IPTABLES
16601 +       help
16602 +         This module performs checking on the IPv6 source address
16603 +         Compares the last 64 bits with the EUI64 (delivered
16604 +         from the MAC address) address
16605 +
16606 +         To compile it as a module, choose M here.  If unsure, say N.
16607 +
16608 +#  dep_tristate '  Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
16609 +#  dep_tristate '  TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES
16610 +#  if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
16611 +#    dep_tristate '  Connection state match support' CONFIG_IP6_NF_MATCH_STATE $CONFIG_IP6_NF_CONNTRACK $CONFIG_IP6_NF_IPTABLES 
16612 +#  fi
16613 +#  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
16614 +#    dep_tristate '  Unclean match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_UNCLEAN $CONFIG_IP6_NF_IPTABLES
16615 +#    dep_tristate '  Owner match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_OWNER $CONFIG_IP6_NF_IPTABLES
16616 +#  fi
16617 +# The targets
16618 +config IP6_NF_FILTER
16619 +       tristate "Packet filtering"
16620 +       depends on IP6_NF_IPTABLES
16621 +       help
16622 +         Packet filtering defines a table `filter', which has a series of
16623 +         rules for simple packet filtering at local input, forwarding and
16624 +         local output.  See the man page for iptables(8).
16625 +
16626 +         To compile it as a module, choose M here.  If unsure, say N.
16627 +
16628 +config IP6_NF_TARGET_LOG
16629 +       tristate "LOG target support"
16630 +       depends on IP6_NF_FILTER
16631 +       help
16632 +         This option adds a `LOG' target, which allows you to create rules in
16633 +         any iptables table which records the packet header to the syslog.
16634 +
16635 +         To compile it as a module, choose M here.  If unsure, say N.
16636 +
16637 +#  if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
16638 +#    dep_tristate '    REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
16639 +#    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
16640 +#      dep_tristate '    MIRROR target support (EXPERIMENTAL)' CONFIG_IP6_NF_TARGET_MIRROR $CONFIG_IP6_NF_FILTER
16641 +#    fi
16642 +#  fi
16643 +config IP6_NF_MANGLE
16644 +       tristate "Packet mangling"
16645 +       depends on IP6_NF_IPTABLES
16646 +       help
16647 +         This option adds a `mangle' table to iptables: see the man page for
16648 +         iptables(8).  This table is used for various packet alterations
16649 +         which can effect how the packet is routed.
16650 +
16651 +         To compile it as a module, choose M here.  If unsure, say N.
16652 +
16653 +#    dep_tristate '    TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
16654 +config IP6_NF_TARGET_MARK
16655 +       tristate "MARK target support"
16656 +       depends on IP6_NF_MANGLE
16657 +       help
16658 +         This option adds a `MARK' target, which allows you to create rules
16659 +         in the `mangle' table which alter the netfilter mark (nfmark) field
16660 +         associated with the packet packet prior to routing. This can change
16661 +         the routing method (see `Use netfilter MARK value as routing
16662 +         key') and can also be used by other subsystems to change their
16663 +         behavior.
16664 +
16665 +         To compile it as a module, choose M here.  If unsure, say N.
16666 +
16667 +#dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
16668 +config IP6_NF_RAW
16669 +       tristate  'raw table support (required for TRACE)'
16670 +       depends on IP6_NF_IPTABLES
16671 +       help
16672 +         This option adds a `raw' table to ip6tables. This table is the very
16673 +         first in the netfilter framework and hooks in at the PREROUTING
16674 +         and OUTPUT chains.
16675 +       
16676 +         If you want to compile it as a module, say M here and read
16677 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16678 +         help
16679 +
16680 +config IP6_NF_TARGET_HL
16681 +       tristate  'HL target support'
16682 +       depends on IP6_NF_MANGLE
16683 +       help
16684 +         This option adds a `HL' target, which allows you to modify the value of
16685 +         IPv6 Hop Limit field.
16686 +       
16687 +         If you want to compile it as a module, say M here and read
16688 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16689 +
16690 +config IP6_NF_TARGET_REJECT
16691 +       tristate  'REJECT target support'
16692 +       depends on IP6_NF_FILTER
16693 +       help
16694 +         The REJECT target allows a filtering rule to specify that an ICMPv6
16695 +         error should be issued in response to an incoming packet, rather
16696 +         than silently being dropped.
16697 +       
16698 +         If you want to compile it as a module, say M here and read
16699 +         Documentation/modules.txt.  If unsure, say `N'.
16700 +
16701 +config IP6_NF_MATCH_FUZZY
16702 +       tristate  'Fuzzy match support'
16703 +       depends on IP6_NF_FILTER
16704 +       help
16705 +         This option adds a `fuzzy' match, which allows you to match
16706 +         packets according to a fuzzy logic based law.
16707 +       
16708 +         If you want to compile it as a module, say M here and read
16709 +         Documentation/modules.txt.  If unsure, say `N'.
16710 +
16711 +config IP6_NF_MATCH_NTH
16712 +       tristate  'Nth match support'
16713 +       depends on IP6_NF_IPTABLES
16714 +       help
16715 +         This option adds a `Nth' match, which allow you to make
16716 +         rules that match every Nth packet.  By default there are 
16717 +         16 different counters.
16718 +       
16719 +         [options]
16720 +          --every     Nth              Match every Nth packet
16721 +         [--counter]  num              Use counter 0-15 (default:0)
16722 +         [--start]    num              Initialize the counter at the number 'num'
16723 +                                       instead of 0. Must be between 0 and Nth-1
16724 +         [--packet]   num              Match on 'num' packet. Must be between 0
16725 +                                       and Nth-1.
16726 +       
16727 +                                       If --packet is used for a counter than
16728 +                                       there must be Nth number of --packet
16729 +                                       rules, covering all values between 0 and
16730 +                                       Nth-1 inclusively.
16731 +        
16732 +         If you want to compile it as a module, say M here and read
16733 +         Documentation/modules.txt.  If unsure, say `N'.
16734 +
16735 +config IP6_NF_MATCH_RANDOM
16736 +       tristate  'Random match support'
16737 +       depends on IP6_NF_IPTABLES
16738 +       help
16739 +         This option adds a `random' match,
16740 +         which allow you to match packets randomly
16741 +         following a given probability.
16742 +        
16743 +         If you want to compile it as a module, say M here and read
16744 +         Documentation/modules.txt.  If unsure, say `N'.
16745 +
16746 +config IP6_NF_TARGET_ROUTE
16747 +       tristate '    ROUTE target support'
16748 +       depends on IP6_NF_MANGLE
16749 +       help
16750 +         This option adds a `ROUTE' target, which enables you to setup unusual
16751 +         routes. The ROUTE target is also able to change the incoming interface
16752 +         of a packet.
16753 +       
16754 +         The target can be or not a final target. It has to be used inside the 
16755 +         mangle table.
16756 +         
16757 +         Not working as a module.
16758 +
16759 +config IP6_NF_TARGET_TRACE
16760 +       tristate  'TRACE target support'
16761 +       depends on IP6_NF_RAW
16762 +       help
16763 +         The TRACE target allows packets to be traced as those
16764 +         matches any subsequent rule in any table/rule. The matched
16765 +         rule and the packet is logged with the prefix
16766 +       
16767 +         TRACE: tablename/chainname/rulenum  
16768 +       
16769 +         If you want to compile it as a module, say M here and read
16770 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16771 +
16772 +endmenu
16773 +
16774 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Makefile linux-2.6.7/net/ipv6/netfilter/Makefile
16775 --- linux-2.6.7.org/net/ipv6/netfilter/Makefile 2004-06-16 07:19:36.000000000 +0200
16776 +++ linux-2.6.7/net/ipv6/netfilter/Makefile     2004-06-25 12:27:27.387499888 +0200
16777 @@ -8,18 +8,28 @@
16778  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
16779  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
16780  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
16781 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
16782  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
16783  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
16784  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
16785  obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
16786  obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
16787 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
16788  obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
16789  obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
16790  obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
16791  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16792  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
16793  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
16794 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
16795 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
16796  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
16797  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
16798 +
16799 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
16800 +
16801 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
16802 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
16803  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
16804 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
16805  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
16806 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c
16807 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c        1970-01-01 01:00:00.000000000 +0100
16808 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c    2004-06-25 12:21:05.615538048 +0200
16809 @@ -0,0 +1,105 @@
16810 +/* 
16811 + * Hop Limit modification target for ip6tables
16812 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
16813 + * Based on HW's TTL module
16814 + *
16815 + * This software is distributed under the terms of GNU GPL
16816 + */
16817 +
16818 +#include <linux/module.h>
16819 +#include <linux/skbuff.h>
16820 +#include <linux/ip.h>
16821 +
16822 +#include <linux/netfilter_ipv6/ip6_tables.h>
16823 +#include <linux/netfilter_ipv6/ip6t_HL.h>
16824 +
16825 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
16826 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
16827 +MODULE_LICENSE("GPL");
16828 +
16829 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
16830 +               const struct net_device *in, const struct net_device *out,
16831 +               const void *targinfo, void *userinfo)
16832 +{
16833 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
16834 +       const struct ip6t_HL_info *info = targinfo;
16835 +       u_int16_t diffs[2];
16836 +       int new_hl;
16837 +                        
16838 +       switch (info->mode) {
16839 +               case IP6T_HL_SET:
16840 +                       new_hl = info->hop_limit;
16841 +                       break;
16842 +               case IP6T_HL_INC:
16843 +                       new_hl = ip6h->hop_limit + info->hop_limit;
16844 +                       if (new_hl > 255)
16845 +                               new_hl = 255;
16846 +                       break;
16847 +               case IP6T_HL_DEC:
16848 +                       new_hl = ip6h->hop_limit + info->hop_limit;
16849 +                       if (new_hl < 0)
16850 +                               new_hl = 0;
16851 +                       break;
16852 +               default:
16853 +                       new_hl = ip6h->hop_limit;
16854 +                       break;
16855 +       }
16856 +
16857 +       if (new_hl != ip6h->hop_limit) {
16858 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
16859 +               ip6h->hop_limit = new_hl;
16860 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
16861 +       }
16862 +
16863 +       return IP6T_CONTINUE;
16864 +}
16865 +
16866 +static int ip6t_hl_checkentry(const char *tablename,
16867 +               const struct ip6t_entry *e,
16868 +               void *targinfo,
16869 +               unsigned int targinfosize,
16870 +               unsigned int hook_mask)
16871 +{
16872 +       struct ip6t_HL_info *info = targinfo;
16873 +
16874 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
16875 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
16876 +                               targinfosize,
16877 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
16878 +               return 0;       
16879 +       }       
16880 +
16881 +       if (strcmp(tablename, "mangle")) {
16882 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
16883 +               return 0;
16884 +       }
16885 +
16886 +       if (info->mode > IP6T_HL_MAXMODE) {
16887 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
16888 +                       info->mode);
16889 +               return 0;
16890 +       }
16891 +
16892 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
16893 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
16894 +               return 0;
16895 +       }
16896 +       
16897 +       return 1;
16898 +}
16899 +
16900 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
16901 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
16902 +
16903 +static int __init init(void)
16904 +{
16905 +       return ip6t_register_target(&ip6t_HL);
16906 +}
16907 +
16908 +static void __exit fini(void)
16909 +{
16910 +       ip6t_unregister_target(&ip6t_HL);
16911 +}
16912 +
16913 +module_init(init);
16914 +module_exit(fini);
16915 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c
16916 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c    1970-01-01 01:00:00.000000000 +0100
16917 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c        2004-06-25 12:21:07.477255024 +0200
16918 @@ -0,0 +1,458 @@
16919 +/*
16920 + * IP6 tables REJECT target module
16921 + * Linux INET6 implementation
16922 + *
16923 + * Copyright (C)2003 USAGI/WIDE Project
16924 + *
16925 + * Authors:
16926 + *     Yasuyuki Kozakai        <yasuyuki.kozakai@toshiba.co.jp>
16927 + *
16928 + * Based on net/ipv4/netfilter/ipt_REJECT.c
16929 + *
16930 + * This program is free software; you can redistribute it and/or
16931 + * modify it under the terms of the GNU General Public License
16932 + * as published by the Free Software Foundation; either version
16933 + * 2 of the License, or (at your option) any later version.
16934 + */
16935 +
16936 +#include <linux/config.h>
16937 +#include <linux/module.h>
16938 +#include <linux/skbuff.h>
16939 +#include <linux/icmpv6.h>
16940 +#include <net/ipv6.h>
16941 +#include <net/tcp.h>
16942 +#include <net/icmp.h>
16943 +#include <net/ip6_fib.h>
16944 +#include <net/ip6_route.h>
16945 +#include <net/flow.h>
16946 +#include <linux/netfilter_ipv6/ip6_tables.h>
16947 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
16948 +
16949 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
16950 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
16951 +MODULE_LICENSE("GPL");
16952 +
16953 +#if 0
16954 +#define DEBUGP printk
16955 +#else
16956 +#define DEBUGP(format, args...)
16957 +#endif
16958 +
16959 +#if 0
16960 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
16961 +{
16962 +       void (*attach)(struct sk_buff *, struct nf_ct_info *);
16963 +       if (nfct && (attach = ip6_ct_attach) != NULL) {
16964 +               mb();
16965 +               attach(new_skb, nfct);
16966 +       }
16967 +}
16968 +#endif
16969 +
16970 +static int maybe_reroute(struct sk_buff *skb)
16971 +{
16972 +       if (skb->nfcache & NFC_ALTERED){
16973 +               if (ip6_route_me_harder(skb) != 0){
16974 +                       kfree_skb(skb);
16975 +                       return -EINVAL;
16976 +               }
16977 +       }
16978 +
16979 +       return dst_output(skb);
16980 +}
16981 +
16982 +/* Send RST reply */
16983 +static void send_reset(struct sk_buff *oldskb)
16984 +{
16985 +       struct sk_buff *nskb;
16986 +       struct tcphdr otcph, *tcph;
16987 +       unsigned int otcplen, tcphoff, hh_len;
16988 +       int needs_ack;
16989 +       struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
16990 +       struct dst_entry *dst = NULL;
16991 +       u8 proto;
16992 +       struct flowi fl;
16993 +       proto = oip6h->nexthdr;
16994 +       int err;
16995 +
16996 +       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
16997 +           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
16998 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
16999 +               return;
17000 +       }
17001 +
17002 +       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
17003 +                                  &proto, oldskb->len - ((u8*)(oip6h+1)
17004 +                                                         - oldskb->data));
17005 +
17006 +       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
17007 +               DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
17008 +               return;
17009 +       }
17010 +
17011 +       otcplen = oldskb->len - tcphoff;
17012 +
17013 +       /* IP header checks: fragment, too short. */
17014 +       if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
17015 +               DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
17016 +                       proto, otcplen);
17017 +               return;
17018 +       }
17019 +
17020 +       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
17021 +               if (net_ratelimit())
17022 +                       printk("ip6t_REJECT: Can't copy tcp header\n");
17023 +               return;
17024 +       }
17025 +
17026 +       /* No RST for RST. */
17027 +       if (otcph.rst) {
17028 +               DEBUGP("ip6t_REJECT: RST is set\n");
17029 +               return;
17030 +       }
17031 +
17032 +       /* Check checksum. */
17033 +       if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
17034 +                           skb_checksum(oldskb, tcphoff, otcplen, 0))) {
17035 +               DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
17036 +               return;
17037 +       }
17038 +
17039 +       memset(&fl, 0, sizeof(fl));
17040 +       fl.proto = IPPROTO_TCP;
17041 +       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
17042 +       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
17043 +       fl.fl_ip_sport = otcph.dest;
17044 +       fl.fl_ip_dport = otcph.source;
17045 +       err = ip6_dst_lookup(NULL, &dst, &fl);
17046 +       if (err) {
17047 +               if (net_ratelimit())
17048 +                       printk("ip6t_REJECT: can't find dst. err = %d\n", err);
17049 +               return;
17050 +       }
17051 +
17052 +       hh_len = (dst->dev->hard_header_len + 15)&~15;
17053 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
17054 +                        + sizeof(struct tcphdr) + dst->trailer_len,
17055 +                        GFP_ATOMIC);
17056 +
17057 +       if (!nskb) {
17058 +               if (net_ratelimit())
17059 +                       printk("ip6t_REJECT: Can't alloc skb\n");
17060 +               dst_release(dst);
17061 +               return;
17062 +       }
17063 +
17064 +       nskb->dst = dst;
17065 +       dst_hold(dst);
17066 +
17067 +       skb_reserve(nskb, hh_len + dst->header_len);
17068 +
17069 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17070 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
17071 +       ip6h->version = 6;
17072 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17073 +       ip6h->nexthdr = IPPROTO_TCP;
17074 +       ip6h->payload_len = htons(sizeof(struct tcphdr));
17075 +       ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
17076 +       ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
17077 +
17078 +       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
17079 +       /* Truncate to length (no data) */
17080 +       tcph->doff = sizeof(struct tcphdr)/4;
17081 +       tcph->source = otcph.dest;
17082 +       tcph->dest = otcph.source;
17083 +
17084 +       if (otcph.ack) {
17085 +               needs_ack = 0;
17086 +               tcph->seq = otcph.ack_seq;
17087 +               tcph->ack_seq = 0;
17088 +       } else {
17089 +               needs_ack = 1;
17090 +               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
17091 +                                     + otcplen - (otcph.doff<<2));
17092 +               tcph->seq = 0;
17093 +       }
17094 +
17095 +       /* Reset flags */
17096 +       ((u_int8_t *)tcph)[13] = 0;
17097 +       tcph->rst = 1;
17098 +       tcph->ack = needs_ack;
17099 +       tcph->window = 0;
17100 +       tcph->urg_ptr = 0;
17101 +       tcph->check = 0;
17102 +
17103 +       /* Adjust TCP checksum */
17104 +       tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
17105 +                                     &nskb->nh.ipv6h->daddr,
17106 +                                     sizeof(struct tcphdr), IPPROTO_TCP,
17107 +                                     csum_partial((char *)tcph,
17108 +                                                  sizeof(struct tcphdr), 0));
17109 +
17110 +#if 0
17111 +       connection_attach(nskb, oldskb->nfct);
17112 +#endif
17113 +
17114 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17115 +               maybe_reroute);
17116 +
17117 +       dst_release(dst);
17118 +}
17119 +
17120 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
17121 +{
17122 +       struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
17123 +       struct icmp6hdr *icmp6h;
17124 +       struct dst_entry *dst = NULL;
17125 +       struct rt6_info *rt;
17126 +       int tmo;
17127 +       __u32 csum;
17128 +       unsigned int len, datalen, hh_len;
17129 +       int saddr_type, daddr_type;
17130 +       unsigned int ptr, ip6off;
17131 +       u8 proto;
17132 +       struct flowi fl;
17133 +       struct sk_buff *nskb;
17134 +       char *data;
17135 +
17136 +       saddr_type = ipv6_addr_type(&hdr->saddr);
17137 +       daddr_type = ipv6_addr_type(&hdr->daddr);
17138 +
17139 +       if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
17140 +           (!(daddr_type & IPV6_ADDR_UNICAST))) {
17141 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
17142 +               return;
17143 +       }
17144 +
17145 +       ip6off = skb_in->nh.raw - skb_in->data;
17146 +       proto = hdr->nexthdr;
17147 +       ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
17148 +                              skb_in->len - ip6off);
17149 +
17150 +       if ((ptr < 0) || (ptr > skb_in->len)) {
17151 +               ptr = ip6off + sizeof(struct ipv6hdr);
17152 +               proto = hdr->nexthdr;
17153 +       } else if (proto == IPPROTO_ICMPV6) {
17154 +                u8 type;
17155 +
17156 +                if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
17157 +                                                     icmp6_type), &type, 1)) {
17158 +                       DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
17159 +                       return;
17160 +               }
17161 +
17162 +               if (!(type & ICMPV6_INFOMSG_MASK)) {
17163 +                       DEBUGP("ip6t_REJECT: no reply to icmp error\n");
17164 +                       return;
17165 +               }
17166 +        } else if (proto == IPPROTO_UDP) {
17167 +               int plen = skb_in->len - (ptr - ip6off);
17168 +               uint16_t check;
17169 +
17170 +               if (plen < sizeof(struct udphdr)) {
17171 +                       DEBUGP("ip6t_REJECT: too short\n");
17172 +                       return;
17173 +               }
17174 +
17175 +               if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
17176 +                                 &check, 2)) {
17177 +                       if (net_ratelimit())
17178 +                               printk("ip6t_REJECT: can't get copy from skb");
17179 +                       return;
17180 +               }
17181 +
17182 +               if (check &&
17183 +                   csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
17184 +                                   IPPROTO_UDP,
17185 +                                   skb_checksum(skb_in, ptr, plen, 0))) {
17186 +                       DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
17187 +                       return;
17188 +               }
17189 +       }
17190 +
17191 +       memset(&fl, 0, sizeof(fl));
17192 +       fl.proto = IPPROTO_ICMPV6;
17193 +       ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
17194 +       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
17195 +       fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
17196 +       fl.fl_icmp_code = code;
17197 +
17198 +       if (ip6_dst_lookup(NULL, &dst, &fl)) {
17199 +               return;
17200 +       }
17201 +
17202 +       rt = (struct rt6_info *)dst;
17203 +       tmo = 1*HZ;
17204 +
17205 +       if (rt->rt6i_dst.plen < 128)
17206 +               tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
17207 +
17208 +       if (!xrlim_allow(dst, tmo)) {
17209 +               if (net_ratelimit())
17210 +                       printk("ip6t_REJECT: rate limitted\n");
17211 +               goto dst_release_out;
17212 +       }
17213 +
17214 +       len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
17215 +
17216 +       if (len > dst_pmtu(dst))
17217 +               len = dst_pmtu(dst);
17218 +       if (len > IPV6_MIN_MTU)
17219 +               len = IPV6_MIN_MTU;
17220 +
17221 +       datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
17222 +       hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
17223 +
17224 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
17225 +                        GFP_ATOMIC);
17226 +
17227 +       if (!nskb) {
17228 +               if (net_ratelimit())
17229 +                       printk("ip6t_REJECT: can't alloc skb\n");
17230 +               goto dst_release_out;
17231 +       }
17232 +
17233 +       nskb->priority = 0;
17234 +       nskb->dst = dst;
17235 +       dst_hold(dst);
17236 +
17237 +       skb_reserve(nskb, hh_len + dst->header_len);
17238 +
17239 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17240 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
17241 +       ip6h->version = 6;
17242 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17243 +       ip6h->nexthdr = IPPROTO_ICMPV6;
17244 +       ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
17245 +       ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
17246 +       ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
17247 +
17248 +       icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
17249 +       icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
17250 +       icmp6h->icmp6_code = code;
17251 +       icmp6h->icmp6_cksum = 0;
17252 +
17253 +       data = skb_put(nskb, datalen);
17254 +
17255 +       csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
17256 +       csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
17257 +       icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
17258 +                                            datalen + sizeof(struct icmp6hdr),
17259 +                                            IPPROTO_ICMPV6, csum);
17260 +
17261 +#if 0
17262 +       connection_attach(nskb, skb_in->nfct);
17263 +#endif
17264 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17265 +               maybe_reroute);
17266 +
17267 +dst_release_out:
17268 +       dst_release(dst);
17269 +}
17270 +
17271 +static unsigned int reject6_target(struct sk_buff **pskb,
17272 +                          unsigned int hooknum,
17273 +                          const struct net_device *in,
17274 +                          const struct net_device *out,
17275 +                          const void *targinfo,
17276 +                          void *userinfo)
17277 +{
17278 +       const struct ip6t_reject_info *reject = targinfo;
17279 +
17280 +       DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
17281 +       /* WARNING: This code causes reentry within ip6tables.
17282 +          This means that the ip6tables jump stack is now crap.  We
17283 +          must return an absolute verdict. --RR */
17284 +       switch (reject->with) {
17285 +       case IP6T_ICMP6_NO_ROUTE:
17286 +               send_unreach(*pskb, ICMPV6_NOROUTE);
17287 +               break;
17288 +       case IP6T_ICMP6_ADM_PROHIBITED:
17289 +               send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
17290 +               break;
17291 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
17292 +               send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
17293 +               break;
17294 +       case IP6T_ICMP6_ADDR_UNREACH:
17295 +               send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
17296 +               break;
17297 +       case IP6T_ICMP6_PORT_UNREACH:
17298 +               send_unreach(*pskb, ICMPV6_PORT_UNREACH);
17299 +               break;
17300 +       case IP6T_ICMP6_ECHOREPLY:
17301 +               /* Do nothing */
17302 +               break;
17303 +       case IP6T_TCP_RESET:
17304 +               send_reset(*pskb);
17305 +               break;
17306 +       default:
17307 +               if (net_ratelimit())
17308 +                       printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
17309 +               break;
17310 +       }
17311 +
17312 +       return NF_DROP;
17313 +}
17314 +
17315 +static int check(const char *tablename,
17316 +                const struct ip6t_entry *e,
17317 +                void *targinfo,
17318 +                unsigned int targinfosize,
17319 +                unsigned int hook_mask)
17320 +{
17321 +       const struct ip6t_reject_info *rejinfo = targinfo;
17322 +
17323 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
17324 +               DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
17325 +               return 0;
17326 +       }
17327 +
17328 +       /* Only allow these for packet filtering. */
17329 +       if (strcmp(tablename, "filter") != 0) {
17330 +               DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
17331 +               return 0;
17332 +       }
17333 +
17334 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
17335 +                          | (1 << NF_IP6_FORWARD)
17336 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
17337 +               DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
17338 +               return 0;
17339 +       }
17340 +
17341 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
17342 +               printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
17343 +               return 0;
17344 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
17345 +               /* Must specify that it's a TCP packet */
17346 +               if (e->ipv6.proto != IPPROTO_TCP
17347 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
17348 +                       DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
17349 +                       return 0;
17350 +               }
17351 +       }
17352 +
17353 +       return 1;
17354 +}
17355 +
17356 +static struct ip6t_target ip6t_reject_reg = {
17357 +       .name           = "REJECT",
17358 +       .target         = reject6_target,
17359 +       .checkentry     = check,
17360 +       .me             = THIS_MODULE
17361 +};
17362 +
17363 +static int __init init(void)
17364 +{
17365 +       if (ip6t_register_target(&ip6t_reject_reg))
17366 +               return -EINVAL;
17367 +       return 0;
17368 +}
17369 +
17370 +static void __exit fini(void)
17371 +{
17372 +       ip6t_unregister_target(&ip6t_reject_reg);
17373 +}
17374 +
17375 +module_init(init);
17376 +module_exit(fini);
17377 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.7/net/ipv6/netfilter/ip6t_ROUTE.c
17378 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_ROUTE.c     1970-01-01 01:00:00.000000000 +0100
17379 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_ROUTE.c 2004-06-25 12:21:28.216102240 +0200
17380 @@ -0,0 +1,289 @@
17381 +/*
17382 + * This implements the ROUTE v6 target, which enables you to setup unusual
17383 + * routes not supported by the standard kernel routing table.
17384 + *
17385 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
17386 + *
17387 + * v 1.0 2003/08/05
17388 + *
17389 + * This software is distributed under GNU GPL v2, 1991
17390 + */
17391 +
17392 +#include <linux/module.h>
17393 +#include <linux/skbuff.h>
17394 +#include <linux/ipv6.h>
17395 +#include <linux/netfilter_ipv6/ip6_tables.h>
17396 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
17397 +#include <linux/netdevice.h>
17398 +#include <net/ipv6.h>
17399 +#include <net/ndisc.h>
17400 +#include <net/ip6_route.h>
17401 +#include <linux/icmpv6.h>
17402 +
17403 +#if 1
17404 +#define DEBUGP printk
17405 +#else
17406 +#define DEBUGP(format, args...)
17407 +#endif
17408 +
17409 +#define NIP6(addr) \
17410 +       ntohs((addr).s6_addr16[0]), \
17411 +       ntohs((addr).s6_addr16[1]), \
17412 +       ntohs((addr).s6_addr16[2]), \
17413 +       ntohs((addr).s6_addr16[3]), \
17414 +       ntohs((addr).s6_addr16[4]), \
17415 +       ntohs((addr).s6_addr16[5]), \
17416 +       ntohs((addr).s6_addr16[6]), \
17417 +       ntohs((addr).s6_addr16[7])
17418 +
17419 +/* Route the packet according to the routing keys specified in
17420 + * route_info. Keys are :
17421 + *  - ifindex : 
17422 + *      0 if no oif preferred, 
17423 + *      otherwise set to the index of the desired oif
17424 + *  - route_info->gw :
17425 + *      0 if no gateway specified,
17426 + *      otherwise set to the next host to which the pkt must be routed
17427 + * If success, skb->dev is the output device to which the packet must 
17428 + * be sent and skb->dst is not NULL
17429 + *
17430 + * RETURN:  1 if the packet was succesfully routed to the 
17431 + *            destination desired
17432 + *          0 if the kernel routing table could not route the packet
17433 + *            according to the keys specified
17434 + */
17435 +static int 
17436 +route6(struct sk_buff *skb,
17437 +       unsigned int ifindex,
17438 +       const struct ip6t_route_target_info *route_info)
17439 +{
17440 +       struct rt6_info *rt = NULL;
17441 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17442 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17443 +
17444 +       DEBUGP("ip6t_ROUTE: called with: ");
17445 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
17446 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
17447 +       DEBUGP("OUT=%s\n", route_info->oif);
17448 +       
17449 +       if (ipv6_addr_any(gw))
17450 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
17451 +       else
17452 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
17453 +
17454 +       if (!rt)
17455 +               goto no_route;
17456 +
17457 +       DEBUGP("ip6t_ROUTE: routing gives: ");
17458 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
17459 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
17460 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
17461 +
17462 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
17463 +               goto wrong_route;
17464 +       
17465 +       if (!rt->rt6i_nexthop) {
17466 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
17467 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
17468 +       }
17469 +
17470 +       /* Drop old route. */
17471 +       dst_release(skb->dst);
17472 +       skb->dst = &rt->u.dst;
17473 +       skb->dev = rt->rt6i_dev;
17474 +       return 1;
17475 +
17476 + wrong_route:
17477 +       dst_release(&rt->u.dst);
17478 + no_route:
17479 +       if (!net_ratelimit())
17480 +               return 0;
17481 +
17482 +       printk("ip6t_ROUTE: no explicit route found ");
17483 +       if (ifindex)
17484 +               printk("via interface %s ", route_info->oif);
17485 +       if (!ipv6_addr_any(gw))
17486 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
17487 +       printk("\n");
17488 +       return 0;
17489 +}
17490 +
17491 +
17492 +/* Stolen from ip6_output_finish
17493 + * PRE : skb->dev is set to the device we are leaving by
17494 + *       skb->dst is not NULL
17495 + * POST: the packet is sent with the link layer header pushed
17496 + *       the packet is destroyed
17497 + */
17498 +static void ip_direct_send(struct sk_buff *skb)
17499 +{
17500 +       struct dst_entry *dst = skb->dst;
17501 +       struct hh_cache *hh = dst->hh;
17502 +
17503 +       if (hh) {
17504 +               read_lock_bh(&hh->hh_lock);
17505 +               memcpy(skb->data - 16, hh->hh_data, 16);
17506 +               read_unlock_bh(&hh->hh_lock);
17507 +               skb_push(skb, hh->hh_len);
17508 +               hh->hh_output(skb);
17509 +       } else if (dst->neighbour)
17510 +               dst->neighbour->output(skb);
17511 +       else {
17512 +               if (net_ratelimit())
17513 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
17514 +               kfree_skb(skb);
17515 +       }
17516 +}
17517 +
17518 +
17519 +static unsigned int 
17520 +route6_oif(const struct ip6t_route_target_info *route_info,
17521 +          struct sk_buff *skb) 
17522 +{
17523 +       unsigned int ifindex = 0;
17524 +       struct net_device *dev_out = NULL;
17525 +
17526 +       /* The user set the interface name to use.
17527 +        * Getting the current interface index.
17528 +        */
17529 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
17530 +               ifindex = dev_out->ifindex;
17531 +       } else {
17532 +               /* Unknown interface name : packet dropped */
17533 +               if (net_ratelimit()) 
17534 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
17535 +
17536 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17537 +                       return IP6T_CONTINUE;
17538 +               else
17539 +                       return NF_DROP;
17540 +       }
17541 +
17542 +       /* Trying the standard way of routing packets */
17543 +       if (route6(skb, ifindex, route_info)) {
17544 +               dev_put(dev_out);
17545 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17546 +                       return IP6T_CONTINUE;
17547 +               
17548 +               ip_direct_send(skb);
17549 +               return NF_STOLEN;
17550 +       } else 
17551 +               return NF_DROP;
17552 +}
17553 +
17554 +
17555 +static unsigned int 
17556 +route6_gw(const struct ip6t_route_target_info *route_info,
17557 +         struct sk_buff *skb) 
17558 +{
17559 +       if (route6(skb, 0, route_info)) {
17560 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17561 +                       return IP6T_CONTINUE;
17562 +
17563 +               ip_direct_send(skb);
17564 +               return NF_STOLEN;
17565 +       } else
17566 +               return NF_DROP;
17567 +}
17568 +
17569 +
17570 +static unsigned int 
17571 +ip6t_route_target(struct sk_buff **pskb,
17572 +                 unsigned int hooknum,
17573 +                 const struct net_device *in,
17574 +                 const struct net_device *out,
17575 +                 const void *targinfo,
17576 +                 void *userinfo)
17577 +{
17578 +       const struct ip6t_route_target_info *route_info = targinfo;
17579 +       struct sk_buff *skb = *pskb;
17580 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17581 +
17582 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
17583 +               goto do_it;
17584 +
17585 +       /* If we are at PREROUTING or INPUT hook
17586 +        * the TTL isn't decreased by the IP stack
17587 +        */
17588 +       if (hooknum == NF_IP6_PRE_ROUTING ||
17589 +           hooknum == NF_IP6_LOCAL_IN) {
17590 +
17591 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17592 +
17593 +               if (ipv6h->hop_limit <= 1) {
17594 +                       /* Force OUTPUT device used as source address */
17595 +                       skb->dev = skb->dst->dev;
17596 +
17597 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
17598 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
17599 +
17600 +                       return NF_DROP;
17601 +               }
17602 +
17603 +               ipv6h->hop_limit--;
17604 +       }
17605 +
17606 +
17607 + do_it:
17608 +       if (route_info->oif[0]) 
17609 +               return route6_oif(route_info, *pskb);
17610 +       
17611 +       if (!ipv6_addr_any(gw))
17612 +               return route6_gw(route_info, *pskb);
17613 +
17614 +       if (net_ratelimit()) 
17615 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
17616 +
17617 +       return IP6T_CONTINUE;
17618 +}
17619 +
17620 +
17621 +static int 
17622 +ip6t_route_checkentry(const char *tablename,
17623 +                     const struct ip6t_entry *e,
17624 +                     void *targinfo,
17625 +                     unsigned int targinfosize,
17626 +                     unsigned int hook_mask)
17627 +{
17628 +       if (strcmp(tablename, "mangle") != 0) {
17629 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
17630 +               return 0;
17631 +       }
17632 +
17633 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
17634 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
17635 +                      targinfosize,
17636 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
17637 +               return 0;
17638 +       }
17639 +
17640 +       return 1;
17641 +}
17642 +
17643 +
17644 +static struct ip6t_target ip6t_route_reg = {
17645 +       .name       = "ROUTE",
17646 +       .target     = ip6t_route_target,
17647 +       .checkentry = ip6t_route_checkentry,
17648 +       .me         = THIS_MODULE
17649 +};
17650 +
17651 +
17652 +static int __init init(void)
17653 +{
17654 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
17655 +       if (ip6t_register_target(&ip6t_route_reg))
17656 +               return -EINVAL;
17657 +
17658 +       return 0;
17659 +}
17660 +
17661 +
17662 +static void __exit fini(void)
17663 +{
17664 +       ip6t_unregister_target(&ip6t_route_reg);
17665 +}
17666 +
17667 +module_init(init);
17668 +module_exit(fini);
17669 +MODULE_LICENSE("GPL");
17670 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.7/net/ipv6/netfilter/ip6t_TRACE.c
17671 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_TRACE.c     1970-01-01 01:00:00.000000000 +0100
17672 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_TRACE.c 2004-06-25 12:21:30.343778784 +0200
17673 @@ -0,0 +1,65 @@
17674 +/* This is a module which is used for setting
17675 + * the NFC_TRACE flag in the nfcache field of an skb. 
17676 + */
17677 +#include <linux/module.h>
17678 +#include <linux/skbuff.h>
17679 +
17680 +#include <linux/netfilter_ipv6/ip6_tables.h>
17681 +
17682 +MODULE_LICENSE("GPL");
17683 +
17684 +static unsigned int
17685 +target(struct sk_buff **pskb,
17686 +       unsigned int hooknum,
17687 +       const struct net_device *in,
17688 +       const struct net_device *out,
17689 +       const void *targinfo,
17690 +       void *userinfo)
17691 +{
17692 +       (*pskb)->nfcache |= NFC_TRACE;
17693 +       return IP6T_CONTINUE;
17694 +}
17695 +
17696 +static int 
17697 +checkentry(const char *tablename,
17698 +                  const struct ip6t_entry *e,
17699 +           void *targinfo,
17700 +           unsigned int targinfosize,
17701 +           unsigned int hook_mask)
17702 +{
17703 +       if (targinfosize != 0) {
17704 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17705 +                      targinfosize);
17706 +               return 0;
17707 +       }
17708 +
17709 +       if (strcmp(tablename, "raw") != 0) {
17710 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17711 +               return 0;
17712 +       }
17713 +
17714 +       return 1;
17715 +}
17716 +
17717 +static struct ip6t_target ip6t_trace_reg = { 
17718 +       .name = "TRACE",
17719 +       .target = target, 
17720 +       .checkentry = checkentry, 
17721 +       .me = THIS_MODULE
17722 +};
17723 +
17724 +static int __init init(void)
17725 +{
17726 +       if (ip6t_register_target(&ip6t_trace_reg))
17727 +               return -EINVAL;
17728 +
17729 +       return 0;
17730 +}
17731 +
17732 +static void __exit fini(void)
17733 +{
17734 +       ip6t_unregister_target(&ip6t_trace_reg);
17735 +}
17736 +
17737 +module_init(init);
17738 +module_exit(fini);
17739 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c
17740 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c     1970-01-01 01:00:00.000000000 +0100
17741 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c 2004-06-25 12:21:08.963029152 +0200
17742 @@ -0,0 +1,189 @@
17743 +/*
17744 + * This module implements a simple TSK FLC
17745 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
17746 + * to limit , in an adaptive and flexible way , the packet rate crossing
17747 + * a given stream . It serves as an initial and very simple (but effective)
17748 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
17749 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
17750 + * into our code in a precise , adaptive and efficient manner.
17751 + *  The goal is very similar to that of "limit" match , but using techniques of
17752 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
17753 + * avoiding over and undershoots - and stuff like that .
17754 + *
17755 + *
17756 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
17757 + * 2002-08-17  : Changed to eliminate floating point operations .
17758 + * 2002-08-23  : Coding style changes .
17759 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
17760 + */
17761 +
17762 +#include <linux/module.h>
17763 +#include <linux/skbuff.h>
17764 +#include <linux/ipv6.h>
17765 +#include <linux/random.h>
17766 +#include <net/tcp.h>
17767 +#include <linux/spinlock.h>
17768 +#include <linux/netfilter_ipv6/ip6_tables.h>
17769 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
17770 +
17771 +/*
17772 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
17773 + Expressed in percentage
17774 +*/
17775 +
17776 +#define PAR_LOW                1/100
17777 +#define PAR_HIGH       1
17778 +
17779 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
17780 +
17781 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
17782 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
17783 +MODULE_LICENSE("GPL");
17784 +
17785 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17786 +{
17787 +       if (tx >= maxi) return 100;
17788 +
17789 +       if (tx <= mini) return 0;
17790 +
17791 +       return ((100 * (tx-mini)) / (maxi-mini));
17792 +}
17793 +
17794 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17795 +{
17796 +       if (tx <= mini) return 100;
17797 +
17798 +       if (tx >= maxi) return 0;
17799 +
17800 +       return ((100 * (maxi - tx)) / (maxi - mini));
17801 +
17802 +}
17803 +
17804 +static int
17805 +ip6t_fuzzy_match(const struct sk_buff *pskb,
17806 +              const struct net_device *in,
17807 +              const struct net_device *out,
17808 +              const void *matchinfo,
17809 +              int offset,
17810 +              const void *hdr,
17811 +              u_int16_t datalen,
17812 +              int *hotdrop)
17813 +{
17814 +       /* From userspace */
17815 +
17816 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
17817 +
17818 +       u_int8_t random_number;
17819 +       unsigned long amount;
17820 +       u_int8_t howhigh, howlow;
17821 +
17822 +
17823 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
17824 +
17825 +       info->bytes_total += pskb->len;
17826 +       info->packets_total++;
17827 +
17828 +       info->present_time = jiffies;
17829 +
17830 +       if (info->present_time >= info->previous_time)
17831 +               amount = info->present_time - info->previous_time;
17832 +       else {
17833 +               /* There was a transition : I choose to re-sample
17834 +                  and keep the old acceptance rate...
17835 +               */
17836 +
17837 +               amount = 0;
17838 +               info->previous_time = info->present_time;
17839 +               info->bytes_total = info->packets_total = 0;
17840 +            };
17841 +
17842 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
17843 +
17844 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
17845 +                                       / amount);
17846 +
17847 +               info->previous_time = info->present_time;
17848 +               info->bytes_total = info->packets_total = 0;
17849 +
17850 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
17851 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
17852 +
17853 +               info->acceptance_rate = (u_int8_t) \
17854 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
17855 +
17856 +       /* In fact, the above defuzzification would require a denominator
17857 +        * proportional to (howhigh+howlow) but, in this particular case,
17858 +        * that expression is constant.
17859 +        * An imediate consequence is that it is not necessary to call
17860 +        * both mf_high and mf_low - but to keep things understandable,
17861 +        * I did so.
17862 +        */
17863 +
17864 +       }
17865 +
17866 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
17867 +
17868 +
17869 +       if (info->acceptance_rate < 100)
17870 +       {
17871 +               get_random_bytes((void *)(&random_number), 1);
17872 +
17873 +               /*  If within the acceptance , it can pass => don't match */
17874 +               if (random_number <= (255 * info->acceptance_rate) / 100)
17875 +                       return 0;
17876 +               else
17877 +                       return 1; /* It can't pass (It matches) */
17878 +       };
17879 +
17880 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
17881 +
17882 +}
17883 +
17884 +static int
17885 +ip6t_fuzzy_checkentry(const char *tablename,
17886 +                  const struct ip6t_ip6 *ip,
17887 +                  void *matchinfo,
17888 +                  unsigned int matchsize,
17889 +                  unsigned int hook_mask)
17890 +{
17891 +
17892 +       const struct ip6t_fuzzy_info *info = matchinfo;
17893 +
17894 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
17895 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
17896 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
17897 +               return 0;
17898 +       }
17899 +
17900 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
17901 +        || (info->minimum_rate >= info->maximum_rate)) {
17902 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
17903 +               return 0;
17904 +       }
17905 +
17906 +       return 1;
17907 +}
17908 +
17909 +static struct ip6t_match ip6t_fuzzy_reg = {
17910 +       {NULL, NULL},
17911 +       "fuzzy",
17912 +       ip6t_fuzzy_match,
17913 +       ip6t_fuzzy_checkentry,
17914 +       NULL,
17915 +       THIS_MODULE };
17916 +
17917 +static int __init init(void)
17918 +{
17919 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
17920 +               return -EINVAL;
17921 +
17922 +       return 0;
17923 +}
17924 +
17925 +static void __exit fini(void)
17926 +{
17927 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
17928 +}
17929 +
17930 +module_init(init);
17931 +module_exit(fini);
17932 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c
17933 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c       1970-01-01 01:00:00.000000000 +0100
17934 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c   2004-06-25 12:21:10.462801152 +0200
17935 @@ -0,0 +1,173 @@
17936 +/*
17937 +  This is a module which is used for match support for every Nth packet
17938 +  This file is distributed under the terms of the GNU General Public
17939 +  License (GPL). Copies of the GPL can be obtained from:
17940 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
17941 +
17942 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
17943 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
17944 +        * added support for multiple counters
17945 +        * added support for matching on individual packets
17946 +          in the counter cycle
17947 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
17948 +
17949 +*/
17950 +
17951 +#include <linux/module.h>
17952 +#include <linux/skbuff.h>
17953 +#include <linux/ip.h>
17954 +#include <net/tcp.h>
17955 +#include <linux/spinlock.h>
17956 +#include <linux/netfilter_ipv6/ip6_tables.h>
17957 +#include <linux/netfilter_ipv6/ip6t_nth.h>
17958 +
17959 +MODULE_LICENSE("GPL");
17960 +
17961 +/*
17962 + * State information.
17963 + */
17964 +struct state {
17965 +       spinlock_t lock;
17966 +       u_int16_t number;
17967 +};
17968 +
17969 +static struct state states[IP6T_NTH_NUM_COUNTERS];
17970 +
17971 +static int
17972 +ip6t_nth_match(const struct sk_buff *pskb,
17973 +             const struct net_device *in,
17974 +             const struct net_device *out,
17975 +             const void *matchinfo,
17976 +             int offset,
17977 +             const void *hdr,
17978 +             u_int16_t datalen,
17979 +             int *hotdrop)
17980 +{
17981 +       /* Parameters from userspace */
17982 +       const struct ip6t_nth_info *info = matchinfo;
17983 +        unsigned counter = info->counter;
17984 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
17985 +       {
17986 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
17987 +               return 0;
17988 +        };
17989 +
17990 +        spin_lock(&states[counter].lock);
17991 +
17992 +        /* Are we matching every nth packet?*/
17993 +        if (info->packet == 0xFF)
17994 +        {
17995 +               /* We're matching every nth packet and only every nth packet*/
17996 +               /* Do we match or invert match? */
17997 +               if (info->not == 0)
17998 +               {
17999 +                       if (states[counter].number == 0)
18000 +                       {
18001 +                               ++states[counter].number;
18002 +                               goto match;
18003 +                       }
18004 +                       if (states[counter].number >= info->every)
18005 +                               states[counter].number = 0; /* reset the counter */
18006 +                       else
18007 +                               ++states[counter].number;
18008 +                       goto dontmatch;
18009 +               }
18010 +               else
18011 +               {
18012 +                       if (states[counter].number == 0)
18013 +                       {
18014 +                               ++states[counter].number;
18015 +                               goto dontmatch;
18016 +                       }
18017 +                       if (states[counter].number >= info->every)
18018 +                               states[counter].number = 0;
18019 +                       else
18020 +                               ++states[counter].number;
18021 +                       goto match;
18022 +               }
18023 +        }
18024 +        else
18025 +        {
18026 +               /* We're using the --packet, so there must be a rule for every value */
18027 +               if (states[counter].number == info->packet)
18028 +               {
18029 +                       /* only increment the counter when a match happens */
18030 +                       if (states[counter].number >= info->every)
18031 +                               states[counter].number = 0; /* reset the counter */
18032 +                       else
18033 +                               ++states[counter].number;
18034 +                       goto match;
18035 +               }
18036 +               else
18037 +                       goto dontmatch;
18038 +       }
18039 +
18040 + dontmatch:
18041 +       /* don't match */
18042 +       spin_unlock(&states[counter].lock);
18043 +       return 0;
18044 +
18045 + match:
18046 +       spin_unlock(&states[counter].lock);
18047 +       return 1;
18048 +}
18049 +
18050 +static int
18051 +ip6t_nth_checkentry(const char *tablename,
18052 +                  const struct ip6t_ip6 *e,
18053 +                  void *matchinfo,
18054 +                  unsigned int matchsize,
18055 +                  unsigned int hook_mask)
18056 +{
18057 +       /* Parameters from userspace */
18058 +       const struct ip6t_nth_info *info = matchinfo;
18059 +        unsigned counter = info->counter;
18060 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
18061 +       {
18062 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
18063 +                       return 0;
18064 +               };
18065 +
18066 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
18067 +               printk("nth: matchsize %u != %u\n", matchsize,
18068 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
18069 +               return 0;
18070 +       }
18071 +
18072 +       states[counter].number = info->startat;
18073 +
18074 +       return 1;
18075 +}
18076 +
18077 +static struct ip6t_match ip6t_nth_reg = { 
18078 +       {NULL, NULL},
18079 +       "nth",
18080 +       ip6t_nth_match,
18081 +       ip6t_nth_checkentry,
18082 +       NULL,
18083 +       THIS_MODULE };
18084 +
18085 +static int __init init(void)
18086 +{
18087 +       unsigned counter;
18088 +        memset(&states, 0, sizeof(states));
18089 +       if (ip6t_register_match(&ip6t_nth_reg))
18090 +               return -EINVAL;
18091 +
18092 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
18093 +       {
18094 +               spin_lock_init(&(states[counter].lock));
18095 +        };
18096 +
18097 +       printk("ip6t_nth match loaded\n");
18098 +       return 0;
18099 +}
18100 +
18101 +static void __exit fini(void)
18102 +{
18103 +       ip6t_unregister_match(&ip6t_nth_reg);
18104 +       printk("ip6t_nth match unloaded\n");
18105 +}
18106 +
18107 +module_init(init);
18108 +module_exit(fini);
18109 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.7/net/ipv6/netfilter/ip6t_owner.c
18110 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_owner.c     2004-06-25 10:47:46.000000000 +0200
18111 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_owner.c 2004-06-25 12:23:17.499488640 +0200
18112 @@ -21,6 +21,39 @@
18113  MODULE_LICENSE("GPL");
18114  
18115  static int
18116 +match_comm(const struct sk_buff *skb, const char *comm)
18117 +{
18118 +       struct task_struct *p, *g;
18119 +       struct files_struct *files;
18120 +       int i;
18121 +
18122 +       read_lock(&tasklist_lock);
18123 +       do_each_thread(g, p) {
18124 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
18125 +                       continue;
18126 +
18127 +               task_lock(p);
18128 +               files = p->files;
18129 +               if(files) {
18130 +                       read_lock(&files->file_lock);
18131 +                       for (i=0; i < files->max_fds; i++) {
18132 +                               if (fcheck_files(files, i) ==
18133 +                                   skb->sk->sk_socket->file) {
18134 +                                       read_unlock(&files->file_lock);
18135 +                                       task_unlock(p);
18136 +                                       read_unlock(&tasklist_lock);
18137 +                                       return 1;
18138 +                               }
18139 +                       }
18140 +                       read_unlock(&files->file_lock);
18141 +               }
18142 +               task_unlock(p);
18143 +       } while_each_thread(g, p);
18144 +       read_unlock(&tasklist_lock);
18145 +       return 0;
18146 +}
18147 +
18148 +static int
18149  match_pid(const struct sk_buff *skb, pid_t pid)
18150  {
18151         struct task_struct *p;
18152 @@ -125,6 +158,12 @@
18153                         return 0;
18154         }
18155  
18156 +       if(info->match & IP6T_OWNER_COMM) {
18157 +               if (!match_comm(skb, info->comm) ^
18158 +                   !!(info->invert & IP6T_OWNER_COMM))
18159 +                       return 0;
18160 +       }
18161 +
18162         return 1;
18163  }
18164  
18165 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.7/net/ipv6/netfilter/ip6t_policy.c
18166 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_policy.c    1970-01-01 01:00:00.000000000 +0100
18167 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_policy.c        2004-05-07 18:20:57.000000000 +0200
18168 @@ -0,0 +1,201 @@
18169 +/* IP tables module for matching IPsec policy
18170 + *
18171 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
18172 + *
18173 + * This program is free software; you can redistribute it and/or modify
18174 + * it under the terms of the GNU General Public License version 2 as
18175 + * published by the Free Software Foundation.
18176 + */
18177 +
18178 +#include <linux/kernel.h>
18179 +#include <linux/config.h>
18180 +#include <linux/module.h>
18181 +#include <linux/skbuff.h>
18182 +#include <linux/init.h>
18183 +#include <net/xfrm.h>
18184 +
18185 +#include <linux/netfilter_ipv6.h>
18186 +#include <linux/netfilter_ipv6/ip6t_policy.h>
18187 +#include <linux/netfilter_ipv6/ip6_tables.h>
18188 +
18189 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
18190 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
18191 +MODULE_LICENSE("GPL");
18192 +
18193 +
18194 +static inline int ip6_masked_addrcmp(struct in6_addr addr1,
18195 +                                     struct in6_addr mask,
18196 +                                     struct in6_addr addr2)
18197 +{
18198 +       int i;
18199 +
18200 +       for (i = 0; i < 16; i++) {
18201 +               if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
18202 +                   (addr2.s6_addr[i] & mask.s6_addr[i]))
18203 +                       return 1;
18204 +       }
18205 +       return 0;
18206 +}
18207 +
18208 +
18209 +static inline int
18210 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
18211 +{
18212 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
18213 +       
18214 +       struct in6_addr xfrm_saddr, xfrm_daddr;
18215 +       
18216 +       if ((e->match.saddr
18217 +            && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
18218 +               ^ e->invert.saddr ) ||
18219 +           (e->match.daddr
18220 +            && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
18221 +               ^ e->invert.daddr ) ||
18222 +           MISMATCH(proto, x->id.proto) ||
18223 +           MISMATCH(mode, x->props.mode) ||
18224 +           MISMATCH(spi, x->id.spi) ||
18225 +           MISMATCH(reqid, x->props.reqid))
18226 +               return 0;
18227 +       return 1;
18228 +}
18229 +
18230 +static int
18231 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18232 +{
18233 +       const struct ip6t_policy_elem *e;
18234 +       struct sec_path *sp = skb->sp;
18235 +       int strict = info->flags & POLICY_MATCH_STRICT;
18236 +       int i, pos;
18237 +
18238 +       if (sp == NULL)
18239 +               return -1;
18240 +       if (strict && info->len != sp->len)
18241 +               return 0;
18242 +
18243 +       for (i = sp->len - 1; i >= 0; i--) {
18244 +               pos = strict ? i - sp->len + 1 : 0;
18245 +               if (pos >= info->len)
18246 +                       return 0;
18247 +               e = &info->pol[pos];
18248 +
18249 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
18250 +                       if (!strict)
18251 +                               return 1;
18252 +               } else if (strict)
18253 +                       return 0;
18254 +       }
18255 +
18256 +       return strict ? 1 : 0;
18257 +}
18258 +
18259 +static int
18260 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18261 +{
18262 +       const struct ip6t_policy_elem *e;
18263 +       struct dst_entry *dst = skb->dst;
18264 +       int strict = info->flags & POLICY_MATCH_STRICT;
18265 +       int i, pos;
18266 +
18267 +       if (dst->xfrm == NULL)
18268 +               return -1;
18269 +
18270 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
18271 +               pos = strict ? i : 0;
18272 +               if (pos >= info->len)
18273 +                       return 0;
18274 +               e = &info->pol[pos];
18275 +
18276 +               if (match_xfrm_state(dst->xfrm, e)) {
18277 +                       if (!strict)
18278 +                               return 1;
18279 +               } else if (strict)
18280 +                       return 0;
18281 +       }
18282 +
18283 +       return strict ? 1 : 0;
18284 +}
18285 +
18286 +static int match(const struct sk_buff *skb,
18287 +                 const struct net_device *in,
18288 +                 const struct net_device *out,
18289 +                 const void *matchinfo,
18290 +                int offset,
18291 +                const void *hdr,
18292 +                u_int16_t datalen,
18293 +                int *hotdrop)
18294 +{
18295 +       const struct ip6t_policy_info *info = matchinfo;
18296 +       int ret;
18297 +
18298 +       if (info->flags & POLICY_MATCH_IN)
18299 +               ret = match_policy_in(skb, info);
18300 +       else
18301 +               ret = match_policy_out(skb, info);
18302 +
18303 +       if (ret < 0) {
18304 +               if (info->flags & POLICY_MATCH_NONE)
18305 +                       ret = 1;
18306 +               else
18307 +                       ret = 0;
18308 +       } else if (info->flags & POLICY_MATCH_NONE)
18309 +               ret = 0;
18310 +
18311 +       return ret;
18312 +}
18313 +
18314 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
18315 +                      void *matchinfo, unsigned int matchsize,
18316 +                      unsigned int hook_mask)
18317 +{
18318 +       struct ip6t_policy_info *info = matchinfo;
18319 +
18320 +       if (matchsize != IP6T_ALIGN(sizeof(*info))) {
18321 +               printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
18322 +                      matchsize, IP6T_ALIGN(sizeof(*info)));
18323 +               return 0;
18324 +       }
18325 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
18326 +               printk(KERN_ERR "ip6t_policy: neither incoming nor "
18327 +                               "outgoing policy selected\n");
18328 +               return 0;
18329 +       }
18330 +       if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
18331 +           && info->flags & POLICY_MATCH_OUT) {
18332 +               printk(KERN_ERR "ip6t_policy: output policy not valid in "
18333 +                               "PRE_ROUTING and INPUT\n");
18334 +               return 0;
18335 +       }
18336 +       if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
18337 +           && info->flags & POLICY_MATCH_IN) {
18338 +               printk(KERN_ERR "ip6t_policy: input policy not valid in "
18339 +                               "POST_ROUTING and OUTPUT\n");
18340 +               return 0;
18341 +       }
18342 +       if (info->len > POLICY_MAX_ELEM) {
18343 +               printk(KERN_ERR "ip6t_policy: too many policy elements\n");
18344 +               return 0;
18345 +       }
18346 +
18347 +       return 1;
18348 +}
18349 +
18350 +static struct ip6t_match policy_match =
18351 +{
18352 +       .name           = "policy",
18353 +       .match          = match,
18354 +       .checkentry     = checkentry,
18355 +       .me             = THIS_MODULE,
18356 +};
18357 +
18358 +static int __init init(void)
18359 +{
18360 +       return ip6t_register_match(&policy_match);
18361 +}
18362 +
18363 +static void __exit fini(void)
18364 +{
18365 +       ip6t_unregister_match(&policy_match);
18366 +}
18367 +
18368 +module_init(init);
18369 +module_exit(fini);
18370 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.7/net/ipv6/netfilter/ip6t_random.c
18371 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_random.c    1970-01-01 01:00:00.000000000 +0100
18372 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_random.c        2004-06-25 12:21:12.940424496 +0200
18373 @@ -0,0 +1,97 @@
18374 +/*
18375 +  This is a module which is used for a "random" match support.
18376 +  This file is distributed under the terms of the GNU General Public
18377 +  License (GPL). Copies of the GPL can be obtained from:
18378 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
18379 +
18380 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18381 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18382 +*/
18383 +
18384 +#include <linux/module.h>
18385 +#include <linux/skbuff.h>
18386 +#include <linux/ip.h>
18387 +#include <linux/random.h>
18388 +#include <net/tcp.h>
18389 +#include <linux/spinlock.h>
18390 +#include <linux/netfilter_ipv6/ip6_tables.h>
18391 +#include <linux/netfilter_ipv6/ip6t_random.h>
18392 +
18393 +MODULE_LICENSE("GPL");
18394 +
18395 +static int
18396 +ip6t_rand_match(const struct sk_buff *pskb,
18397 +              const struct net_device *in,
18398 +              const struct net_device *out,
18399 +              const void *matchinfo,
18400 +              int offset,
18401 +              const void *hdr,
18402 +              u_int16_t datalen,
18403 +              int *hotdrop)
18404 +{
18405 +       /* Parameters from userspace */
18406 +       const struct ip6t_rand_info *info = matchinfo;
18407 +       u_int8_t random_number;
18408 +
18409 +       /* get 1 random number from the kernel random number generation routine */
18410 +       get_random_bytes((void *)(&random_number), 1);
18411 +
18412 +       /* Do we match ? */
18413 +       if (random_number <= info->average)
18414 +               return 1;
18415 +       else
18416 +               return 0;
18417 +}
18418 +
18419 +static int
18420 +ip6t_rand_checkentry(const char *tablename,
18421 +                  const struct ip6t_ip6 *e,
18422 +                  void *matchinfo,
18423 +                  unsigned int matchsize,
18424 +                  unsigned int hook_mask)
18425 +{
18426 +       /* Parameters from userspace */
18427 +       const struct ip6t_rand_info *info = matchinfo;
18428 +
18429 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
18430 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
18431 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
18432 +               return 0;
18433 +       }
18434 +
18435 +       /* must be  1 <= average % <= 99 */
18436 +       /* 1  x 2.55 = 2   */
18437 +       /* 99 x 2.55 = 252 */
18438 +       if ((info->average < 2) || (info->average > 252)) {
18439 +               printk("ip6t_random:  invalid average %u\n", info->average);
18440 +               return 0;
18441 +       }
18442 +
18443 +       return 1;
18444 +}
18445 +
18446 +static struct ip6t_match ip6t_rand_reg = { 
18447 +       {NULL, NULL},
18448 +       "random",
18449 +       ip6t_rand_match,
18450 +       ip6t_rand_checkentry,
18451 +       NULL,
18452 +       THIS_MODULE };
18453 +
18454 +static int __init init(void)
18455 +{
18456 +       if (ip6t_register_match(&ip6t_rand_reg))
18457 +               return -EINVAL;
18458 +
18459 +       printk("ip6t_random match loaded\n");
18460 +       return 0;
18461 +}
18462 +
18463 +static void __exit fini(void)
18464 +{
18465 +       ip6t_unregister_match(&ip6t_rand_reg);
18466 +       printk("ip6t_random match unloaded\n");
18467 +}
18468 +
18469 +module_init(init);
18470 +module_exit(fini);
18471 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/xfrm/xfrm_input.c linux-2.6.7/net/xfrm/xfrm_input.c
18472 --- linux-2.6.7.org/net/xfrm/xfrm_input.c       2004-06-16 07:18:54.000000000 +0200
18473 +++ linux-2.6.7/net/xfrm/xfrm_input.c   2004-06-25 12:21:37.111749896 +0200
18474 @@ -29,6 +29,9 @@
18475         if (!sp)
18476                 return NULL;
18477  
18478 +#ifdef CONFIG_NETFILTER
18479 +       sp->decap_done = 0;
18480 +#endif
18481         sp->len = 0;
18482         if (src) {
18483                 int i;
18484 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/xfrm/xfrm_policy.c linux-2.6.7/net/xfrm/xfrm_policy.c
18485 --- linux-2.6.7.org/net/xfrm/xfrm_policy.c      2004-06-16 07:19:23.000000000 +0200
18486 +++ linux-2.6.7/net/xfrm/xfrm_policy.c  2004-06-25 12:21:38.725504568 +0200
18487 @@ -21,6 +21,7 @@
18488  #include <linux/workqueue.h>
18489  #include <linux/notifier.h>
18490  #include <linux/netdevice.h>
18491 +#include <linux/netfilter.h>
18492  #include <net/xfrm.h>
18493  #include <net/ip.h>
18494  
18495 @@ -911,6 +912,7 @@
18496  
18497         if (_decode_session(skb, &fl, family) < 0)
18498                 return 0;
18499 +       nf_nat_decode_session(skb, &fl, family);
18500  
18501         /* First, check used SA against their selectors. */
18502         if (skb->sp) {
This page took 1.51624 seconds and 3 git commands to generate.