]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.6-rc3-pom-ng-20040429.patch
- CSZ scheduler removed from kernel tree.
[packages/kernel.git] / 2.6.6-rc3-pom-ng-20040429.patch
CommitLineData
b8c31cb3 1 Netfilter SNAP 20040429
2 included:
3 PENDING/expect-evict-order
4 PENDING/init_conntrack-optimize
5 PENDING/ipt_helper-invert-fix
6 PENDING/nf-log
7 PENDING/nf_reset
8 PENDING/orphaned-expect-fix
9 PENDING/proc-no-internal-targets
10 BASE/HOPLIMIT
11 BASE/IPV4OPTSSTRING
12 BASE/NETLINK // fix socket -> sk_socket
13 BASE/REJECT
14 BASE/TTL
15 BASE/connlimit
16 BASE/dstlimit
17 BASE/fuzzy
18 BASE/ipv4options
19 BASE/mport
20 BASE/nth
21 BASE/osf // fix socket -> sk_socket
22 BASE/pool // added EXPORT_SYMBOL(ip_pool_mod, ip_pool_match)
23 BASE/psd
24 BASE/quota
25 BASE/random
26 BASE/realm
27 BASE/sctp
28 BASE/time
29 BASE/u32
30 EXTRA/CONNMARK // main linux.patch needs fix
31 EXTRA/IPMARK
32 EXTRA/ROUTE
33 EXTRA/TARPIT // fix Makefile.ladd and req patch for 2.6
34 EXTRA/TRACE
35 EXTRA/XOR
36 EXTRA/addrtype
37 EXTRA/eggdrop-conntrack
38 EXTRA/h323-conntrack-nat
39 EXTRA/ipsec-01-output-hooks
40 EXTRA/ipsec-02-input-hooks
41 EXTRA/ipsec-03-policy-lookup
42 EXTRA/ipsec-04-policy-check
43 EXTRA/ipt_helper-any
44 EXTRA/mms-conntrack-nat
45 EXTRA/owner-socketlookup
46 EXTRA/ownercmd
47 EXTRA/policy
48 EXTRA/quake3-conntrack-nat
49 EXTRA/rsh
50 EXTRA/rtsp-conntrack
51 EXTRA/sctp-conntrack-nat
52 EXTRA/string // required unclean module - included
53 EXTRA/talk-conntrack-nat
54
55diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter.h linux-2.6.6-rc3/include/linux/netfilter.h
56--- linux-2.6.6-rc3.org/include/linux/netfilter.h 2004-04-28 03:35:48.000000000 +0200
57+++ linux-2.6.6-rc3/include/linux/netfilter.h 2004-04-30 09:12:42.000000000 +0200
58@@ -23,6 +23,7 @@
59 <= 0x2000 is used for protocol-flags. */
60 #define NFC_UNKNOWN 0x4000
61 #define NFC_ALTERED 0x8000
62+#define NFC_TRACE 0x10000
63
64 #ifdef __KERNEL__
65 #include <linux/config.h>
66@@ -137,12 +138,14 @@
67 /* This is gross, but inline doesn't cut it for avoiding the function
68 call in fast path: gcc doesn't inline (needs value tracking?). --RR */
69 #ifdef CONFIG_NETFILTER_DEBUG
70-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
71- nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
72+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
73+(!(cond) \
74+ ? (okfn)(skb) \
75+ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
76 #define NF_HOOK_THRESH nf_hook_slow
77 #else
78-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
79-(list_empty(&nf_hooks[(pf)][(hook)]) \
80+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
81+(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
82 ? (okfn)(skb) \
83 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
84 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
85@@ -150,6 +153,8 @@
86 ? (okfn)(skb) \
87 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
88 #endif
89+#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
90+ NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
91
92 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
93 struct net_device *indev, struct net_device *outdev,
94@@ -182,7 +187,24 @@
95
96 #else /* !CONFIG_NETFILTER */
97 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
98+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
99 #endif /*CONFIG_NETFILTER*/
100
101+#ifdef CONFIG_XFRM
102+#ifdef CONFIG_IP_NF_NAT_NEEDED
103+struct flowi;
104+extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
105+
106+static inline void
107+nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
108+{
109+ if (family == AF_INET)
110+ nf_nat_decode_session4(skb, fl);
111+}
112+#else /* CONFIG_IP_NF_NAT_NEEDED */
113+#define nf_nat_decode_session(skb,fl,family)
114+#endif /* CONFIG_IP_NF_NAT_NEEDED */
115+#endif /* CONFIG_XFRM */
116+
117 #endif /*__KERNEL__*/
118 #endif /*__LINUX_NETFILTER_H*/
119diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h linux-2.6.6-rc3/include/linux/netfilter_helpers.h
120--- linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
121+++ linux-2.6.6-rc3/include/linux/netfilter_helpers.h 2004-04-30 09:14:05.000000000 +0200
122@@ -0,0 +1,133 @@
123+/*
124+ * Helpers for netfiler modules. This file provides implementations for basic
125+ * functions such as strncasecmp(), etc.
126+ *
127+ * gcc will warn for defined but unused functions, so we only include the
128+ * functions requested. The following macros are used:
129+ * NF_NEED_STRNCASECMP nf_strncasecmp()
130+ * NF_NEED_STRTOU16 nf_strtou16()
131+ * NF_NEED_STRTOU32 nf_strtou32()
132+ */
133+#ifndef _NETFILTER_HELPERS_H
134+#define _NETFILTER_HELPERS_H
135+
136+/* Only include these functions for kernel code. */
137+#ifdef __KERNEL__
138+
139+#include <linux/ctype.h>
140+#define iseol(c) ( (c) == '\r' || (c) == '\n' )
141+
142+/*
143+ * The standard strncasecmp()
144+ */
145+#ifdef NF_NEED_STRNCASECMP
146+static int
147+nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
148+{
149+ if (s1 == NULL || s2 == NULL)
150+ {
151+ if (s1 == NULL && s2 == NULL)
152+ {
153+ return 0;
154+ }
155+ return (s1 == NULL) ? -1 : 1;
156+ }
157+ while (len > 0 && tolower(*s1) == tolower(*s2))
158+ {
159+ len--;
160+ s1++;
161+ s2++;
162+ }
163+ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
164+}
165+#endif /* NF_NEED_STRNCASECMP */
166+
167+/*
168+ * Parse a string containing a 16-bit unsigned integer.
169+ * Returns the number of chars used, or zero if no number is found.
170+ */
171+#ifdef NF_NEED_STRTOU16
172+static int
173+nf_strtou16(const char* pbuf, u_int16_t* pval)
174+{
175+ int n = 0;
176+
177+ *pval = 0;
178+ while (isdigit(pbuf[n]))
179+ {
180+ *pval = (*pval * 10) + (pbuf[n] - '0');
181+ n++;
182+ }
183+
184+ return n;
185+}
186+#endif /* NF_NEED_STRTOU16 */
187+
188+/*
189+ * Parse a string containing a 32-bit unsigned integer.
190+ * Returns the number of chars used, or zero if no number is found.
191+ */
192+#ifdef NF_NEED_STRTOU32
193+static int
194+nf_strtou32(const char* pbuf, u_int32_t* pval)
195+{
196+ int n = 0;
197+
198+ *pval = 0;
199+ while (pbuf[n] >= '0' && pbuf[n] <= '9')
200+ {
201+ *pval = (*pval * 10) + (pbuf[n] - '0');
202+ n++;
203+ }
204+
205+ return n;
206+}
207+#endif /* NF_NEED_STRTOU32 */
208+
209+/*
210+ * Given a buffer and length, advance to the next line and mark the current
211+ * line.
212+ */
213+#ifdef NF_NEED_NEXTLINE
214+static int
215+nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
216+{
217+ uint off = *poff;
218+ uint physlen = 0;
219+
220+ if (off >= len)
221+ {
222+ return 0;
223+ }
224+
225+ while (p[off] != '\n')
226+ {
227+ if (len-off <= 1)
228+ {
229+ return 0;
230+ }
231+
232+ physlen++;
233+ off++;
234+ }
235+
236+ /* if we saw a crlf, physlen needs adjusted */
237+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
238+ {
239+ physlen--;
240+ }
241+
242+ /* advance past the newline */
243+ off++;
244+
245+ *plineoff = *poff;
246+ *plinelen = physlen;
247+ *poff = off;
248+
249+ return 1;
250+}
251+#endif /* NF_NEED_NEXTLINE */
252+
253+#endif /* __KERNEL__ */
254+
255+#endif /* _NETFILTER_HELPERS_H */
256diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
257--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-28 03:36:37.000000000 +0200
258+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-30 09:14:39.000000000 +0200
259@@ -51,10 +51,12 @@
260
261 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
262 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
263+#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
264
265 /* per conntrack: protocol private data */
266 union ip_conntrack_proto {
267 /* insert conntrack proto private data here */
268+ struct ip_ct_sctp sctp;
269 struct ip_ct_tcp tcp;
270 struct ip_ct_icmp icmp;
271 };
272@@ -64,6 +66,11 @@
273 };
274
275 /* Add protocol helper include file here */
276+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
277+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
278+#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
279+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
280+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
281 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
282 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
283 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
284@@ -71,6 +78,11 @@
285 /* per expectation: application helper private data */
286 union ip_conntrack_expect_help {
287 /* insert conntrack helper private data (expect) here */
288+ struct ip_ct_talk_expect exp_talk_info;
289+ struct ip_ct_rtsp_expect exp_rtsp_info;
290+ struct ip_ct_rsh_expect exp_rsh_info;
291+ struct ip_ct_mms_expect exp_mms_info;
292+ struct ip_ct_h225_expect exp_h225_info;
293 struct ip_ct_amanda_expect exp_amanda_info;
294 struct ip_ct_ftp_expect exp_ftp_info;
295 struct ip_ct_irc_expect exp_irc_info;
296@@ -85,6 +97,11 @@
297 /* per conntrack: application helper private data */
298 union ip_conntrack_help {
299 /* insert conntrack helper private data (master) here */
300+ struct ip_ct_talk_master ct_talk_info;
301+ struct ip_ct_rtsp_master ct_rtsp_info;
302+ struct ip_ct_rsh_master ct_rsh_info;
303+ struct ip_ct_mms_master ct_mms_info;
304+ struct ip_ct_h225_master ct_h225_info;
305 struct ip_ct_ftp_master ct_ftp_info;
306 struct ip_ct_irc_master ct_irc_info;
307 };
308@@ -207,6 +224,10 @@
309 } nat;
310 #endif /* CONFIG_IP_NF_NAT_NEEDED */
311
312+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
313+ unsigned long mark;
314+#endif
315+
316 };
317
318 /* get master conntrack via master expectation */
319diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
320--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
321+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-04-30 09:12:34.000000000 +0200
322@@ -0,0 +1,31 @@
323+#ifndef _IP_CONNTRACK_H323_H
324+#define _IP_CONNTRACK_H323_H
325+/* H.323 connection tracking. */
326+
327+#ifdef __KERNEL__
328+/* Protects H.323 related data */
329+#include <linux/netfilter_ipv4/lockhelp.h>
330+DECLARE_LOCK_EXTERN(ip_h323_lock);
331+#endif
332+
333+/* Default H.225 port */
334+#define H225_PORT 1720
335+
336+/* This structure is per expected connection */
337+struct ip_ct_h225_expect {
338+ u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
339+ enum ip_conntrack_dir dir; /* Direction of the original connection */
340+ unsigned int offset; /* offset of the address in the payload */
341+};
342+
343+/* This structure exists only once per master */
344+struct ip_ct_h225_master {
345+ int is_h225; /* H.225 or H.245 connection */
346+#ifdef CONFIG_IP_NF_NAT_NEEDED
347+ enum ip_conntrack_dir dir; /* Direction of the original connection */
348+ u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
349+ unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
350+#endif
351+};
352+
353+#endif /* _IP_CONNTRACK_H323_H */
354diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
355--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
356+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-04-30 09:12:58.000000000 +0200
357@@ -0,0 +1,31 @@
358+#ifndef _IP_CONNTRACK_MMS_H
359+#define _IP_CONNTRACK_MMS_H
360+/* MMS tracking. */
361+
362+#ifdef __KERNEL__
363+#include <linux/netfilter_ipv4/lockhelp.h>
364+
365+DECLARE_LOCK_EXTERN(ip_mms_lock);
366+
367+#define MMS_PORT 1755
368+#define MMS_SRV_MSG_ID 196610
369+
370+#define MMS_SRV_MSG_OFFSET 36
371+#define MMS_SRV_UNICODE_STRING_OFFSET 60
372+#define MMS_SRV_CHUNKLENLV_OFFSET 16
373+#define MMS_SRV_CHUNKLENLM_OFFSET 32
374+#define MMS_SRV_MESSAGELENGTH_OFFSET 8
375+#endif
376+
377+/* This structure is per expected connection */
378+struct ip_ct_mms_expect {
379+ u_int32_t len;
380+ u_int32_t padding;
381+ u_int16_t port;
382+};
383+
384+/* This structure exists only once per master */
385+struct ip_ct_mms_master {
386+};
387+
388+#endif /* _IP_CONNTRACK_MMS_H */
389diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
390--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
391+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-04-30 09:13:29.000000000 +0200
392@@ -0,0 +1,21 @@
393+#ifndef _IP_CT_QUAKE3
394+#define _IP_CT_QUAKE3
395+
396+/* Don't confuse with 27960, often used as the Server Port */
397+#define QUAKE3_MASTER_PORT 27950
398+
399+struct quake3_search {
400+ const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
401+ const char *pattern;
402+ size_t plen;
403+};
404+
405+/* This structure is per expected connection */
406+struct ip_ct_quake3_expect {
407+};
408+
409+/* This structure exists only once per master */
410+struct ip_ct_quake3_master {
411+};
412+
413+#endif /* _IP_CT_QUAKE3 */
414diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
415--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
416+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-04-30 09:13:59.000000000 +0200
417@@ -0,0 +1,35 @@
418+/* RSH extension for IP connection tracking, Version 1.0
419+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
420+ * based on HW's ip_conntrack_irc.c
421+ *
422+ * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
423+ *
424+ * This program is free software; you can redistribute it and/or
425+ * modify it under the terms of the GNU General Public License
426+ * as published by the Free Software Foundation; either version
427+ * 2 of the License, or (at your option) any later version.
428+ */
429+#ifndef _IP_CONNTRACK_RSH_H
430+#define _IP_CONNTRACK_RSH_H
431+
432+#ifdef __KERNEL__
433+#include <linux/netfilter_ipv4/lockhelp.h>
434+
435+DECLARE_LOCK_EXTERN(ip_rsh_lock);
436+#endif
437+
438+
439+#define RSH_PORT 514
440+
441+/* This structure is per expected connection */
442+struct ip_ct_rsh_expect
443+{
444+ u_int16_t port;
445+};
446+
447+/* This structure exists only once per master */
448+struct ip_ct_rsh_master {
449+};
450+
451+#endif /* _IP_CONNTRACK_RSH_H */
452+
453diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
454--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
455+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-04-30 09:14:05.000000000 +0200
456@@ -0,0 +1,68 @@
457+/*
458+ * RTSP extension for IP connection tracking.
459+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
460+ * based on ip_conntrack_irc.h
461+ *
462+ * This program is free software; you can redistribute it and/or
463+ * modify it under the terms of the GNU General Public License
464+ * as published by the Free Software Foundation; either version
465+ * 2 of the License, or (at your option) any later version.
466+ */
467+#ifndef _IP_CONNTRACK_RTSP_H
468+#define _IP_CONNTRACK_RTSP_H
469+
470+/* #define IP_NF_RTSP_DEBUG */
471+#define IP_NF_RTSP_VERSION "0.01"
472+
473+/* port block types */
474+typedef enum {
475+ pb_single, /* client_port=x */
476+ pb_range, /* client_port=x-y */
477+ pb_discon /* client_port=x/y (rtspbis) */
478+} portblock_t;
479+
480+/* We record seq number and length of rtsp headers here, all in host order. */
481+
482+/*
483+ * This structure is per expected connection. It is a member of struct
484+ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
485+ * there and we are expected to only store the length of the data which
486+ * needs replaced. If a packet contains multiple RTSP messages, we create
487+ * one expected connection per message.
488+ *
489+ * We use these variables to mark the entire header block. This may seem
490+ * like overkill, but the nature of RTSP requires it. A header may appear
491+ * multiple times in a message. We must treat two Transport headers the
492+ * same as one Transport header with two entries.
493+ */
494+struct ip_ct_rtsp_expect
495+{
496+ u_int32_t len; /* length of header block */
497+ portblock_t pbtype; /* Type of port block that was requested */
498+ u_int16_t loport; /* Port that was requested, low or first */
499+ u_int16_t hiport; /* Port that was requested, high or second */
500+#if 0
501+ uint method; /* RTSP method */
502+ uint cseq; /* CSeq from request */
503+#endif
504+};
505+
506+/* This structure exists only once per master */
507+struct ip_ct_rtsp_master
508+{
509+ /* Empty (?) */
510+};
511+
512+
513+#ifdef __KERNEL__
514+
515+#include <linux/netfilter_ipv4/lockhelp.h>
516+
517+#define RTSP_PORT 554
518+
519+/* Protects rtsp part of conntracks */
520+DECLARE_LOCK_EXTERN(ip_rtsp_lock);
521+
522+#endif /* __KERNEL__ */
523+
524+#endif /* _IP_CONNTRACK_RTSP_H */
525diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
526--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
527+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-04-30 09:14:08.000000000 +0200
528@@ -0,0 +1,25 @@
529+#ifndef _IP_CONNTRACK_SCTP_H
530+#define _IP_CONNTRACK_SCTP_H
531+/* SCTP tracking. */
532+
533+enum sctp_conntrack {
534+ SCTP_CONNTRACK_NONE,
535+ SCTP_CONNTRACK_CLOSED,
536+ SCTP_CONNTRACK_COOKIE_WAIT,
537+ SCTP_CONNTRACK_COOKIE_ECHOED,
538+ SCTP_CONNTRACK_ESTABLISHED,
539+ SCTP_CONNTRACK_SHUTDOWN_SENT,
540+ SCTP_CONNTRACK_SHUTDOWN_RECD,
541+ SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
542+ SCTP_CONNTRACK_MAX
543+};
544+
545+struct ip_ct_sctp
546+{
547+ enum sctp_conntrack state;
548+
549+ u_int32_t vtag[IP_CT_DIR_MAX];
550+ u_int32_t ttag[IP_CT_DIR_MAX];
551+};
552+
553+#endif /* _IP_CONNTRACK_SCTP_H */
554diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
555--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
556+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-04-30 09:14:39.000000000 +0200
557@@ -0,0 +1,152 @@
558+#ifndef _IP_CONNTRACK_TALK_H
559+#define _IP_CONNTRACK_TALK_H
560+/* TALK tracking. */
561+
562+#ifdef __KERNEL__
563+#include <linux/in.h>
564+#include <linux/netfilter_ipv4/lockhelp.h>
565+
566+/* Protects talk part of conntracks */
567+DECLARE_LOCK_EXTERN(ip_talk_lock);
568+#endif
569+
570+
571+#define TALK_PORT 517
572+#define NTALK_PORT 518
573+
574+/* talk structures and constants from <protocols/talkd.h> */
575+
576+/*
577+ * 4.3BSD struct sockaddr
578+ */
579+struct talk_addr {
580+ u_int16_t ta_family;
581+ u_int16_t ta_port;
582+ u_int32_t ta_addr;
583+ u_int32_t ta_junk1;
584+ u_int32_t ta_junk2;
585+};
586+
587+#define TALK_OLD_NSIZE 9
588+#define TALK_NSIZE 12
589+#define TALK_TTY_NSIZE 16
590+
591+/*
592+ * Client->server request message formats.
593+ */
594+struct talk_msg {
595+ u_char type; /* request type, see below */
596+ char l_name[TALK_OLD_NSIZE];/* caller's name */
597+ char r_name[TALK_OLD_NSIZE];/* callee's name */
598+ u_char pad;
599+ u_int32_t id_num; /* message id */
600+ int32_t pid; /* caller's process id */
601+ char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
602+ struct talk_addr addr; /* old (4.3) style */
603+ struct talk_addr ctl_addr; /* old (4.3) style */
604+};
605+
606+struct ntalk_msg {
607+ u_char vers; /* protocol version */
608+ u_char type; /* request type, see below */
609+ u_char answer; /* not used */
610+ u_char pad;
611+ u_int32_t id_num; /* message id */
612+ struct talk_addr addr; /* old (4.3) style */
613+ struct talk_addr ctl_addr; /* old (4.3) style */
614+ int32_t pid; /* caller's process id */
615+ char l_name[TALK_NSIZE];/* caller's name */
616+ char r_name[TALK_NSIZE];/* callee's name */
617+ char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
618+};
619+
620+struct ntalk2_msg {
621+ u_char vers; /* talk protocol version */
622+ u_char type; /* request type */
623+ u_char answer; /* */
624+ u_char extended; /* !0 if additional parts */
625+ u_int32_t id_num; /* message id number (dels) */
626+ struct talk_addr addr; /* target address */
627+ struct talk_addr ctl_addr; /* reply to address */
628+ int32_t pid; /* caller's process id */
629+ char l_name[TALK_NSIZE]; /* caller's name */
630+ char r_name[TALK_NSIZE]; /* callee's name */
631+ char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
632+};
633+
634+/*
635+ * Server->client response message formats.
636+ */
637+struct talk_response {
638+ u_char type; /* type of request message, see below */
639+ u_char answer; /* response to request message, see below */
640+ u_char pad[2];
641+ u_int32_t id_num; /* message id */
642+ struct talk_addr addr; /* address for establishing conversation */
643+};
644+
645+struct ntalk_response {
646+ u_char vers; /* protocol version */
647+ u_char type; /* type of request message, see below */
648+ u_char answer; /* response to request message, see below */
649+ u_char pad;
650+ u_int32_t id_num; /* message id */
651+ struct talk_addr addr; /* address for establishing conversation */
652+};
653+
654+struct ntalk2_response {
655+ u_char vers; /* protocol version */
656+ u_char type; /* type of request message */
657+ u_char answer; /* response to request */
658+ u_char rvers; /* Version of answering vers*/
659+ u_int32_t id_num; /* message id number */
660+ struct talk_addr addr; /* address for connection */
661+ /* This is at the end to compatiblize this with NTALK version. */
662+ char r_name[TALK_NSIZE]; /* callee's name */
663+};
664+
665+#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
666+#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
667+#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
668+
669+#define TALK_VERSION 0 /* protocol versions */
670+#define NTALK_VERSION 1
671+#define NTALK2_VERSION 2
672+
673+/* message type values */
674+#define LEAVE_INVITE 0 /* leave invitation with server */
675+#define LOOK_UP 1 /* check for invitation by callee */
676+#define DELETE 2 /* delete invitation by caller */
677+#define ANNOUNCE 3 /* announce invitation by caller */
678+/* NTALK2 */
679+#define REPLY_QUERY 4 /* request reply data from local daemon */
680+
681+/* answer values */
682+#define SUCCESS 0 /* operation completed properly */
683+#define NOT_HERE 1 /* callee not logged in */
684+#define FAILED 2 /* operation failed for unexplained reason */
685+#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
686+#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
687+#define UNKNOWN_REQUEST 5 /* request has invalid type value */
688+#define BADVERSION 6 /* request has invalid protocol version */
689+#define BADADDR 7 /* request has invalid addr value */
690+#define BADCTLADDR 8 /* request has invalid ctl_addr value */
691+/* NTALK2 */
692+#define NO_CALLER 9 /* no-one calling answer from REPLY */
693+#define TRY_HERE 10 /* Not on this machine, try this */
694+#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
695+#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
696+
697+/* We don't really need much for talk */
698+struct ip_ct_talk_expect
699+{
700+ /* Port that was to be used */
701+ u_int16_t port;
702+};
703+
704+/* This structure exists only once per master */
705+struct ip_ct_talk_master
706+{
707+};
708+
709+#endif /* _IP_CONNTRACK_TALK_H */
710diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
711--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-28 03:36:22.000000000 +0200
712+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-30 09:14:08.000000000 +0200
713@@ -25,6 +25,9 @@
714 struct {
715 u_int16_t id;
716 } icmp;
717+ struct {
718+ u_int16_t port;
719+ } sctp;
720 };
721
722 /* The manipulable part of the tuple. */
723@@ -55,6 +58,9 @@
724 struct {
725 u_int8_t type, code;
726 } icmp;
727+ struct {
728+ u_int16_t port;
729+ } sctp;
730 } u;
731
732 /* The protocol. */
733diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h
734--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
735+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h 2004-04-30 09:10:40.000000000 +0200
736@@ -0,0 +1,64 @@
737+#ifndef _IP_POOL_H
738+#define _IP_POOL_H
739+
740+/***************************************************************************/
741+/* This program is free software; you can redistribute it and/or modify */
742+/* it under the terms of the GNU General Public License as published by */
743+/* the Free Software Foundation; either version 2 of the License, or */
744+/* (at your option) any later version. */
745+/* */
746+/* This program is distributed in the hope that it will be useful, */
747+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
748+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
749+/* GNU General Public License for more details. */
750+/* */
751+/* You should have received a copy of the GNU General Public License */
752+/* along with this program; if not, write to the Free Software */
753+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
754+/***************************************************************************/
755+
756+/* A sockopt of such quality has hardly ever been seen before on the open
757+ * market! This little beauty, hardly ever used: above 64, so it's
758+ * traditionally used for firewalling, not touched (even once!) by the
759+ * 2.0, 2.2 and 2.4 kernels!
760+ *
761+ * Comes with its own certificate of authenticity, valid anywhere in the
762+ * Free world!
763+ *
764+ * Rusty, 19.4.2000
765+ */
766+#define SO_IP_POOL 81
767+
768+typedef int ip_pool_t; /* pool index */
769+#define IP_POOL_NONE ((ip_pool_t)-1)
770+
771+struct ip_pool_request {
772+ int op;
773+ ip_pool_t index;
774+ u_int32_t addr;
775+ u_int32_t addr2;
776+};
777+
778+/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
779+
780+#define IP_POOL_BAD001 0x00000010
781+
782+#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
783+#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
784+#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
785+#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
786+#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
787+#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
788+#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
789+#define IP_POOL_USAGE 0x00000018 /* result in addr */
790+#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
791+
792+#ifdef __KERNEL__
793+
794+/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
795+extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
796+extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
797+
798+#endif
799+
800+#endif /*_IP_POOL_H*/
801diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h
802--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h 2004-04-28 03:35:48.000000000 +0200
803+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h 2004-04-30 09:11:53.000000000 +0200
804@@ -134,6 +134,12 @@
805 /* Back pointer */
806 unsigned int comefrom;
807
808+ /* Name of the chain */
809+ char *chainname;
810+
811+ /* Rule number in the chain. */
812+ u_int32_t rulenum;
813+
814 /* Packet and byte counters. */
815 struct ipt_counters counters;
816
817diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
818--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
819+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-30 09:11:35.000000000 +0200
820@@ -0,0 +1,25 @@
821+#ifndef _IPT_CONNMARK_H_target
822+#define _IPT_CONNMARK_H_target
823+
824+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
825+ * by Henrik Nordstrom <hno@marasystems.com>
826+ *
827+ * This program is free software; you can redistribute it and/or modify
828+ * it under the terms of the GNU General Public License as published by
829+ * the Free Software Foundation; either version 2 of the License, or
830+ * (at your option) any later version.
831+ */
832+
833+enum {
834+ IPT_CONNMARK_SET = 0,
835+ IPT_CONNMARK_SAVE,
836+ IPT_CONNMARK_RESTORE
837+};
838+
839+struct ipt_connmark_target_info {
840+ unsigned long mark;
841+ unsigned long mask;
842+ u_int8_t mode;
843+};
844+
845+#endif /*_IPT_CONNMARK_H_target*/
846diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
847--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
848+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-04-30 09:11:38.000000000 +0200
849@@ -0,0 +1,13 @@
850+#ifndef _IPT_IPMARK_H_target
851+#define _IPT_IPMARK_H_target
852+
853+struct ipt_ipmark_target_info {
854+ unsigned long andmask;
855+ unsigned long ormask;
856+ unsigned int addr;
857+};
858+
859+#define IPT_IPMARK_SRC 0
860+#define IPT_IPMARK_DST 1
861+
862+#endif /*_IPT_IPMARK_H_target*/
863diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h
864--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
865+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h 2004-04-30 09:10:09.000000000 +0200
866@@ -0,0 +1,27 @@
867+#ifndef _IPT_FWMON_H
868+#define _IPT_FWMON_H
869+
870+/* Bitmask macros */
871+#define MASK(x,y) (x & y)
872+#define MASK_SET(x,y) x |= y
873+#define MASK_UNSET(x,y) x &= ~y
874+
875+#define USE_MARK 0x00000001
876+#define USE_DROP 0x00000002
877+#define USE_SIZE 0x00000004
878+
879+struct ipt_nldata
880+{
881+ unsigned int flags;
882+ unsigned int mark;
883+ unsigned int size;
884+};
885+
886+/* Old header */
887+struct netlink_t {
888+ unsigned int len;
889+ unsigned int mark;
890+ char iface[IFNAMSIZ];
891+};
892+
893+#endif /*_IPT_FWMON_H*/
894diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h
895--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
896+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h 2004-04-30 09:10:15.000000000 +0200
897@@ -0,0 +1,21 @@
898+/* TTL modification module for IP tables
899+ * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
900+
901+#ifndef _IPT_TTL_H
902+#define _IPT_TTL_H
903+
904+enum {
905+ IPT_TTL_SET = 0,
906+ IPT_TTL_INC,
907+ IPT_TTL_DEC
908+};
909+
910+#define IPT_TTL_MAXMODE IPT_TTL_DEC
911+
912+struct ipt_TTL_info {
913+ u_int8_t mode;
914+ u_int8_t ttl;
915+};
916+
917+
918+#endif
919diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
920--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
921+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h 2004-04-30 09:11:56.000000000 +0200
922@@ -0,0 +1,9 @@
923+#ifndef _IPT_XOR_H
924+#define _IPT_XOR_H
925+
926+struct ipt_XOR_info {
927+ char key[30];
928+ u_int8_t block_size;
929+};
930+
931+#endif /* _IPT_XOR_H */
932diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
933--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
934+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-30 09:11:57.000000000 +0200
935@@ -0,0 +1,11 @@
936+#ifndef _IPT_ADDRTYPE_H
937+#define _IPT_ADDRTYPE_H
938+
939+struct ipt_addrtype_info {
940+ u_int16_t source; /* source-type mask */
941+ u_int16_t dest; /* dest-type mask */
942+ int invert_source;
943+ int invert_dest;
944+};
945+
946+#endif
947diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h
948--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
949+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-04-30 09:10:17.000000000 +0200
950@@ -0,0 +1,12 @@
951+#ifndef _IPT_CONNLIMIT_H
952+#define _IPT_CONNLIMIT_H
953+
954+struct ipt_connlimit_data;
955+
956+struct ipt_connlimit_info {
957+ int limit;
958+ int inverse;
959+ u_int32_t mask;
960+ struct ipt_connlimit_data *data;
961+};
962+#endif /* _IPT_CONNLIMIT_H */
963diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
964--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
965+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-30 09:11:35.000000000 +0200
966@@ -0,0 +1,18 @@
967+#ifndef _IPT_CONNMARK_H
968+#define _IPT_CONNMARK_H
969+
970+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
971+ * by Henrik Nordstrom <hno@marasystems.com>
972+ *
973+ * This program is free software; you can redistribute it and/or modify
974+ * it under the terms of the GNU General Public License as published by
975+ * the Free Software Foundation; either version 2 of the License, or
976+ * (at your option) any later version.
977+ */
978+
979+struct ipt_connmark_info {
980+ unsigned long mark, mask;
981+ u_int8_t invert;
982+};
983+
984+#endif /*_IPT_CONNMARK_H*/
985diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h
986--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
987+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-04-30 09:10:21.000000000 +0200
988@@ -0,0 +1,39 @@
989+#ifndef _IPT_DSTLIMIT_H
990+#define _IPT_DSTLIMIT_H
991+
992+/* timings are in milliseconds. */
993+#define IPT_DSTLIMIT_SCALE 10000
994+/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
995+ seconds, or one every 59 hours. */
996+
997+/* details of this structure hidden by the implementation */
998+struct ipt_dstlimit_htable;
999+
1000+#define IPT_DSTLIMIT_HASH_DIP 0x0001
1001+#define IPT_DSTLIMIT_HASH_DPT 0x0002
1002+#define IPT_DSTLIMIT_HASH_SIP 0x0004
1003+
1004+struct dstlimit_cfg {
1005+ u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
1006+ u_int32_t avg; /* Average secs between packets * scale */
1007+ u_int32_t burst; /* Period multiplier for upper limit. */
1008+
1009+ /* user specified */
1010+ u_int32_t size; /* how many buckets */
1011+ u_int32_t max; /* max number of entries */
1012+ u_int32_t gc_interval; /* gc interval */
1013+ u_int32_t expire; /* when do entries expire? */
1014+};
1015+
1016+struct ipt_dstlimit_info {
1017+ char name [IFNAMSIZ]; /* name */
1018+ struct dstlimit_cfg cfg;
1019+ struct ipt_dstlimit_htable *hinfo;
1020+
1021+ /* Used internally by the kernel */
1022+ union {
1023+ void *ptr;
1024+ struct ipt_dstlimit_info *master;
1025+ } u;
1026+};
1027+#endif /*_IPT_DSTLIMIT_H*/
1028diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h
1029--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1030+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-04-30 09:10:22.000000000 +0200
1031@@ -0,0 +1,21 @@
1032+#ifndef _IPT_FUZZY_H
1033+#define _IPT_FUZZY_H
1034+
1035+#include <linux/param.h>
1036+#include <linux/types.h>
1037+
1038+#define MAXFUZZYRATE 10000000
1039+#define MINFUZZYRATE 3
1040+
1041+struct ipt_fuzzy_info {
1042+ u_int32_t minimum_rate;
1043+ u_int32_t maximum_rate;
1044+ u_int32_t packets_total;
1045+ u_int32_t bytes_total;
1046+ u_int32_t previous_time;
1047+ u_int32_t present_time;
1048+ u_int32_t mean_rate;
1049+ u_int8_t acceptance_rate;
1050+};
1051+
1052+#endif /*_IPT_FUZZY_H*/
1053diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h
1054--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
1055+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-04-30 09:10:27.000000000 +0200
1056@@ -0,0 +1,21 @@
1057+#ifndef __ipt_ipv4options_h_included__
1058+#define __ipt_ipv4options_h_included__
1059+
1060+#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
1061+#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
1062+#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
1063+#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
1064+#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
1065+#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
1066+#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
1067+#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
1068+#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1069+#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
1070+#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
1071+
1072+struct ipt_ipv4options_info {
1073+ u_int16_t options;
1074+};
1075+
1076+
1077+#endif /* __ipt_ipv4options_h_included__ */
1078diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h
1079--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1080+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h 2004-04-30 09:10:30.000000000 +0200
1081@@ -0,0 +1,24 @@
1082+#ifndef _IPT_MPORT_H
1083+#define _IPT_MPORT_H
1084+#include <linux/netfilter_ipv4/ip_tables.h>
1085+
1086+#define IPT_MPORT_SOURCE (1<<0)
1087+#define IPT_MPORT_DESTINATION (1<<1)
1088+#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1089+
1090+#define IPT_MULTI_PORTS 15
1091+
1092+/* Must fit inside union ipt_matchinfo: 32 bytes */
1093+/* every entry in ports[] except for the last one has one bit in pflags
1094+ * associated with it. If this bit is set, the port is the first port of
1095+ * a portrange, with the next entry being the last.
1096+ * End of list is marked with pflags bit set and port=65535.
1097+ * If 14 ports are used (last one does not have a pflag), the last port
1098+ * is repeated to fill the last entry in ports[] */
1099+struct ipt_mport
1100+{
1101+ u_int8_t flags:2; /* Type of comparison */
1102+ u_int16_t pflags:14; /* Port flags */
1103+ u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1104+};
1105+#endif /*_IPT_MPORT_H*/
1106diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h
1107--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1108+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h 2004-04-30 09:10:36.000000000 +0200
1109@@ -0,0 +1,19 @@
1110+#ifndef _IPT_NTH_H
1111+#define _IPT_NTH_H
1112+
1113+#include <linux/param.h>
1114+#include <linux/types.h>
1115+
1116+#ifndef IPT_NTH_NUM_COUNTERS
1117+#define IPT_NTH_NUM_COUNTERS 16
1118+#endif
1119+
1120+struct ipt_nth_info {
1121+ u_int8_t every;
1122+ u_int8_t not;
1123+ u_int8_t startat;
1124+ u_int8_t counter;
1125+ u_int8_t packet;
1126+};
1127+
1128+#endif /*_IPT_NTH_H*/
1129diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h
1130--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1131+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h 2004-04-30 09:10:38.000000000 +0200
1132@@ -0,0 +1,148 @@
1133+/*
1134+ * ipt_osf.h
1135+ *
1136+ * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1137+ *
1138+ *
1139+ * This program is free software; you can redistribute it and/or modify
1140+ * it under the terms of the GNU General Public License as published by
1141+ * the Free Software Foundation; either version 2 of the License, or
1142+ * (at your option) any later version.
1143+ *
1144+ * This program is distributed in the hope that it will be useful,
1145+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1146+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1147+ * GNU General Public License for more details.
1148+ *
1149+ * You should have received a copy of the GNU General Public License
1150+ * along with this program; if not, write to the Free Software
1151+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1152+ */
1153+
1154+#ifndef _IPT_OSF_H
1155+#define _IPT_OSF_H
1156+
1157+#define MAXGENRELEN 32
1158+#define MAXDETLEN 64
1159+
1160+#define IPT_OSF_GENRE 1
1161+#define IPT_OSF_SMART 2
1162+#define IPT_OSF_LOG 4
1163+#define IPT_OSF_NETLINK 8
1164+
1165+#define IPT_OSF_LOGLEVEL_ALL 0
1166+#define IPT_OSF_LOGLEVEL_FIRST 1
1167+
1168+#include <linux/list.h>
1169+
1170+#ifndef __KERNEL__
1171+#include <netinet/ip.h>
1172+#include <netinet/tcp.h>
1173+
1174+struct list_head
1175+{
1176+ struct list_head *prev, *next;
1177+};
1178+#endif
1179+
1180+struct ipt_osf_info
1181+{
1182+ char genre[MAXGENRELEN];
1183+ int len;
1184+ unsigned long flags;
1185+ int loglevel;
1186+ int invert; /* UNSUPPORTED */
1187+};
1188+
1189+struct osf_wc
1190+{
1191+ char wc;
1192+ unsigned long val;
1193+};
1194+
1195+/* This struct represents IANA options
1196+ * http://www.iana.org/assignments/tcp-parameters
1197+ */
1198+struct osf_opt
1199+{
1200+ unsigned char kind;
1201+ unsigned char length;
1202+ struct osf_wc wc;
1203+};
1204+
1205+struct osf_finger
1206+{
1207+ struct list_head flist;
1208+ struct osf_wc wss;
1209+ unsigned char ttl;
1210+ unsigned char df;
1211+ unsigned long ss;
1212+ unsigned char genre[MAXGENRELEN];
1213+ unsigned char version[MAXGENRELEN], subtype[MAXGENRELEN];
1214+
1215+ /* Not needed, but for consistency with original table from Michal Zalewski */
1216+ unsigned char details[MAXDETLEN];
1217+
1218+ int opt_num;
1219+ struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1220+
1221+};
1222+
1223+struct ipt_osf_nlmsg
1224+{
1225+ struct osf_finger f;
1226+ struct iphdr ip;
1227+ struct tcphdr tcp;
1228+};
1229+
1230+#ifdef __KERNEL__
1231+
1232+/* Defines for IANA option kinds */
1233+
1234+#define OSFOPT_EOL 0 /* End of options */
1235+#define OSFOPT_NOP 1 /* NOP */
1236+#define OSFOPT_MSS 2 /* Maximum segment size */
1237+#define OSFOPT_WSO 3 /* Window scale option */
1238+#define OSFOPT_SACKP 4 /* SACK permitted */
1239+#define OSFOPT_SACK 5 /* SACK */
1240+#define OSFOPT_ECHO 6
1241+#define OSFOPT_ECHOREPLY 7
1242+#define OSFOPT_TS 8 /* Timestamp option */
1243+#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1244+#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1245+/* Others are not used in current OSF */
1246+
1247+static struct osf_opt IANA_opts[] =
1248+{
1249+ {0, 1,},
1250+ {1, 1,},
1251+ {2, 4,},
1252+ {3, 3,},
1253+ {4, 2,},
1254+ {5, 1 ,}, /* SACK length is not defined */
1255+ {6, 6,},
1256+ {7, 6,},
1257+ {8, 10,},
1258+ {9, 2,},
1259+ {10, 3,},
1260+ {11, 1,}, /* CC: Suppose 1 */
1261+ {12, 1,}, /* the same */
1262+ {13, 1,}, /* and here too */
1263+ {14, 3,},
1264+ {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1265+ {16, 1,},
1266+ {17, 1,},
1267+ {18, 3,},
1268+ {19, 18,},
1269+ {20, 1,},
1270+ {21, 1,},
1271+ {22, 1,},
1272+ {23, 1,},
1273+ {24, 1,},
1274+ {25, 1,},
1275+ {26, 1,},
1276+};
1277+
1278+#endif /* __KERNEL__ */
1279+
1280+#endif /* _IPT_OSF_H */
1281diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h
1282--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
1283+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h 2004-04-30 09:13:22.000000000 +0200
1284@@ -0,0 +1,52 @@
1285+#ifndef _IPT_POLICY_H
1286+#define _IPT_POLICY_H
1287+
1288+#define POLICY_MAX_ELEM 4
1289+
1290+enum ipt_policy_flags
1291+{
1292+ POLICY_MATCH_IN = 0x1,
1293+ POLICY_MATCH_OUT = 0x2,
1294+ POLICY_MATCH_NONE = 0x4,
1295+ POLICY_MATCH_STRICT = 0x8,
1296+};
1297+
1298+enum ipt_policy_modes
1299+{
1300+ POLICY_MODE_TRANSPORT,
1301+ POLICY_MODE_TUNNEL
1302+};
1303+
1304+struct ipt_policy_spec
1305+{
1306+ u_int8_t saddr:1,
1307+ daddr:1,
1308+ proto:1,
1309+ mode:1,
1310+ spi:1,
1311+ reqid:1;
1312+};
1313+
1314+struct ipt_policy_elem
1315+{
1316+ u_int32_t saddr;
1317+ u_int32_t smask;
1318+ u_int32_t daddr;
1319+ u_int32_t dmask;
1320+ u_int32_t spi;
1321+ u_int32_t reqid;
1322+ u_int8_t proto;
1323+ u_int8_t mode;
1324+
1325+ struct ipt_policy_spec match;
1326+ struct ipt_policy_spec invert;
1327+};
1328+
1329+struct ipt_policy_info
1330+{
1331+ struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1332+ u_int16_t flags;
1333+ u_int16_t len;
1334+};
1335+
1336+#endif /* _IPT_POLICY_H */
1337diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h
1338--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1339+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h 2004-04-30 09:10:40.000000000 +0200
1340@@ -0,0 +1,25 @@
1341+#ifndef _IPT_POOL_H
1342+#define _IPT_POOL_H
1343+
1344+#include <linux/netfilter_ipv4/ip_pool.h>
1345+
1346+#define IPT_POOL_INV_SRC 0x00000001
1347+#define IPT_POOL_INV_DST 0x00000002
1348+#define IPT_POOL_DEL_SRC 0x00000004
1349+#define IPT_POOL_DEL_DST 0x00000008
1350+#define IPT_POOL_INV_MOD_SRC 0x00000010
1351+#define IPT_POOL_INV_MOD_DST 0x00000020
1352+#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1353+#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1354+#define IPT_POOL_MOD_SRC_DROP 0x00000100
1355+#define IPT_POOL_MOD_DST_DROP 0x00000200
1356+
1357+/* match info */
1358+struct ipt_pool_info
1359+{
1360+ ip_pool_t src;
1361+ ip_pool_t dst;
1362+ unsigned flags;
1363+};
1364+
1365+#endif /*_IPT_POOL_H*/
1366diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h
1367--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1368+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h 2004-04-30 09:10:44.000000000 +0200
1369@@ -0,0 +1,40 @@
1370+#ifndef _IPT_PSD_H
1371+#define _IPT_PSD_H
1372+
1373+#include <linux/param.h>
1374+#include <linux/types.h>
1375+
1376+/*
1377+ * High port numbers have a lower weight to reduce the frequency of false
1378+ * positives, such as from passive mode FTP transfers.
1379+ */
1380+#define PORT_WEIGHT_PRIV 3
1381+#define PORT_WEIGHT_HIGH 1
1382+
1383+/*
1384+ * Port scan detection thresholds: at least COUNT ports need to be scanned
1385+ * from the same source, with no longer than DELAY ticks between ports.
1386+ */
1387+#define SCAN_MIN_COUNT 7
1388+#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1389+#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1390+#define SCAN_DELAY_THRESHOLD (HZ * 3)
1391+
1392+/*
1393+ * Keep track of up to LIST_SIZE source addresses, using a hash table of
1394+ * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1395+ * HASH_MAX source addresses per the same hash value.
1396+ */
1397+#define LIST_SIZE 0x100
1398+#define HASH_LOG 9
1399+#define HASH_SIZE (1 << HASH_LOG)
1400+#define HASH_MAX 0x10
1401+
1402+struct ipt_psd_info {
1403+ unsigned int weight_threshold;
1404+ unsigned int delay_threshold;
1405+ unsigned short lo_ports_weight;
1406+ unsigned short hi_ports_weight;
1407+};
1408+
1409+#endif /*_IPT_PSD_H*/
1410diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h
1411--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1412+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h 2004-04-30 09:10:45.000000000 +0200
1413@@ -0,0 +1,11 @@
1414+#ifndef _IPT_QUOTA_H
1415+#define _IPT_QUOTA_H
1416+
1417+/* print debug info in both kernel/netfilter module & iptable library */
1418+//#define DEBUG_IPT_QUOTA
1419+
1420+struct ipt_quota_info {
1421+ u_int64_t quota;
1422+};
1423+
1424+#endif /*_IPT_QUOTA_H*/
1425diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h
1426--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1427+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h 2004-04-30 09:10:46.000000000 +0200
1428@@ -0,0 +1,11 @@
1429+#ifndef _IPT_RAND_H
1430+#define _IPT_RAND_H
1431+
1432+#include <linux/param.h>
1433+#include <linux/types.h>
1434+
1435+struct ipt_rand_info {
1436+ u_int8_t average;
1437+};
1438+
1439+#endif /*_IPT_RAND_H*/
1440diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h
1441--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
1442+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h 2004-04-30 09:10:50.000000000 +0200
1443@@ -0,0 +1,9 @@
1444+#ifndef _IPT_REALM_H
1445+#define _IPT_REALM_H
1446+
1447+struct ipt_realm_info {
1448+ u_int32_t id;
1449+ u_int32_t mask;
1450+ u_int8_t invert;
1451+};
1452+#endif /*_IPT_REALM_H*/
1453diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h
1454--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
1455+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h 2004-04-30 09:10:52.000000000 +0200
1456@@ -0,0 +1,107 @@
1457+#ifndef _IPT_SCTP_H_
1458+#define _IPT_SCTP_H_
1459+
1460+#define IPT_SCTP_SRC_PORTS 0x01
1461+#define IPT_SCTP_DEST_PORTS 0x02
1462+#define IPT_SCTP_CHUNK_TYPES 0x04
1463+
1464+#define IPT_SCTP_VALID_FLAGS 0x07
1465+
1466+#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1467+
1468+
1469+struct ipt_sctp_flag_info {
1470+ u_int8_t chunktype;
1471+ u_int8_t flag;
1472+ u_int8_t flag_mask;
1473+};
1474+
1475+#define IPT_NUM_SCTP_FLAGS 4
1476+
1477+struct ipt_sctp_info {
1478+ u_int16_t dpts[2]; /* Min, Max */
1479+ u_int16_t spts[2]; /* Min, Max */
1480+
1481+ u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
1482+
1483+#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
1484+#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
1485+#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
1486+
1487+ u_int32_t chunk_match_type;
1488+ struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1489+ int flag_count;
1490+
1491+ u_int32_t flags;
1492+ u_int32_t invflags;
1493+};
1494+
1495+#define bytes(type) (sizeof(type) * 8)
1496+
1497+#define SCTP_CHUNKMAP_SET(chunkmap, type) \
1498+ do { \
1499+ chunkmap[type / bytes(u_int32_t)] |= \
1500+ 1 << (type % bytes(u_int32_t)); \
1501+ } while (0)
1502+
1503+#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
1504+ do { \
1505+ chunkmap[type / bytes(u_int32_t)] &= \
1506+ ~(1 << (type % bytes(u_int32_t))); \
1507+ } while (0)
1508+
1509+#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
1510+({ \
1511+ (chunkmap[type / bytes (u_int32_t)] & \
1512+ (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
1513+})
1514+
1515+#define SCTP_CHUNKMAP_RESET(chunkmap) \
1516+ do { \
1517+ int i; \
1518+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1519+ chunkmap[i] = 0; \
1520+ } while (0)
1521+
1522+#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
1523+ do { \
1524+ int i; \
1525+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1526+ chunkmap[i] = ~0; \
1527+ } while (0)
1528+
1529+#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
1530+ do { \
1531+ int i; \
1532+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
1533+ destmap[i] = srcmap[i]; \
1534+ } while (0)
1535+
1536+#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
1537+({ \
1538+ int i; \
1539+ int flag = 1; \
1540+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1541+ if (chunkmap[i]) { \
1542+ flag = 0; \
1543+ break; \
1544+ } \
1545+ } \
1546+ flag; \
1547+})
1548+
1549+#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
1550+({ \
1551+ int i; \
1552+ int flag = 1; \
1553+ for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
1554+ if (chunkmap[i] != ~0) { \
1555+ flag = 0; \
1556+ break; \
1557+ } \
1558+ } \
1559+ flag; \
1560+})
1561+
1562+#endif /* _IPT_SCTP_H_ */
1563+
1564diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h
1565--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
1566+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h 2004-04-30 09:14:35.000000000 +0200
1567@@ -0,0 +1,21 @@
1568+#ifndef _IPT_STRING_H
1569+#define _IPT_STRING_H
1570+
1571+/* *** PERFORMANCE TWEAK ***
1572+ * Packet size and search string threshold,
1573+ * above which sublinear searches is used. */
1574+#define IPT_STRING_HAYSTACK_THRESH 100
1575+#define IPT_STRING_NEEDLE_THRESH 20
1576+
1577+#define BM_MAX_NLEN 256
1578+#define BM_MAX_HLEN 1024
1579+
1580+typedef char *(*proc_ipt_search) (char *, char *, int, int);
1581+
1582+struct ipt_string_info {
1583+ char string[BM_MAX_NLEN];
1584+ u_int16_t invert;
1585+ u_int16_t len;
1586+};
1587+
1588+#endif /* _IPT_STRING_H */
1589diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h
1590--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1591+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h 2004-04-30 09:10:54.000000000 +0200
1592@@ -0,0 +1,13 @@
1593+#ifndef __ipt_time_h_included__
1594+#define __ipt_time_h_included__
1595+
1596+
1597+struct ipt_time_info {
1598+ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
1599+ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
1600+ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
1601+ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
1602+};
1603+
1604+
1605+#endif /* __ipt_time_h_included__ */
1606diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h
1607--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
1608+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h 2004-04-30 09:10:55.000000000 +0200
1609@@ -0,0 +1,40 @@
1610+#ifndef _IPT_U32_H
1611+#define _IPT_U32_H
1612+#include <linux/netfilter_ipv4/ip_tables.h>
1613+
1614+enum ipt_u32_ops
1615+{
1616+ IPT_U32_AND,
1617+ IPT_U32_LEFTSH,
1618+ IPT_U32_RIGHTSH,
1619+ IPT_U32_AT
1620+};
1621+
1622+struct ipt_u32_location_element
1623+{
1624+ u_int32_t number;
1625+ u_int8_t nextop;
1626+};
1627+struct ipt_u32_value_element
1628+{
1629+ u_int32_t min;
1630+ u_int32_t max;
1631+};
1632+/* *** any way to allow for an arbitrary number of elements?
1633+ for now I settle for a limit of 10 of each */
1634+#define U32MAXSIZE 10
1635+struct ipt_u32_test
1636+{
1637+ u_int8_t nnums;
1638+ struct ipt_u32_location_element location[U32MAXSIZE+1];
1639+ u_int8_t nvalues;
1640+ struct ipt_u32_value_element value[U32MAXSIZE+1];
1641+};
1642+
1643+struct ipt_u32
1644+{
1645+ u_int8_t ntests;
1646+ struct ipt_u32_test tests[U32MAXSIZE+1];
1647+};
1648+
1649+#endif /*_IPT_U32_H*/
1650diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc3/include/linux/netfilter_ipv4.h
1651--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h 2004-04-28 03:36:31.000000000 +0200
1652+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4.h 2004-04-30 09:12:40.000000000 +0200
1653@@ -7,6 +7,8 @@
1654
1655 #include <linux/config.h>
1656 #include <linux/netfilter.h>
1657+#include <linux/netdevice.h>
1658+#include <net/protocol.h>
1659
1660 /* IP Cache bits. */
1661 /* Src IP address. */
1662@@ -85,6 +87,58 @@
1663 Returns true or false. */
1664 extern int skb_ip_make_writable(struct sk_buff **pskb,
1665 unsigned int writable_len);
1666+
1667+#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1668+#include <net/route.h>
1669+#include <net/xfrm.h>
1670+
1671+static inline int nf_hook_input_cond(struct sk_buff *skb)
1672+{
1673+ return !skb->sp || skb->sp->decap_done;
1674+}
1675+
1676+static inline int
1677+nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1678+{
1679+ return skb->sp && !skb->sp->decap_done
1680+ && (!ipprot || !ipprot->xfrm_prot);
1681+}
1682+
1683+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1684+{
1685+ return skb->sp && !skb->sp->decap_done
1686+ && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1687+}
1688+
1689+extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1690+extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1691+#else /* CONFIG_XFRM */
1692+static inline int nf_hook_input_cond(struct sk_buff *skb)
1693+{
1694+ return 1;
1695+}
1696+
1697+static inline int
1698+nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1699+{
1700+ return 0;
1701+}
1702+
1703+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1704+{
1705+ return 0;
1706+}
1707+
1708+static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1709+{
1710+ return 0;
1711+}
1712+
1713+static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1714+{
1715+ return 0;
1716+}
1717+#endif /* CONFIG_XFRM */
1718 #endif /*__KERNEL__*/
1719
1720 #endif /*__LINUX_IP_NETFILTER_H*/
1721diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h
1722--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-28 03:36:37.000000000 +0200
1723+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-30 09:11:53.000000000 +0200
1724@@ -140,6 +140,12 @@
1725 /* Back pointer */
1726 unsigned int comefrom;
1727
1728+ /* Name of the chain */
1729+ char *chainname;
1730+
1731+ /* Rule number in the chain. */
1732+ u_int32_t rulenum;
1733+
1734 /* Packet and byte counters. */
1735 struct ip6t_counters counters;
1736
1737diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h
1738--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
1739+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h 2004-04-30 09:10:04.000000000 +0200
1740@@ -0,0 +1,22 @@
1741+/* Hop Limit modification module for ip6tables
1742+ * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1743+ * Based on HW's TTL module */
1744+
1745+#ifndef _IP6T_HL_H
1746+#define _IP6T_HL_H
1747+
1748+enum {
1749+ IP6T_HL_SET = 0,
1750+ IP6T_HL_INC,
1751+ IP6T_HL_DEC
1752+};
1753+
1754+#define IP6T_HL_MAXMODE IP6T_HL_DEC
1755+
1756+struct ip6t_HL_info {
1757+ u_int8_t mode;
1758+ u_int8_t hop_limit;
1759+};
1760+
1761+
1762+#endif
1763diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h
1764--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-04-28 03:34:59.000000000 +0200
1765+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-04-30 09:10:13.000000000 +0200
1766@@ -2,15 +2,17 @@
1767 #define _IP6T_REJECT_H
1768
1769 enum ip6t_reject_with {
1770- IP6T_ICMP_NET_UNREACHABLE,
1771- IP6T_ICMP_HOST_UNREACHABLE,
1772- IP6T_ICMP_PROT_UNREACHABLE,
1773- IP6T_ICMP_PORT_UNREACHABLE,
1774- IP6T_ICMP_ECHOREPLY
1775+ IP6T_ICMP6_NO_ROUTE,
1776+ IP6T_ICMP6_ADM_PROHIBITED,
1777+ IP6T_ICMP6_NOT_NEIGHBOUR,
1778+ IP6T_ICMP6_ADDR_UNREACH,
1779+ IP6T_ICMP6_PORT_UNREACH,
1780+ IP6T_ICMP6_ECHOREPLY,
1781+ IP6T_TCP_RESET
1782 };
1783
1784 struct ip6t_reject_info {
1785 enum ip6t_reject_with with; /* reject type */
1786 };
1787
1788-#endif /*_IPT_REJECT_H*/
1789+#endif /*_IP6T_REJECT_H*/
1790diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1791--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1792+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-04-30 09:10:22.000000000 +0200
1793@@ -0,0 +1,21 @@
1794+#ifndef _IP6T_FUZZY_H
1795+#define _IP6T_FUZZY_H
1796+
1797+#include <linux/param.h>
1798+#include <linux/types.h>
1799+
1800+#define MAXFUZZYRATE 10000000
1801+#define MINFUZZYRATE 3
1802+
1803+struct ip6t_fuzzy_info {
1804+ u_int32_t minimum_rate;
1805+ u_int32_t maximum_rate;
1806+ u_int32_t packets_total;
1807+ u_int32_t bytes_total;
1808+ u_int32_t previous_time;
1809+ u_int32_t present_time;
1810+ u_int32_t mean_rate;
1811+ u_int8_t acceptance_rate;
1812+};
1813+
1814+#endif /*_IP6T_FUZZY_H*/
1815diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h
1816--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1817+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h 2004-04-30 09:10:36.000000000 +0200
1818@@ -0,0 +1,19 @@
1819+#ifndef _IP6T_NTH_H
1820+#define _IP6T_NTH_H
1821+
1822+#include <linux/param.h>
1823+#include <linux/types.h>
1824+
1825+#ifndef IP6T_NTH_NUM_COUNTERS
1826+#define IP6T_NTH_NUM_COUNTERS 16
1827+#endif
1828+
1829+struct ip6t_nth_info {
1830+ u_int8_t every;
1831+ u_int8_t not;
1832+ u_int8_t startat;
1833+ u_int8_t counter;
1834+ u_int8_t packet;
1835+};
1836+
1837+#endif /*_IP6T_NTH_H*/
1838diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h
1839--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-28 03:36:03.000000000 +0200
1840+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-30 09:13:19.000000000 +0200
1841@@ -6,12 +6,14 @@
1842 #define IP6T_OWNER_GID 0x02
1843 #define IP6T_OWNER_PID 0x04
1844 #define IP6T_OWNER_SID 0x08
1845+#define IP6T_OWNER_COMM 0x10
1846
1847 struct ip6t_owner_info {
1848 uid_t uid;
1849 gid_t gid;
1850 pid_t pid;
1851 pid_t sid;
1852+ char comm[16];
1853 u_int8_t match, invert; /* flags */
1854 };
1855
1856diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h
1857--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1858+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h 2004-04-30 09:13:22.000000000 +0200
1859@@ -0,0 +1,52 @@
1860+#ifndef _IP6T_POLICY_H\r
1861+#define _IP6T_POLICY_H\r
1862+\r
1863+#define POLICY_MAX_ELEM 4\r
1864+\r
1865+enum ip6t_policy_flags\r
1866+{\r
1867+ POLICY_MATCH_IN = 0x1,\r
1868+ POLICY_MATCH_OUT = 0x2,\r
1869+ POLICY_MATCH_NONE = 0x4,\r
1870+ POLICY_MATCH_STRICT = 0x8,\r
1871+};\r
1872+\r
1873+enum ip6t_policy_modes\r
1874+{\r
1875+ POLICY_MODE_TRANSPORT,\r
1876+ POLICY_MODE_TUNNEL\r
1877+};\r
1878+\r
1879+struct ip6t_policy_spec\r
1880+{\r
1881+ u_int8_t saddr:1,\r
1882+ daddr:1,\r
1883+ proto:1,\r
1884+ mode:1,\r
1885+ spi:1,\r
1886+ reqid:1;\r
1887+};\r
1888+\r
1889+struct ip6t_policy_elem\r
1890+{\r
1891+ struct in6_addr saddr;\r
1892+ struct in6_addr smask;\r
1893+ struct in6_addr daddr;\r
1894+ struct in6_addr dmask;\r
1895+ u_int32_t spi;\r
1896+ u_int32_t reqid;\r
1897+ u_int8_t proto;\r
1898+ u_int8_t mode;\r
1899+\r
1900+ struct ip6t_policy_spec match;\r
1901+ struct ip6t_policy_spec invert;\r
1902+};\r
1903+\r
1904+struct ip6t_policy_info\r
1905+{\r
1906+ struct ip6t_policy_elem pol[POLICY_MAX_ELEM];\r
1907+ u_int16_t flags;\r
1908+ u_int16_t len;\r
1909+};\r
1910+\r
1911+#endif /* _IP6T_POLICY_H */\r
1912diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h
1913--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
1914+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h 2004-04-30 09:10:46.000000000 +0200
1915@@ -0,0 +1,11 @@
1916+#ifndef _IP6T_RAND_H
1917+#define _IP6T_RAND_H
1918+
1919+#include <linux/param.h>
1920+#include <linux/types.h>
1921+
1922+struct ip6t_rand_info {
1923+ u_int8_t average;
1924+};
1925+
1926+#endif /*_IP6T_RAND_H*/
1927diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_mime.h linux-2.6.6-rc3/include/linux/netfilter_mime.h
1928--- linux-2.6.6-rc3.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1929+++ linux-2.6.6-rc3/include/linux/netfilter_mime.h 2004-04-30 09:14:05.000000000 +0200
1930@@ -0,0 +1,89 @@
1931+/*
1932+ * MIME functions for netfilter modules. This file provides implementations
1933+ * for basic MIME parsing. MIME headers are used in many protocols, such as
1934+ * HTTP, RTSP, SIP, etc.
1935+ *
1936+ * gcc will warn for defined but unused functions, so we only include the
1937+ * functions requested. The following macros are used:
1938+ * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
1939+ */
1940+#ifndef _NETFILTER_MIME_H
1941+#define _NETFILTER_MIME_H
1942+
1943+/* Only include these functions for kernel code. */
1944+#ifdef __KERNEL__
1945+
1946+#include <linux/ctype.h>
1947+
1948+/*
1949+ * Given a buffer and length, advance to the next line and mark the current
1950+ * line. If the current line is empty, *plinelen will be set to zero. If
1951+ * not, it will be set to the actual line length (including CRLF).
1952+ *
1953+ * 'line' in this context means logical line (includes LWS continuations).
1954+ * Returns 1 on success, 0 on failure.
1955+ */
1956+#ifdef NF_NEED_MIME_NEXTLINE
1957+static int
1958+nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1959+{
1960+ uint off = *poff;
1961+ uint physlen = 0;
1962+ int is_first_line = 1;
1963+
1964+ if (off >= len)
1965+ {
1966+ return 0;
1967+ }
1968+
1969+ do
1970+ {
1971+ while (p[off] != '\n')
1972+ {
1973+ if (len-off <= 1)
1974+ {
1975+ return 0;
1976+ }
1977+
1978+ physlen++;
1979+ off++;
1980+ }
1981+
1982+ /* if we saw a crlf, physlen needs adjusted */
1983+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1984+ {
1985+ physlen--;
1986+ }
1987+
1988+ /* advance past the newline */
1989+ off++;
1990+
1991+ /* check for an empty line */
1992+ if (physlen == 0)
1993+ {
1994+ break;
1995+ }
1996+
1997+ /* check for colon on the first physical line */
1998+ if (is_first_line)
1999+ {
2000+ is_first_line = 0;
2001+ if (memchr(p+(*poff), ':', physlen) == NULL)
2002+ {
2003+ return 0;
2004+ }
2005+ }
2006+ }
2007+ while (p[off] == ' ' || p[off] == '\t');
2008+
2009+ *plineoff = *poff;
2010+ *plinelen = (physlen == 0) ? 0 : (off - *poff);
2011+ *poff = off;
2012+
2013+ return 1;
2014+}
2015+#endif /* NF_NEED_MIME_NEXTLINE */
2016+
2017+#endif /* __KERNEL__ */
2018+
2019+#endif /* _NETFILTER_MIME_H */
2020diff -Nur linux-2.6.6-rc3.org/include/linux/skbuff.h linux-2.6.6-rc3/include/linux/skbuff.h
2021--- linux-2.6.6-rc3.org/include/linux/skbuff.h 2004-04-30 08:34:16.000000000 +0200
2022+++ linux-2.6.6-rc3/include/linux/skbuff.h 2004-04-30 09:09:38.000000000 +0200
2023@@ -1049,6 +1049,14 @@
2024 if (nfct)
2025 atomic_inc(&nfct->master->use);
2026 }
2027+static inline void nf_reset(struct sk_buff *skb)
2028+{
2029+ nf_conntrack_put(skb->nfct);
2030+ skb->nfct = NULL;
2031+#ifdef CONFIG_NETFILTER_DEBUG
2032+ skb->nf_debug = 0;
2033+#endif
2034+}
2035
2036 #ifdef CONFIG_BRIDGE_NETFILTER
2037 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2038@@ -1061,9 +1069,10 @@
2039 if (nf_bridge)
2040 atomic_inc(&nf_bridge->use);
2041 }
2042-#endif
2043-
2044-#endif
2045+#endif /* CONFIG_BRIDGE_NETFILTER */
2046+#else /* CONFIG_NETFILTER */
2047+static inline void nf_reset(struct sk_buff *skb) {}
2048+#endif /* CONFIG_NETFILTER */
2049
2050 #endif /* __KERNEL__ */
2051 #endif /* _LINUX_SKBUFF_H */
2052diff -Nur linux-2.6.6-rc3.org/include/net/ip.h linux-2.6.6-rc3/include/net/ip.h
2053--- linux-2.6.6-rc3.org/include/net/ip.h 2004-04-28 03:36:16.000000000 +0200
2054+++ linux-2.6.6-rc3/include/net/ip.h 2004-04-30 09:12:39.000000000 +0200
2055@@ -30,6 +30,8 @@
2056 #include <linux/netdevice.h>
2057 #include <linux/inetdevice.h>
2058 #include <linux/in_route.h>
2059+#include <linux/netfilter.h>
2060+#include <linux/netfilter_ipv4.h>
2061 #include <net/route.h>
2062 #include <net/arp.h>
2063
2064@@ -48,6 +50,7 @@
2065 #define IPSKB_TRANSLATED 2
2066 #define IPSKB_FORWARDED 4
2067 #define IPSKB_XFRM_TUNNEL_SIZE 8
2068+#define IPSKB_XFRM_TRANSFORMED 16
2069 };
2070
2071 struct ipcm_cookie
2072@@ -212,6 +215,12 @@
2073 __ip_select_ident(iph, dst, more);
2074 }
2075
2076+extern inline int ip_dst_output(struct sk_buff *skb)
2077+{
2078+ return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2079+ skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2080+}
2081+
2082 /*
2083 * Map a multicast IP onto multicast MAC for type ethernet.
2084 */
2085diff -Nur linux-2.6.6-rc3.org/include/net/protocol.h linux-2.6.6-rc3/include/net/protocol.h
2086--- linux-2.6.6-rc3.org/include/net/protocol.h 2004-04-28 03:35:44.000000000 +0200
2087+++ linux-2.6.6-rc3/include/net/protocol.h 2004-04-30 09:12:40.000000000 +0200
2088@@ -39,6 +39,7 @@
2089 int (*handler)(struct sk_buff *skb);
2090 void (*err_handler)(struct sk_buff *skb, u32 info);
2091 int no_policy;
2092+ int xfrm_prot;
2093 };
2094
2095 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2096diff -Nur linux-2.6.6-rc3.org/include/net/tcp.h linux-2.6.6-rc3/include/net/tcp.h
2097--- linux-2.6.6-rc3.org/include/net/tcp.h 2004-04-30 08:34:16.000000000 +0200
2098+++ linux-2.6.6-rc3/include/net/tcp.h 2004-04-30 09:13:14.000000000 +0200
2099@@ -162,6 +162,7 @@
2100 extern void tcp_bucket_unlock(struct sock *sk);
2101 extern int tcp_port_rover;
2102 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2103+extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2104
2105 /* These are AF independent. */
2106 static __inline__ int tcp_bhashfn(__u16 lport)
2107diff -Nur linux-2.6.6-rc3.org/include/net/udp.h linux-2.6.6-rc3/include/net/udp.h
2108--- linux-2.6.6-rc3.org/include/net/udp.h 2004-04-28 03:36:29.000000000 +0200
2109+++ linux-2.6.6-rc3/include/net/udp.h 2004-04-30 09:13:14.000000000 +0200
2110@@ -74,6 +74,8 @@
2111 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2112 extern int udp_disconnect(struct sock *sk, int flags);
2113
2114+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2115+
2116 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2117 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
2118 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
2119diff -Nur linux-2.6.6-rc3.org/include/net/xfrm.h linux-2.6.6-rc3/include/net/xfrm.h
2120--- linux-2.6.6-rc3.org/include/net/xfrm.h 2004-04-28 03:36:31.000000000 +0200
2121+++ linux-2.6.6-rc3/include/net/xfrm.h 2004-04-30 09:12:40.000000000 +0200
2122@@ -540,6 +540,9 @@
2123 {
2124 atomic_t refcnt;
2125 int len;
2126+#ifdef CONFIG_NETFILTER
2127+ int decap_done;
2128+#endif
2129 struct sec_decap_state x[XFRM_MAX_DEPTH];
2130 };
2131
2132diff -Nur linux-2.6.6-rc3.org/net/core/netfilter.c linux-2.6.6-rc3/net/core/netfilter.c
2133--- linux-2.6.6-rc3.org/net/core/netfilter.c 2004-04-28 03:35:46.000000000 +0200
2134+++ linux-2.6.6-rc3/net/core/netfilter.c 2004-04-30 09:12:42.000000000 +0200
2135@@ -27,6 +27,8 @@
2136 #include <linux/icmp.h>
2137 #include <net/sock.h>
2138 #include <net/route.h>
2139+#include <net/xfrm.h>
2140+#include <net/ip.h>
2141 #include <linux/ip.h>
2142
2143 /* In this code, we can be waiting indefinitely for userspace to
2144@@ -638,7 +640,6 @@
2145 #ifdef CONFIG_IP_ROUTE_FWMARK
2146 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2147 #endif
2148- fl.proto = iph->protocol;
2149 if (ip_route_output_key(&rt, &fl) != 0)
2150 return -1;
2151
2152@@ -665,6 +666,20 @@
2153 if ((*pskb)->dst->error)
2154 return -1;
2155
2156+#ifdef CONFIG_XFRM
2157+ if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2158+ struct xfrm_policy_afinfo *afinfo;
2159+
2160+ afinfo = xfrm_policy_get_afinfo(AF_INET);
2161+ if (afinfo != NULL) {
2162+ afinfo->decode_session(*pskb, &fl);
2163+ xfrm_policy_put_afinfo(afinfo);
2164+ if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2165+ return -1;
2166+ }
2167+ }
2168+#endif
2169+
2170 /* Change in oif may mean change in hh_len. */
2171 hh_len = (*pskb)->dst->dev->hard_header_len;
2172 if (skb_headroom(*pskb) < hh_len) {
2173@@ -682,6 +697,71 @@
2174 return 0;
2175 }
2176
2177+#ifdef CONFIG_XFRM
2178+inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2179+{
2180+ skb->sp->decap_done = 1;
2181+ dst_release(skb->dst);
2182+ skb->dst = NULL;
2183+ nf_reset(skb);
2184+ return netif_rx(skb);
2185+}
2186+
2187+int nf_rcv_postxfrm_local(struct sk_buff *skb)
2188+{
2189+ __skb_push(skb, skb->data - skb->nh.raw);
2190+ /* Fix header len and checksum if last xfrm was transport mode */
2191+ if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2192+ skb->nh.iph->tot_len = htons(skb->len);
2193+ ip_send_check(skb->nh.iph);
2194+ }
2195+ return nf_rcv_postxfrm_nonlocal(skb);
2196+}
2197+
2198+#ifdef CONFIG_IP_NF_NAT_NEEDED
2199+#include <linux/netfilter_ipv4/ip_conntrack.h>
2200+#include <linux/netfilter_ipv4/ip_nat.h>
2201+
2202+void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2203+{
2204+ struct ip_conntrack *ct;
2205+ struct ip_conntrack_tuple *t;
2206+ struct ip_nat_info_manip *m;
2207+ unsigned int i;
2208+
2209+ if (skb->nfct == NULL)
2210+ return;
2211+ ct = (struct ip_conntrack *)skb->nfct->master;
2212+
2213+ for (i = 0; i < ct->nat.info.num_manips; i++) {
2214+ m = &ct->nat.info.manips[i];
2215+ t = &ct->tuplehash[m->direction].tuple;
2216+
2217+ switch (m->hooknum) {
2218+ case NF_IP_PRE_ROUTING:
2219+ if (m->maniptype != IP_NAT_MANIP_DST)
2220+ break;
2221+ fl->fl4_dst = t->dst.ip;
2222+ if (t->dst.protonum == IPPROTO_TCP ||
2223+ t->dst.protonum == IPPROTO_UDP)
2224+ fl->fl_ip_dport = t->dst.u.tcp.port;
2225+ break;
2226+#ifdef CONFIG_IP_NF_NAT_LOCAL
2227+ case NF_IP_LOCAL_IN:
2228+ if (m->maniptype != IP_NAT_MANIP_SRC)
2229+ break;
2230+ fl->fl4_src = t->src.ip;
2231+ if (t->dst.protonum == IPPROTO_TCP ||
2232+ t->dst.protonum == IPPROTO_UDP)
2233+ fl->fl_ip_sport = t->src.u.tcp.port;
2234+ break;
2235+#endif
2236+ }
2237+ }
2238+}
2239+#endif /* CONFIG_IP_NF_NAT_NEEDED */
2240+#endif
2241+
2242 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2243 {
2244 struct sk_buff *nskb;
2245@@ -839,3 +919,4 @@
2246 EXPORT_SYMBOL(nf_unregister_hook);
2247 EXPORT_SYMBOL(nf_unregister_queue_handler);
2248 EXPORT_SYMBOL(nf_unregister_sockopt);
2249+EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2250diff -Nur linux-2.6.6-rc3.org/net/ipv4/ah4.c linux-2.6.6-rc3/net/ipv4/ah4.c
2251--- linux-2.6.6-rc3.org/net/ipv4/ah4.c 2004-04-28 03:36:34.000000000 +0200
2252+++ linux-2.6.6-rc3/net/ipv4/ah4.c 2004-04-30 09:12:40.000000000 +0200
2253@@ -145,6 +145,7 @@
2254 err = -EHOSTUNREACH;
2255 goto error_nolock;
2256 }
2257+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2258 return NET_XMIT_BYPASS;
2259
2260 error:
2261@@ -343,6 +344,7 @@
2262 .handler = xfrm4_rcv,
2263 .err_handler = ah4_err,
2264 .no_policy = 1,
2265+ .xfrm_prot = 1,
2266 };
2267
2268 static int __init ah4_init(void)
2269diff -Nur linux-2.6.6-rc3.org/net/ipv4/esp4.c linux-2.6.6-rc3/net/ipv4/esp4.c
2270--- linux-2.6.6-rc3.org/net/ipv4/esp4.c 2004-04-28 03:36:01.000000000 +0200
2271+++ linux-2.6.6-rc3/net/ipv4/esp4.c 2004-04-30 09:12:40.000000000 +0200
2272@@ -216,6 +216,7 @@
2273 err = -EHOSTUNREACH;
2274 goto error_nolock;
2275 }
2276+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2277 return NET_XMIT_BYPASS;
2278
2279 error:
2280@@ -598,6 +599,7 @@
2281 .handler = xfrm4_rcv,
2282 .err_handler = esp4_err,
2283 .no_policy = 1,
2284+ .xfrm_prot = 1,
2285 };
2286
2287 static int __init esp4_init(void)
2288diff -Nur linux-2.6.6-rc3.org/net/ipv4/igmp.c linux-2.6.6-rc3/net/ipv4/igmp.c
2289--- linux-2.6.6-rc3.org/net/ipv4/igmp.c 2004-04-28 03:36:55.000000000 +0200
2290+++ linux-2.6.6-rc3/net/ipv4/igmp.c 2004-04-30 09:12:39.000000000 +0200
2291@@ -342,7 +342,7 @@
2292 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2293
2294 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2295- dst_output);
2296+ ip_dst_output);
2297 }
2298
2299 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2300@@ -672,7 +672,7 @@
2301 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2302
2303 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2304- dst_output);
2305+ ip_dst_output);
2306 }
2307
2308 static void igmp_gq_timer_expire(unsigned long data)
2309diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_forward.c linux-2.6.6-rc3/net/ipv4/ip_forward.c
2310--- linux-2.6.6-rc3.org/net/ipv4/ip_forward.c 2004-04-28 03:34:59.000000000 +0200
2311+++ linux-2.6.6-rc3/net/ipv4/ip_forward.c 2004-04-30 09:12:39.000000000 +0200
2312@@ -51,7 +51,7 @@
2313 if (unlikely(opt->optlen))
2314 ip_forward_options(skb);
2315
2316- return dst_output(skb);
2317+ return ip_dst_output(skb);
2318 }
2319
2320 int ip_forward(struct sk_buff *skb)
2321diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_gre.c linux-2.6.6-rc3/net/ipv4/ip_gre.c
2322--- linux-2.6.6-rc3.org/net/ipv4/ip_gre.c 2004-04-28 03:36:22.000000000 +0200
2323+++ linux-2.6.6-rc3/net/ipv4/ip_gre.c 2004-04-30 09:09:38.000000000 +0200
2324@@ -643,13 +643,7 @@
2325 skb->dev = tunnel->dev;
2326 dst_release(skb->dst);
2327 skb->dst = NULL;
2328-#ifdef CONFIG_NETFILTER
2329- nf_conntrack_put(skb->nfct);
2330- skb->nfct = NULL;
2331-#ifdef CONFIG_NETFILTER_DEBUG
2332- skb->nf_debug = 0;
2333-#endif
2334-#endif
2335+ nf_reset(skb);
2336 ipgre_ecn_decapsulate(iph, skb);
2337 netif_rx(skb);
2338 read_unlock(&ipgre_lock);
2339@@ -877,13 +871,7 @@
2340 }
2341 }
2342
2343-#ifdef CONFIG_NETFILTER
2344- nf_conntrack_put(skb->nfct);
2345- skb->nfct = NULL;
2346-#ifdef CONFIG_NETFILTER_DEBUG
2347- skb->nf_debug = 0;
2348-#endif
2349-#endif
2350+ nf_reset(skb);
2351
2352 IPTUNNEL_XMIT();
2353 tunnel->recursion--;
2354diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
2355--- linux-2.6.6-rc3.org/net/ipv4/ip_input.c 2004-04-28 03:35:06.000000000 +0200
2356+++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-30 09:12:42.000000000 +0200
2357@@ -202,18 +202,10 @@
2358
2359 #ifdef CONFIG_NETFILTER_DEBUG
2360 nf_debug_ip_local_deliver(skb);
2361- skb->nf_debug = 0;
2362 #endif /*CONFIG_NETFILTER_DEBUG*/
2363
2364 __skb_pull(skb, ihl);
2365
2366-#ifdef CONFIG_NETFILTER
2367- /* Free reference early: we don't need it any more, and it may
2368- hold ip_conntrack module loaded indefinitely. */
2369- nf_conntrack_put(skb->nfct);
2370- skb->nfct = NULL;
2371-#endif /*CONFIG_NETFILTER*/
2372-
2373 /* Point into the IP datagram, just past the header. */
2374 skb->h.raw = skb->data;
2375
2376@@ -228,6 +220,13 @@
2377 resubmit:
2378 hash = protocol & (MAX_INET_PROTOS - 1);
2379 raw_sk = sk_head(&raw_v4_htable[hash]);
2380+ ipprot = inet_protos[hash];
2381+ smp_read_barrier_depends();
2382+
2383+ if (nf_xfrm_local_done(skb, ipprot)) {
2384+ nf_rcv_postxfrm_local(skb);
2385+ goto out;
2386+ }
2387
2388 /* If there maybe a raw socket we must check - if not we
2389 * don't care less
2390@@ -235,14 +234,15 @@
2391 if (raw_sk)
2392 raw_v4_input(skb, skb->nh.iph, hash);
2393
2394- if ((ipprot = inet_protos[hash]) != NULL) {
2395+ if (ipprot != NULL) {
2396 int ret;
2397
2398- smp_read_barrier_depends();
2399- if (!ipprot->no_policy &&
2400- !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2401- kfree_skb(skb);
2402- goto out;
2403+ if (!ipprot->no_policy) {
2404+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2405+ kfree_skb(skb);
2406+ goto out;
2407+ }
2408+ nf_reset(skb);
2409 }
2410 ret = ipprot->handler(skb);
2411 if (ret < 0) {
2412@@ -283,8 +283,8 @@
2413 return 0;
2414 }
2415
2416- return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2417- ip_local_deliver_finish);
2418+ return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2419+ ip_local_deliver_finish, nf_hook_input_cond(skb));
2420 }
2421
2422 static inline int ip_rcv_finish(struct sk_buff *skb)
2423@@ -301,6 +301,9 @@
2424 goto drop;
2425 }
2426
2427+ if (nf_xfrm_nonlocal_done(skb))
2428+ return nf_rcv_postxfrm_nonlocal(skb);
2429+
2430 #ifdef CONFIG_NET_CLS_ROUTE
2431 if (skb->dst->tclassid) {
2432 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2433@@ -422,8 +425,8 @@
2434 }
2435 }
2436
2437- return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2438- ip_rcv_finish);
2439+ return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2440+ ip_rcv_finish, nf_hook_input_cond(skb));
2441
2442 inhdr_error:
2443 IP_INC_STATS_BH(IpInHdrErrors);
2444diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_output.c linux-2.6.6-rc3/net/ipv4/ip_output.c
2445--- linux-2.6.6-rc3.org/net/ipv4/ip_output.c 2004-04-28 03:36:55.000000000 +0200
2446+++ linux-2.6.6-rc3/net/ipv4/ip_output.c 2004-04-30 09:12:39.000000000 +0200
2447@@ -123,6 +123,15 @@
2448 return ttl;
2449 }
2450
2451+#ifdef CONFIG_NETFILTER
2452+/* out-of-line copy is only required with netfilter */
2453+int ip_dst_output(struct sk_buff *skb)
2454+{
2455+ return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2456+ skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2457+}
2458+#endif
2459+
2460 /*
2461 * Add an ip header to a skbuff and send it out.
2462 *
2463@@ -165,7 +174,7 @@
2464
2465 /* Send it out. */
2466 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2467- dst_output);
2468+ ip_dst_output);
2469 }
2470
2471 static inline int ip_finish_output2(struct sk_buff *skb)
2472@@ -283,7 +292,7 @@
2473 return ip_finish_output(skb);
2474 }
2475
2476-int ip_output(struct sk_buff *skb)
2477+static inline int ip_output2(struct sk_buff *skb)
2478 {
2479 IP_INC_STATS(IpOutRequests);
2480
2481@@ -294,6 +303,16 @@
2482 return ip_finish_output(skb);
2483 }
2484
2485+int ip_output(struct sk_buff *skb)
2486+{
2487+ int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2488+
2489+ if (transformed)
2490+ nf_reset(skb);
2491+ return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2492+ skb->dst->dev, ip_output2, transformed);
2493+}
2494+
2495 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2496 {
2497 struct sock *sk = skb->sk;
2498@@ -387,7 +406,7 @@
2499 skb->priority = sk->sk_priority;
2500
2501 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2502- dst_output);
2503+ ip_dst_output);
2504
2505 no_route:
2506 IP_INC_STATS(IpOutNoRoutes);
2507@@ -1177,7 +1196,7 @@
2508
2509 /* Netfilter gets whole the not fragmented skb. */
2510 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2511- skb->dst->dev, dst_output);
2512+ skb->dst->dev, ip_dst_output);
2513 if (err) {
2514 if (err > 0)
2515 err = inet->recverr ? net_xmit_errno(err) : 0;
2516diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipcomp.c linux-2.6.6-rc3/net/ipv4/ipcomp.c
2517--- linux-2.6.6-rc3.org/net/ipv4/ipcomp.c 2004-04-28 03:36:33.000000000 +0200
2518+++ linux-2.6.6-rc3/net/ipv4/ipcomp.c 2004-04-30 09:12:40.000000000 +0200
2519@@ -231,6 +231,7 @@
2520 err = -EHOSTUNREACH;
2521 goto error_nolock;
2522 }
2523+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2524 err = NET_XMIT_BYPASS;
2525
2526 out_exit:
2527@@ -407,6 +408,7 @@
2528 .handler = xfrm4_rcv,
2529 .err_handler = ipcomp4_err,
2530 .no_policy = 1,
2531+ .xfrm_prot = 1,
2532 };
2533
2534 static int __init ipcomp4_init(void)
2535diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
2536--- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-28 03:37:06.000000000 +0200
2537+++ linux-2.6.6-rc3/net/ipv4/ipip.c 2004-04-30 09:12:40.000000000 +0200
2538@@ -478,6 +478,11 @@
2539
2540 read_lock(&ipip_lock);
2541 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2542+ /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2543+ if (nf_xfrm_local_done(skb, NULL)) {
2544+ nf_rcv_postxfrm_local(skb);
2545+ return 0;
2546+ }
2547 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2548 kfree_skb(skb);
2549 return 0;
2550@@ -496,13 +501,7 @@
2551 skb->dev = tunnel->dev;
2552 dst_release(skb->dst);
2553 skb->dst = NULL;
2554-#ifdef CONFIG_NETFILTER
2555- nf_conntrack_put(skb->nfct);
2556- skb->nfct = NULL;
2557-#ifdef CONFIG_NETFILTER_DEBUG
2558- skb->nf_debug = 0;
2559-#endif
2560-#endif
2561+ nf_reset(skb);
2562 ipip_ecn_decapsulate(iph, skb);
2563 netif_rx(skb);
2564 read_unlock(&ipip_lock);
2565@@ -647,13 +646,7 @@
2566 if ((iph->ttl = tiph->ttl) == 0)
2567 iph->ttl = old_iph->ttl;
2568
2569-#ifdef CONFIG_NETFILTER
2570- nf_conntrack_put(skb->nfct);
2571- skb->nfct = NULL;
2572-#ifdef CONFIG_NETFILTER_DEBUG
2573- skb->nf_debug = 0;
2574-#endif
2575-#endif
2576+ nf_reset(skb);
2577
2578 IPTUNNEL_XMIT();
2579 tunnel->recursion--;
2580diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipmr.c linux-2.6.6-rc3/net/ipv4/ipmr.c
2581--- linux-2.6.6-rc3.org/net/ipv4/ipmr.c 2004-04-28 03:35:47.000000000 +0200
2582+++ linux-2.6.6-rc3/net/ipv4/ipmr.c 2004-04-30 09:12:39.000000000 +0200
2583@@ -1120,7 +1120,7 @@
2584 if (unlikely(opt->optlen))
2585 ip_forward_options(skb);
2586
2587- return dst_output(skb);
2588+ return ip_dst_output(skb);
2589 }
2590
2591 /*
2592diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
2593--- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig 2004-04-28 03:36:31.000000000 +0200
2594+++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig 2004-04-30 09:14:39.000000000 +0200
2595@@ -206,6 +206,11 @@
2596
2597 To compile it as a module, choose M here. If unsure, say N.
2598
2599+config IP_NF_MATCH_UNCLEAN
2600+ tristate 'unclean match support (EXPERIMENTAL)'
2601+ depends on EXPERIMENTAL && IP_NF_IPTABLES
2602+ help
2603+
2604 config IP_NF_MATCH_TTL
2605 tristate "TTL match support"
2606 depends on IP_NF_IPTABLES
2607@@ -603,5 +608,227 @@
2608 <file:Documentation/modules.txt>. If unsure, say `N'.
2609 help
2610
2611+config IP_NF_TARGET_IPV4OPTSSTRIP
2612+ tristate 'IPV4OPTSSTRIP target support'
2613+ depends on IP_NF_MANGLE
2614+ help
2615+
2616+config IP_NF_TARGET_NETLINK
2617+ tristate 'NETLINK target support'
2618+ depends on IP_NF_FILTER
2619+ help
2620+
2621+config IP_NF_TARGET_TTL
2622+ tristate 'TTL target support'
2623+ depends on IP_NF_MANGLE
2624+ help
2625+
2626+config IP_NF_MATCH_CONNLIMIT
2627+ tristate 'Connections/IP limit match support'
2628+ depends on IP_NF_IPTABLES
2629+ help
2630+
2631+config IP_NF_MATCH_DSTLIMIT
2632+ tristate 'dstlimit match support'
2633+ depends on IP_NF_IPTABLES
2634+ help
2635+
2636+config IP_NF_MATCH_FUZZY
2637+ tristate 'fuzzy match support'
2638+ depends on IP_NF_IPTABLES
2639+ help
2640+
2641+config IP_NF_MATCH_IPV4OPTIONS
2642+ tristate 'IPV4OPTIONS match support'
2643+ depends on IP_NF_IPTABLES
2644+ help
2645+
2646+config IP_NF_MATCH_MPORT
2647+ tristate 'Multiple port with ranges match support'
2648+ depends on IP_NF_IPTABLES
2649+ help
2650+
2651+config IP_NF_MATCH_NTH
2652+ tristate 'Nth match support'
2653+ depends on IP_NF_IPTABLES
2654+ help
2655+
2656+config IP_NF_MATCH_OSF
2657+ tristate 'OSF match support'
2658+ depends on IP_NF_IPTABLES
2659+ help
2660+
2661+config IP_POOL_STATISTICS
2662+ bool 'enable statistics on pool usage'
2663+ depends on IP_NF_POOL!=n
2664+
2665+config IP_NF_POOL
2666+ tristate 'IP address pool support'
2667+ depends on IP_NF_IPTABLES
2668+ help
2669+
2670+config IP_NF_MATCH_PSD
2671+ tristate 'psd match support'
2672+ depends on IP_NF_IPTABLES
2673+ help
2674+
2675+config IP_NF_MATCH_QUOTA
2676+ tristate 'quota match support'
2677+ depends on IP_NF_IPTABLES
2678+ help
2679+
2680+config IP_NF_MATCH_RANDOM
2681+ tristate 'random match support'
2682+ depends on IP_NF_IPTABLES
2683+ help
2684+
2685+config IP_NF_MATCH_REALM
2686+ tristate 'realm match support'
2687+ depends on IP_NF_IPTABLES && NET_CLS_ROUTE
2688+ help
2689+
2690+config IP_NF_MATCH_SCTP
2691+ tristate 'SCTP protocol match support'
2692+ depends on IP_NF_IPTABLES
2693+ help
2694+
2695+config IP_NF_MATCH_TIME
2696+ tristate 'TIME match support'
2697+ depends on IP_NF_IPTABLES
2698+ help
2699+
2700+config IP_NF_MATCH_U32
2701+ tristate 'U32 match support'
2702+ depends on IP_NF_IPTABLES
2703+ help
2704+
2705+config IP_NF_CONNTRACK_MARK
2706+ bool 'Connection mark tracking support'
2707+config IP_NF_TARGET_CONNMARK
2708+ tristate 'CONNMARK target support'
2709+ depends on IP_NF_MANGLE
2710+config IP_NF_MATCH_CONNMARK
2711+ tristate ' Connection mark match support'
2712+ depends on IP_NF_IPTABLES
2713+ help
2714+
2715+config IP_NF_TARGET_IPMARK
2716+ tristate 'IPMARK target support'
2717+ depends on IP_NF_MANGLE
2718+ help
2719+
2720+config IP_NF_TARGET_TARPIT
2721+ tristate 'TARPIT target support'
2722+ depends on IP_NF_FILTER
2723+ help
2724+
2725+config IP_NF_TARGET_TRACE
2726+ tristate 'TRACE target support'
2727+ depends on IP_NF_RAW
2728+ help
2729+ The TRACE target allows packets to be traced as those
2730+ matches any subsequent rule in any table/rule. The matched
2731+ rule and the packet is logged with the prefix
2732+
2733+ TRACE: tablename/chainname/rulenum
2734+
2735+ If you want to compile it as a module, say M here and read
2736+ <file:Documentation/modules.txt>. If unsure, say `N'.
2737+ help
2738+
2739+config IP_NF_TARGET_XOR
2740+ tristate 'XOR target support'
2741+ depends on IP_NF_MANGLE
2742+ help
2743+
2744+config IP_NF_MATCH_ADDRTYPE
2745+ tristate 'address type match support'
2746+ depends on IP_NF_IPTABLES
2747+ help
2748+
2749+config IP_NF_EGG
2750+ tristate 'Eggdrop bot support'
2751+ depends on IP_NF_CONNTRACK
2752+ help
2753+
2754+config IP_NF_NAT_H323
2755+ tristate
2756+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2757+ default IP_NF_NAT if IP_NF_H323=y
2758+ default m if IP_NF_H323=m
2759+
2760+config IP_NF_H323
2761+ tristate 'H.323 (netmeeting) support'
2762+ depends on IP_NF_CONNTRACK
2763+ help
2764+
2765+config IP_NF_NAT_MMS
2766+ tristate
2767+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2768+ default IP_NF_NAT if IP_NF_MMS=y
2769+ default m if IP_NF_MMS=m
2770+
2771+config IP_NF_MMS
2772+ tristate 'MMS protocol support'
2773+ depends on IP_NF_CONNTRACK
2774+ help
2775+
2776+config IP_NF_MATCH_POLICY
2777+ tristate "IPsec policy match support"
2778+ depends on IP_NF_IPTABLES && XFRM
2779+ help
2780+ Policy matching allows you to match packets based on the
2781+ IPsec policy that was used during decapsulation/will
2782+ be used during encapsulation.
2783+
2784+ To compile it as a module, choose M here. If unsure, say N.
2785+ help
2786+
2787+config IP_NF_NAT_QUAKE3
2788+ tristate
2789+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
2790+ default IP_NF_NAT if IP_NF_QUAKE3=y
2791+ default m if IP_NF_QUAKE3=m
2792+
2793+config IP_NF_QUAKE3
2794+ tristate "Quake3 protocol support"
2795+ depends on IP_NF_CONNTRACK
2796+ help
2797+
2798+config IP_NF_RSH
2799+ tristate 'RSH protocol support'
2800+ depends on IP_NF_CONNTRACK
2801+ help
2802+
2803+config IP_NF_NAT_RTSP
2804+ tristate
2805+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2806+ default IP_NF_NAT if IP_NF_RTSP=y
2807+ default m if IP_NF_RTSP=m
2808+config IP_NF_RTSP
2809+ tristate ' RTSP protocol support'
2810+ depends on IP_NF_CONNTRACK
2811+ help
2812+
2813+config IP_NF_CT_PROTO_SCTP
2814+ tristate 'SCTP protocol connection tracking support'
2815+ depends on IP_NF_CONNTRACK
2816+ help
2817+
2818+config IP_NF_MATCH_STRING
2819+ tristate 'String match support'
2820+ depends on IP_NF_IPTABLES
2821+ help
2822+
2823+config IP_NF_NAT_TALK
2824+ tristate
2825+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2826+ default IP_NF_NAT if IP_NF_TALK=y
2827+ default m if IP_NF_TALK=m
2828+config IP_NF_TALK
2829+ tristate 'talk protocol support'
2830+ depends on IP_NF_CONNTRACK
2831+ help
2832+
2833 endmenu
2834
2835diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
2836--- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile 2004-04-28 03:35:21.000000000 +0200
2837+++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-30 09:14:39.000000000 +0200
2838@@ -19,10 +19,34 @@
2839 # connection tracking
2840 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
2841
2842+# talk protocol support
2843+obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
2844+obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
2845+
2846+
2847+# SCTP protocol connection tracking
2848+obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
2849+
2850+# H.323 support
2851+obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
2852+obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
2853+
2854+
2855 # connection tracking helpers
2856+
2857+# rtsp protocol support
2858+obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
2859+obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
2860+
2861+obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
2862+obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
2863 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
2864 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
2865 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
2866+obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
2867+
2868+obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
2869+
2870 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
2871
2872 # NAT helpers
2873@@ -30,6 +69,8 @@
2874 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
2875 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
2876 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
2877+obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
2878+obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
2879
2880 # generic IP tables
2881 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
2882@@ -43,15 +84,39 @@
2883 # matches
2884 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
2885 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
2886+obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
2887+obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
2888+obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
2889 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
2890+obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
2891 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
2892 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
2893
2894 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
2895 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
2896+
2897+obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
2898+
2899 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
2900 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
2901
2902+obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
2903+
2904+
2905+obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
2906+
2907+obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
2908+
2909+obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
2910+
2911+
2912+obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
2913+
2914+obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
2915+
2916+
2917+obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
2918+
2919 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
2920
2921 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
2922@@ -60,12 +125,22 @@
2923
2924 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
2925
2926+obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
2927+
2928+
2929+obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
2930+obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
2931 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
2932 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
2933+obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
2934+obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
2935 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
2936 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
2937+obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
2938+obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
2939
2940 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
2941+obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
2942
2943 # targets
2944 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
2945@@ -73,6 +148,8 @@
2946 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
2947 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
2948 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
2949+obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
2950+obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
2951 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
2952 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
2953 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
2954@@ -80,8 +157,14 @@
2955 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
2956 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
2957 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
2958+obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
2959+obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
2960+obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
2961+obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
2962+obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
2963 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
2964 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
2965+obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
2966 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
2967
2968 # generic ARP tables
2969diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c
2970--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-28 03:34:58.000000000 +0200
2971+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-30 09:11:35.000000000 +0200
2972@@ -324,8 +324,9 @@
2973 ip_conntrack_destroyed(ct);
2974
2975 WRITE_LOCK(&ip_conntrack_lock);
2976- /* Delete us from our own list to prevent corruption later */
2977- list_del(&ct->sibling_list);
2978+ /* Make sure don't leave any orphaned expectations lying around */
2979+ if (ct->expecting)
2980+ remove_expectations(ct, 1);
2981
2982 /* Delete our master expectation */
2983 if (ct->master) {
2984@@ -692,42 +693,53 @@
2985 struct ip_conntrack_expect *, tuple);
2986 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
2987
2988- /* If master is not in hash table yet (ie. packet hasn't left
2989- this machine yet), how can other end know about expected?
2990- Hence these are not the droids you are looking for (if
2991- master ct never got confirmed, we'd hold a reference to it
2992- and weird things would happen to future packets). */
2993- if (expected && !is_confirmed(expected->expectant))
2994- expected = NULL;
2995-
2996- /* Look up the conntrack helper for master connections only */
2997- if (!expected)
2998- conntrack->helper = ip_ct_find_helper(&repl_tuple);
2999-
3000- /* If the expectation is dying, then this is a loser. */
3001- if (expected
3002- && expected->expectant->helper->timeout
3003- && ! del_timer(&expected->timeout))
3004- expected = NULL;
3005-
3006 if (expected) {
3007- DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3008- conntrack, expected);
3009- /* Welcome, Mr. Bond. We've been expecting you... */
3010- IP_NF_ASSERT(master_ct(conntrack));
3011- __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3012- conntrack->master = expected;
3013- expected->sibling = conntrack;
3014- LIST_DELETE(&ip_conntrack_expect_list, expected);
3015- expected->expectant->expecting--;
3016- nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3017- }
3018- atomic_inc(&ip_conntrack_count);
3019+ /* If master is not in hash table yet (ie. packet hasn't left
3020+ this machine yet), how can other end know about expected?
3021+ Hence these are not the droids you are looking for (if
3022+ master ct never got confirmed, we'd hold a reference to it
3023+ and weird things would happen to future packets). */
3024+ if (!is_confirmed(expected->expectant)) {
3025+
3026+ conntrack->helper = ip_ct_find_helper(&repl_tuple);
3027+ goto end;
3028+ }
3029+
3030+ /* Expectation is dying... */
3031+ if (expected->expectant->helper->timeout
3032+ && ! del_timer(&expected->timeout)) {
3033+ goto end;
3034+ }
3035+
3036+ DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3037+ conntrack, expected);
3038+ /* Welcome, Mr. Bond. We've been expecting you... */
3039+ IP_NF_ASSERT(master_ct(conntrack));
3040+ __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3041+ conntrack->master = expected;
3042+ expected->sibling = conntrack;
3043+#if CONFIG_IP_NF_CONNTRACK_MARK
3044+ conntrack->mark = expected->expectant->mark;
3045+#endif
3046+ LIST_DELETE(&ip_conntrack_expect_list, expected);
3047+ expected->expectant->expecting--;
3048+ nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3049+
3050+ /* this is a braindead... --pablo */
3051+ atomic_inc(&ip_conntrack_count);
3052+ WRITE_UNLOCK(&ip_conntrack_lock);
3053+
3054+ if (expected->expectfn)
3055+ expected->expectfn(conntrack);
3056+
3057+ goto ret;
3058+ } else
3059+ conntrack->helper = ip_ct_find_helper(&repl_tuple);
3060+
3061+end: atomic_inc(&ip_conntrack_count);
3062 WRITE_UNLOCK(&ip_conntrack_lock);
3063
3064- if (expected && expected->expectfn)
3065- expected->expectfn(conntrack);
3066- return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3067+ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3068 }
3069
3070 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3071@@ -947,9 +959,8 @@
3072 atomic_set(&new->use, 1);
3073
3074 /* add to expected list for this connection */
3075- list_add(&new->expected_list, &related_to->sibling_list);
3076+ list_add_tail(&new->expected_list, &related_to->sibling_list);
3077 /* add to global list of expectations */
3078-
3079 list_prepend(&ip_conntrack_expect_list, &new->list);
3080 /* add and start timer if required */
3081 if (related_to->helper->timeout) {
3082@@ -1003,7 +1014,6 @@
3083
3084 } else if (related_to->helper->max_expected &&
3085 related_to->expecting >= related_to->helper->max_expected) {
3086- struct list_head *cur_item;
3087 /* old == NULL */
3088 if (!(related_to->helper->flags &
3089 IP_CT_HELPER_F_REUSE_EXPECT)) {
3090@@ -1029,21 +1039,14 @@
3091 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3092
3093 /* choose the the oldest expectation to evict */
3094- list_for_each(cur_item, &related_to->sibling_list) {
3095- struct ip_conntrack_expect *cur;
3096-
3097- cur = list_entry(cur_item,
3098- struct ip_conntrack_expect,
3099- expected_list);
3100- if (cur->sibling == NULL) {
3101- old = cur;
3102+ list_for_each_entry(old, &related_to->sibling_list,
3103+ expected_list)
3104+ if (old->sibling == NULL)
3105 break;
3106- }
3107- }
3108
3109- /* (!old) cannot happen, since related_to->expecting is the
3110- * number of unconfirmed expects */
3111- IP_NF_ASSERT(old);
3112+ /* We cannot fail since related_to->expecting is the number
3113+ * of unconfirmed expectations */
3114+ IP_NF_ASSERT(old && old->sibling == NULL);
3115
3116 /* newnat14 does not reuse the real allocated memory
3117 * structures but rather unexpects the old and
3118diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
3119--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
3120+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c 2004-04-30 09:12:26.000000000 +0200
3121@@ -0,0 +1,237 @@
3122+/* Eggdrop extension for IP connection tracking, Version 0.0.5
3123+ * based on ip_conntrack_irc.c
3124+ *
3125+ * This module only supports the share userfile-send command,
3126+ * used by eggdrops to share it's userfile.
3127+ *
3128+ * There are no support for NAT at the moment.
3129+ *
3130+ * This program is free software; you can redistribute it and/or
3131+ * modify it under the terms of the GNU General Public License
3132+ * as published by the Free Software Foundation; either version
3133+ * 2 of the License, or (at your option) any later version.
3134+ *
3135+ * Module load syntax:
3136+ *
3137+ * please give the ports of all Eggdrops You have running
3138+ * on your system, the default port is 3333.
3139+ *
3140+ * 2001-04-19: Security update. IP addresses are now compared
3141+ * to prevent unauthorized "related" access.
3142+ *
3143+ * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
3144+ * Port to netfilter 'newnat' API.
3145+ */
3146+
3147+#include <linux/module.h>
3148+#include <linux/netfilter.h>
3149+#include <linux/ip.h>
3150+#include <net/checksum.h>
3151+#include <net/tcp.h>
3152+
3153+#include <linux/netfilter_ipv4/lockhelp.h>
3154+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3155+
3156+#define MAX_PORTS 8
3157+static int ports[MAX_PORTS];
3158+static int ports_c = 0;
3159+static unsigned int egg_timeout = 300;
3160+
3161+MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3162+MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3163+MODULE_LICENSE("GPL");
3164+#ifdef MODULE_PARM
3165+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3166+MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3167+#endif
3168+
3169+DECLARE_LOCK(ip_egg_lock);
3170+struct module *ip_conntrack_egg = THIS_MODULE;
3171+
3172+#if 0
3173+#define DEBUGP printk
3174+#else
3175+#define DEBUGP(format, args...)
3176+#endif
3177+
3178+int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3179+/* tries to get the ip_addr and port out of a eggdrop command
3180+ return value: -1 on failure, 0 on success
3181+ data pointer to first byte of DCC command data
3182+ data_end pointer to last byte of dcc command data
3183+ ip returns parsed ip of dcc command
3184+ port returns parsed port of dcc command */
3185+{
3186+ if (data > data_end)
3187+ return -1;
3188+
3189+ *ip = simple_strtoul(data, &data, 10);
3190+
3191+ /* skip blanks between ip and port */
3192+ while (*data == ' ' && data < data_end)
3193+ data++;
3194+
3195+ *port = simple_strtoul(data, &data, 10);
3196+ return 0;
3197+}
3198+
3199+
3200+static int help(const struct iphdr *iph, size_t len,
3201+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3202+{
3203+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3204+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3205+ char *data = (char *) tcph + tcph->doff * 4;
3206+ char *data_limit;
3207+ u_int32_t tcplen = len - iph->ihl * 4;
3208+ u_int32_t datalen = tcplen - tcph->doff * 4;
3209+ int dir = CTINFO2DIR(ctinfo);
3210+ int bytes_scanned = 0;
3211+ struct ip_conntrack_expect exp;
3212+
3213+ u_int32_t egg_ip;
3214+ u_int16_t egg_port;
3215+
3216+ DEBUGP("entered\n");
3217+
3218+ /* If packet is coming from IRC server */
3219+ if (dir != IP_CT_DIR_REPLY)
3220+ return NF_ACCEPT;
3221+
3222+ /* Until there's been traffic both ways, don't look in packets. */
3223+ if (ctinfo != IP_CT_ESTABLISHED
3224+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3225+ DEBUGP("Conntrackinfo = %u\n", ctinfo);
3226+ return NF_ACCEPT;
3227+ }
3228+
3229+ /* Not whole TCP header? */
3230+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3231+ DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3232+ return NF_ACCEPT;
3233+ }
3234+
3235+ /* Checksum invalid? Ignore. */
3236+ /* FIXME: Source route IP option packets --RR */
3237+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3238+ csum_partial((char *) tcph, tcplen, 0))) {
3239+ DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3240+ tcph, tcplen, NIPQUAD(iph->saddr),
3241+ NIPQUAD(iph->daddr));
3242+ return NF_ACCEPT;
3243+ }
3244+
3245+ data_limit = (char *) data + datalen;
3246+ while (datalen > 5 && bytes_scanned < 128) {
3247+ if (memcmp(data, "s us ", 5)) {
3248+ data++;
3249+ datalen--;
3250+ bytes_scanned++;
3251+ continue;
3252+ }
3253+
3254+ data += 5;
3255+
3256+ DEBUGP("Userfile-share found in connection "
3257+ "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3258+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3259+
3260+ if (parse_command((char *) data, data_limit, &egg_ip,
3261+ &egg_port)) {
3262+ DEBUGP("no data in userfile-share pkt\n");
3263+ return NF_ACCEPT;
3264+ }
3265+
3266+ memset(&exp, 0, sizeof(exp));
3267+
3268+ if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3269+ if (net_ratelimit())
3270+ printk("Forged Eggdrop command from "
3271+ "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3272+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3273+ HIPQUAD(egg_ip), egg_port);
3274+ return NF_ACCEPT;
3275+ }
3276+
3277+ exp.tuple.src.ip = iph->daddr;
3278+ exp.tuple.src.u.tcp.port = 0;
3279+ exp.tuple.dst.ip = htonl(egg_ip);
3280+ exp.tuple.dst.u.tcp.port = htons(egg_port);
3281+ exp.tuple.dst.protonum = IPPROTO_TCP;
3282+
3283+ exp.mask.dst.u.tcp.port = 0xffff;
3284+ exp.mask.dst.protonum = 0xffff;
3285+
3286+ DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3287+ NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3288+ NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3289+
3290+ ip_conntrack_expect_related(ct, &exp);
3291+ break;
3292+ }
3293+ return NF_ACCEPT;
3294+}
3295+
3296+static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3297+static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3298+
3299+static void deregister_helpers(void) {
3300+ int i;
3301+
3302+ for (i = 0; i < ports_c; i++) {
3303+ DEBUGP("unregistering helper for port %d\n", ports[i]);
3304+ ip_conntrack_helper_unregister(&egg_helpers[i]);
3305+ }
3306+}
3307+
3308+static int __init init(void)
3309+{
3310+ int i, ret;
3311+ char *tmpname;
3312+
3313+ /* If no port given, default to standard eggdrop port */
3314+ if (ports[0] == 0)
3315+ ports[0] = 3333;
3316+
3317+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3318+ memset(&egg_helpers[i], 0,
3319+ sizeof(struct ip_conntrack_helper));
3320+ egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3321+ egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3322+ egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3323+ egg_helpers[i].mask.dst.protonum = 0xFFFF;
3324+ egg_helpers[i].max_expected = 1;
3325+ egg_helpers[i].timeout = egg_timeout;
3326+ egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3327+ egg_helpers[i].me = THIS_MODULE;
3328+ egg_helpers[i].help = help;
3329+
3330+ tmpname = &egg_names[i][0];
3331+ if (ports[i] == 3333)
3332+ sprintf(tmpname, "eggdrop");
3333+ else
3334+ sprintf(tmpname, "eggdrop-%d", ports[i]);
3335+ egg_helpers[i].name = tmpname;
3336+
3337+ DEBUGP("port #%d: %d\n", i, ports[i]);
3338+
3339+ ret = ip_conntrack_helper_register(&egg_helpers[i]);
3340+
3341+ if (ret) {
3342+ printk("ip_conntrack_egg: ERROR registering helper "
3343+ "for port %d\n", ports[i]);
3344+ deregister_helpers();
3345+ return 1;
3346+ }
3347+ ports_c++;
3348+ }
3349+ return 0;
3350+}
3351+
3352+static void __exit fini(void)
3353+{
3354+ deregister_helpers();
3355+}
3356+
3357+module_init(init);
3358+module_exit(fini);
3359diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
3360--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
3361+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c 2004-04-30 09:12:34.000000000 +0200
3362@@ -0,0 +1,308 @@
3363+/*
3364+ * H.323 'brute force' extension for H.323 connection tracking.
3365+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3366+ *
3367+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3368+ * (http://www.coritel.it/projects/sofia/nat/)
3369+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3370+ * the unregistered helpers to the conntrack entries.
3371+ */
3372+
3373+
3374+#include <linux/module.h>
3375+#include <linux/netfilter.h>
3376+#include <linux/ip.h>
3377+#include <net/checksum.h>
3378+#include <net/tcp.h>
3379+
3380+#include <linux/netfilter_ipv4/lockhelp.h>
3381+#include <linux/netfilter_ipv4/ip_conntrack.h>
3382+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3383+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3384+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3385+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3386+
3387+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3388+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3389+MODULE_LICENSE("GPL");
3390+
3391+DECLARE_LOCK(ip_h323_lock);
3392+struct module *ip_conntrack_h323 = THIS_MODULE;
3393+
3394+#if 0
3395+#define DEBUGP printk
3396+#else
3397+#define DEBUGP(format, args...)
3398+#endif
3399+
3400+/* FIXME: This should be in userspace. Later. */
3401+static int h245_help(const struct iphdr *iph, size_t len,
3402+ struct ip_conntrack *ct,
3403+ enum ip_conntrack_info ctinfo)
3404+{
3405+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3406+ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3407+ unsigned char *data_limit;
3408+ u_int32_t tcplen = len - iph->ihl * 4;
3409+ u_int32_t datalen = tcplen - tcph->doff * 4;
3410+ int dir = CTINFO2DIR(ctinfo);
3411+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3412+ struct ip_conntrack_expect expect, *exp = &expect;
3413+ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3414+ u_int16_t data_port;
3415+ u_int32_t data_ip;
3416+ unsigned int i;
3417+
3418+ DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3419+ NIPQUAD(iph->saddr), ntohs(tcph->source),
3420+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
3421+
3422+ /* Can't track connections formed before we registered */
3423+ if (!info)
3424+ return NF_ACCEPT;
3425+
3426+ /* Until there's been traffic both ways, don't look in packets. */
3427+ if (ctinfo != IP_CT_ESTABLISHED
3428+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3429+ DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3430+ return NF_ACCEPT;
3431+ }
3432+
3433+ /* Not whole TCP header or too short packet? */
3434+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3435+ DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3436+ return NF_ACCEPT;
3437+ }
3438+
3439+ /* Checksum invalid? Ignore. */
3440+ /* FIXME: Source route IP option packets --RR */
3441+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3442+ csum_partial((char *)tcph, tcplen, 0))) {
3443+ DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3444+ tcph, tcplen, NIPQUAD(iph->saddr),
3445+ NIPQUAD(iph->daddr));
3446+ return NF_ACCEPT;
3447+ }
3448+
3449+ data_limit = (unsigned char *) data + datalen;
3450+ /* bytes: 0123 45
3451+ ipadrr port */
3452+ for (i = 0; data < (data_limit - 5); data++, i++) {
3453+ data_ip = *((u_int32_t *)data);
3454+ if (data_ip == iph->saddr) {
3455+ data_port = *((u_int16_t *)(data + 4));
3456+ memset(&expect, 0, sizeof(expect));
3457+ /* update the H.225 info */
3458+ DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3459+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3460+ NIPQUAD(iph->saddr), ntohs(data_port));
3461+ LOCK_BH(&ip_h323_lock);
3462+ info->is_h225 = H225_PORT + 1;
3463+ exp_info->port = data_port;
3464+ exp_info->dir = dir;
3465+ exp_info->offset = i;
3466+
3467+ exp->seq = ntohl(tcph->seq) + i;
3468+
3469+ exp->tuple = ((struct ip_conntrack_tuple)
3470+ { { ct->tuplehash[!dir].tuple.src.ip,
3471+ { 0 } },
3472+ { data_ip,
3473+ { .tcp = { data_port } },
3474+ IPPROTO_UDP }});
3475+ exp->mask = ((struct ip_conntrack_tuple)
3476+ { { 0xFFFFFFFF, { 0 } },
3477+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3478+
3479+ exp->expectfn = NULL;
3480+
3481+ /* Ignore failure; should only happen with NAT */
3482+ ip_conntrack_expect_related(ct, exp);
3483+
3484+ UNLOCK_BH(&ip_h323_lock);
3485+ }
3486+ }
3487+
3488+ return NF_ACCEPT;
3489+
3490+}
3491+
3492+/* H.245 helper is not registered! */
3493+static struct ip_conntrack_helper h245 =
3494+ { { NULL, NULL },
3495+ "H.245", /* name */
3496+ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3497+ NULL, /* module */
3498+ 8, /* max_ expected */
3499+ 240, /* timeout */
3500+ { { 0, { 0 } }, /* tuple */
3501+ { 0, { 0 }, IPPROTO_TCP } },
3502+ { { 0, { 0xFFFF } }, /* mask */
3503+ { 0, { 0 }, 0xFFFF } },
3504+ h245_help /* helper */
3505+ };
3506+
3507+static int h225_expect(struct ip_conntrack *ct)
3508+{
3509+ WRITE_LOCK(&ip_conntrack_lock);
3510+ ct->helper = &h245;
3511+ DEBUGP("h225_expect: helper for %p added\n", ct);
3512+ WRITE_UNLOCK(&ip_conntrack_lock);
3513+
3514+ return NF_ACCEPT; /* unused */
3515+}
3516+
3517+/* FIXME: This should be in userspace. Later. */
3518+static int h225_help(const struct iphdr *iph, size_t len,
3519+ struct ip_conntrack *ct,
3520+ enum ip_conntrack_info ctinfo)
3521+{
3522+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3523+ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3524+ unsigned char *data_limit;
3525+ u_int32_t tcplen = len - iph->ihl * 4;
3526+ u_int32_t datalen = tcplen - tcph->doff * 4;
3527+ int dir = CTINFO2DIR(ctinfo);
3528+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3529+ struct ip_conntrack_expect expect, *exp = &expect;
3530+ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3531+ u_int16_t data_port;
3532+ u_int32_t data_ip;
3533+ unsigned int i;
3534+
3535+ DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3536+ NIPQUAD(iph->saddr), ntohs(tcph->source),
3537+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
3538+
3539+ /* Can't track connections formed before we registered */
3540+ if (!info)
3541+ return NF_ACCEPT;
3542+
3543+ /* Until there's been traffic both ways, don't look in packets. */
3544+ if (ctinfo != IP_CT_ESTABLISHED
3545+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3546+ DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3547+ return NF_ACCEPT;
3548+ }
3549+
3550+ /* Not whole TCP header or too short packet? */
3551+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3552+ DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3553+ return NF_ACCEPT;
3554+ }
3555+
3556+ /* Checksum invalid? Ignore. */
3557+ /* FIXME: Source route IP option packets --RR */
3558+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3559+ csum_partial((char *)tcph, tcplen, 0))) {
3560+ DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3561+ tcph, tcplen, NIPQUAD(iph->saddr),
3562+ NIPQUAD(iph->daddr));
3563+ return NF_ACCEPT;
3564+ }
3565+
3566+ data_limit = (unsigned char *) data + datalen;
3567+ /* bytes: 0123 45
3568+ ipadrr port */
3569+ for (i = 0; data < (data_limit - 5); data++, i++) {
3570+ data_ip = *((u_int32_t *)data);
3571+ if (data_ip == iph->saddr) {
3572+ data_port = *((u_int16_t *)(data + 4));
3573+ if (data_port == tcph->source) {
3574+ /* Signal address */
3575+ DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3576+ NIPQUAD(iph->saddr));
3577+ /* Update the H.225 info so that NAT can mangle the address/port
3578+ even when we have no expected connection! */
3579+#ifdef CONFIG_IP_NF_NAT_NEEDED
3580+ LOCK_BH(&ip_h323_lock);
3581+ info->dir = dir;
3582+ info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3583+ info->offset[IP_CT_DIR_ORIGINAL] = i;
3584+ UNLOCK_BH(&ip_h323_lock);
3585+#endif
3586+ } else {
3587+ memset(&expect, 0, sizeof(expect));
3588+
3589+ /* update the H.225 info */
3590+ LOCK_BH(&ip_h323_lock);
3591+ info->is_h225 = H225_PORT;
3592+ exp_info->port = data_port;
3593+ exp_info->dir = dir;
3594+ exp_info->offset = i;
3595+
3596+ exp->seq = ntohl(tcph->seq) + i;
3597+
3598+ exp->tuple = ((struct ip_conntrack_tuple)
3599+ { { ct->tuplehash[!dir].tuple.src.ip,
3600+ { 0 } },
3601+ { data_ip,
3602+ { .tcp = { data_port } },
3603+ IPPROTO_TCP }});
3604+ exp->mask = ((struct ip_conntrack_tuple)
3605+ { { 0xFFFFFFFF, { 0 } },
3606+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3607+
3608+ exp->expectfn = h225_expect;
3609+
3610+ /* Ignore failure */
3611+ ip_conntrack_expect_related(ct, exp);
3612+
3613+ DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3614+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3615+ NIPQUAD(iph->saddr), ntohs(data_port));
3616+
3617+ UNLOCK_BH(&ip_h323_lock);
3618+ }
3619+#ifdef CONFIG_IP_NF_NAT_NEEDED
3620+ } else if (data_ip == iph->daddr) {
3621+ data_port = *((u_int16_t *)(data + 4));
3622+ if (data_port == tcph->dest) {
3623+ /* Signal address */
3624+ DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3625+ NIPQUAD(iph->daddr));
3626+ /* Update the H.225 info so that NAT can mangle the address/port
3627+ even when we have no expected connection! */
3628+ LOCK_BH(&ip_h323_lock);
3629+ info->dir = dir;
3630+ info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3631+ info->offset[IP_CT_DIR_REPLY] = i;
3632+ UNLOCK_BH(&ip_h323_lock);
3633+ }
3634+#endif
3635+ }
3636+ }
3637+
3638+ return NF_ACCEPT;
3639+
3640+}
3641+
3642+static struct ip_conntrack_helper h225 =
3643+ { { NULL, NULL },
3644+ "H.225", /* name */
3645+ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
3646+ THIS_MODULE, /* module */
3647+ 2, /* max_expected */
3648+ 240, /* timeout */
3649+ { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
3650+ { 0, { 0 }, IPPROTO_TCP } },
3651+ { { 0, { 0xFFFF } }, /* mask */
3652+ { 0, { 0 }, 0xFFFF } },
3653+ h225_help /* helper */
3654+ };
3655+
3656+static int __init init(void)
3657+{
3658+ return ip_conntrack_helper_register(&h225);
3659+}
3660+
3661+static void __exit fini(void)
3662+{
3663+ /* Unregister H.225 helper */
3664+ ip_conntrack_helper_unregister(&h225);
3665+}
3666+
3667+EXPORT_SYMBOL(ip_h323_lock);
3668+
3669+module_init(init);
3670+module_exit(fini);
3671diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
3672--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
3673+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c 2004-04-30 09:12:58.000000000 +0200
3674@@ -0,0 +1,308 @@
3675+/* MMS extension for IP connection tracking
3676+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3677+ * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
3678+ *
3679+ * ip_conntrack_mms.c v0.3 2002-09-22
3680+ *
3681+ * This program is free software; you can redistribute it and/or
3682+ * modify it under the terms of the GNU General Public License
3683+ * as published by the Free Software Foundation; either version
3684+ * 2 of the License, or (at your option) any later version.
3685+ *
3686+ * Module load syntax:
3687+ * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
3688+ *
3689+ * Please give the ports of all MMS servers You wish to connect to.
3690+ * If you don't specify ports, the default will be TCP port 1755.
3691+ *
3692+ * More info on MMS protocol, firewalls and NAT:
3693+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
3694+ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
3695+ *
3696+ * The SDP project people are reverse-engineering MMS:
3697+ * http://get.to/sdp
3698+ */
3699+
3700+#include <linux/config.h>
3701+#include <linux/module.h>
3702+#include <linux/netfilter.h>
3703+#include <linux/ip.h>
3704+#include <linux/ctype.h>
3705+#include <net/checksum.h>
3706+#include <net/tcp.h>
3707+
3708+#include <linux/netfilter_ipv4/lockhelp.h>
3709+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3710+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
3711+
3712+DECLARE_LOCK(ip_mms_lock);
3713+struct module *ip_conntrack_mms = THIS_MODULE;
3714+
3715+#define MAX_PORTS 8
3716+static int ports[MAX_PORTS];
3717+static int ports_c;
3718+#ifdef MODULE_PARM
3719+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3720+#endif
3721+
3722+#if 0
3723+#define DEBUGP printk
3724+#else
3725+#define DEBUGP(format, args...)
3726+#endif
3727+
3728+EXPORT_SYMBOL(ip_mms_lock);
3729+
3730+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3731+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
3732+MODULE_LICENSE("GPL");
3733+
3734+/* #define isdigit(c) (c >= '0' && c <= '9') */
3735+
3736+/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
3737+static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
3738+{
3739+ int i;
3740+ for (i = 0; i < unicode_size; ++i) {
3741+ string[i] = (char)(unicode[i]);
3742+ }
3743+ string[unicode_size] = 0x00;
3744+}
3745+
3746+__inline static int atoi(char *s)
3747+{
3748+ int i=0;
3749+ while (isdigit(*s)) {
3750+ i = i*10 + *(s++) - '0';
3751+ }
3752+ return i;
3753+}
3754+
3755+/* convert ip address string like "192.168.0.10" to unsigned int */
3756+__inline static u_int32_t asciiiptoi(char *s)
3757+{
3758+ unsigned int i, j, k;
3759+
3760+ for(i=k=0; k<3; ++k, ++s, i<<=8) {
3761+ i+=atoi(s);
3762+ for(j=0; (*(++s) != '.') && (j<3); ++j)
3763+ ;
3764+ }
3765+ i+=atoi(s);
3766+ return ntohl(i);
3767+}
3768+
3769+int parse_mms(const char *data,
3770+ const unsigned int datalen,
3771+ u_int32_t *mms_ip,
3772+ u_int16_t *mms_proto,
3773+ u_int16_t *mms_port,
3774+ char **mms_string_b,
3775+ char **mms_string_e,
3776+ char **mms_padding_e)
3777+{
3778+ int unicode_size, i;
3779+ char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
3780+ char getlengthstring[28];
3781+
3782+ for(unicode_size=0;
3783+ (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
3784+ unicode_size++)
3785+ if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
3786+ return -1; /* out of bounds - incomplete packet */
3787+
3788+ unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
3789+ DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
3790+
3791+ /* IP address ? */
3792+ *mms_ip = asciiiptoi(tempstring+2);
3793+
3794+ i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
3795+
3796+ /* protocol ? */
3797+ if(strncmp(tempstring+3+i, "TCP", 3)==0)
3798+ *mms_proto = IPPROTO_TCP;
3799+ else if(strncmp(tempstring+3+i, "UDP", 3)==0)
3800+ *mms_proto = IPPROTO_UDP;
3801+
3802+ /* port ? */
3803+ *mms_port = atoi(tempstring+7+i);
3804+
3805+ /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
3806+ unicode string, one to the end of the string, and one to the end
3807+ of the packet, since we must keep track of the number of bytes
3808+ between end of the unicode string and the end of packet (padding) */
3809+ *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
3810+ *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
3811+ *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
3812+ return 0;
3813+}
3814+
3815+
3816+/* FIXME: This should be in userspace. Later. */
3817+static int help(const struct iphdr *iph, size_t len,
3818+ struct ip_conntrack *ct,
3819+ enum ip_conntrack_info ctinfo)
3820+{
3821+ /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
3822+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3823+ const char *data = (const char *)tcph + tcph->doff * 4;
3824+ unsigned int tcplen = len - iph->ihl * 4;
3825+ unsigned int datalen = tcplen - tcph->doff * 4;
3826+ int dir = CTINFO2DIR(ctinfo);
3827+ struct ip_conntrack_expect expect, *exp = &expect;
3828+ struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
3829+
3830+ u_int32_t mms_ip;
3831+ u_int16_t mms_proto;
3832+ char mms_proto_string[8];
3833+ u_int16_t mms_port;
3834+ char *mms_string_b, *mms_string_e, *mms_padding_e;
3835+
3836+ /* Until there's been traffic both ways, don't look in packets. */
3837+ if (ctinfo != IP_CT_ESTABLISHED
3838+ && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
3839+ DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
3840+ return NF_ACCEPT;
3841+ }
3842+
3843+ /* Not whole TCP header? */
3844+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
3845+ DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
3846+ return NF_ACCEPT;
3847+ }
3848+
3849+ /* Checksum invalid? Ignore. */
3850+ /* FIXME: Source route IP option packets --RR */
3851+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3852+ csum_partial((char *)tcph, tcplen, 0))) {
3853+ DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3854+ tcph, tcplen, NIPQUAD(iph->saddr),
3855+ NIPQUAD(iph->daddr));
3856+ return NF_ACCEPT;
3857+ }
3858+
3859+ /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
3860+ /* FIXME: There is an issue with only looking at this packet: before this packet,
3861+ the client has already sent a packet to the server with the server's hostname
3862+ according to the client (think of it as the "Host: " header in HTTP/1.1). The
3863+ server will break the connection if this doesn't correspond to its own host
3864+ header. The client can also connect to an IP address; if it's the server's IP
3865+ address, it will not break the connection. When doing DNAT on a connection
3866+ where the client uses a server's IP address, the nat module should detect
3867+ this and change this string accordingly to the DNATed address. This should
3868+ probably be done by checking for an IP address, then storing it as a member
3869+ of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
3870+ */
3871+ if( (MMS_SRV_MSG_OFFSET < datalen) &&
3872+ ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
3873+ DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
3874+ (u8)*(data+36), (u8)*(data+37),
3875+ (u8)*(data+38), (u8)*(data+39),
3876+ datalen);
3877+ if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
3878+ &mms_string_b, &mms_string_e, &mms_padding_e))
3879+ if(net_ratelimit())
3880+ /* FIXME: more verbose debugging ? */
3881+ printk(KERN_WARNING
3882+ "ip_conntrack_mms: Unable to parse data payload\n");
3883+
3884+ memset(&expect, 0, sizeof(expect));
3885+
3886+ sprintf(mms_proto_string, "(%u)", mms_proto);
3887+ DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
3888+ mms_proto == IPPROTO_TCP ? "TCP"
3889+ : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
3890+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3891+ NIPQUAD(mms_ip),
3892+ mms_port);
3893+
3894+ /* it's possible that the client will just ask the server to tunnel
3895+ the stream over the same TCP session (from port 1755): there's
3896+ shouldn't be a need to add an expectation in that case, but it
3897+ makes NAT packet mangling so much easier */
3898+ LOCK_BH(&ip_mms_lock);
3899+
3900+ DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
3901+
3902+ exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
3903+ exp_mms_info->len = (mms_string_e - mms_string_b);
3904+ exp_mms_info->padding = (mms_padding_e - mms_string_e);
3905+ exp_mms_info->port = mms_port;
3906+
3907+ DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
3908+ exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
3909+
3910+ exp->tuple = ((struct ip_conntrack_tuple)
3911+ { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3912+ { mms_ip,
3913+ { .tcp = { (__u16) ntohs(mms_port) } },
3914+ mms_proto } }
3915+ );
3916+ exp->mask = ((struct ip_conntrack_tuple)
3917+ { { 0xFFFFFFFF, { 0 } },
3918+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3919+ exp->expectfn = NULL;
3920+ ip_conntrack_expect_related(ct, &expect);
3921+ UNLOCK_BH(&ip_mms_lock);
3922+ }
3923+
3924+ return NF_ACCEPT;
3925+}
3926+
3927+static struct ip_conntrack_helper mms[MAX_PORTS];
3928+static char mms_names[MAX_PORTS][10];
3929+
3930+/* Not __exit: called from init() */
3931+static void fini(void)
3932+{
3933+ int i;
3934+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3935+ DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
3936+ ports[i]);
3937+ ip_conntrack_helper_unregister(&mms[i]);
3938+ }
3939+}
3940+
3941+static int __init init(void)
3942+{
3943+ int i, ret;
3944+ char *tmpname;
3945+
3946+ if (ports[0] == 0)
3947+ ports[0] = MMS_PORT;
3948+
3949+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3950+ memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
3951+ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
3952+ mms[i].tuple.dst.protonum = IPPROTO_TCP;
3953+ mms[i].mask.src.u.tcp.port = 0xFFFF;
3954+ mms[i].mask.dst.protonum = 0xFFFF;
3955+ mms[i].max_expected = 1;
3956+ mms[i].timeout = 0;
3957+ mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3958+ mms[i].me = THIS_MODULE;
3959+ mms[i].help = help;
3960+
3961+ tmpname = &mms_names[i][0];
3962+ if (ports[i] == MMS_PORT)
3963+ sprintf(tmpname, "mms");
3964+ else
3965+ sprintf(tmpname, "mms-%d", ports[i]);
3966+ mms[i].name = tmpname;
3967+
3968+ DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
3969+ ports[i]);
3970+ ret = ip_conntrack_helper_register(&mms[i]);
3971+
3972+ if (ret) {
3973+ fini();
3974+ return ret;
3975+ }
3976+ ports_c++;
3977+ }
3978+ return 0;
3979+}
3980+
3981+module_init(init);
3982+module_exit(fini);
3983diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
3984--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
3985+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-04-30 09:14:08.000000000 +0200
3986@@ -0,0 +1,529 @@
3987+/*
3988+ * Connection tracking protocol helper module for SCTP.
3989+ *
3990+ * SCTP is defined in RFC 2960. References to various sections in this code
3991+ * are to this RFC.
3992+ *
3993+ * This program is free software; you can redistribute it and/or modify
3994+ * it under the terms of the GNU General Public License version 2 as
3995+ * published by the Free Software Foundation.
3996+ */
3997+
3998+#include <linux/types.h>
3999+#include <linux/sched.h>
4000+#include <linux/timer.h>
4001+#include <linux/netfilter.h>
4002+#include <linux/module.h>
4003+#include <linux/in.h>
4004+#include <linux/ip.h>
4005+#include <linux/sctp.h>
4006+#include <linux/string.h>
4007+
4008+#include <linux/netfilter_ipv4/ip_conntrack.h>
4009+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4010+#include <linux/netfilter_ipv4/lockhelp.h>
4011+
4012+#if 0
4013+#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4014+#else
4015+#define DEBUGP(format, args...)
4016+#endif
4017+
4018+/* Protects conntrack->proto.sctp */
4019+static DECLARE_RWLOCK(sctp_lock);
4020+
4021+/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4022+ closely. They're more complex. --RR
4023+
4024+ And so for me for SCTP :D -Kiran */
4025+
4026+static const char *sctp_conntrack_names[] = {
4027+ "NONE",
4028+ "CLOSED",
4029+ "COOKIE_WAIT",
4030+ "COOKIE_ECHOED",
4031+ "ESTABLISHED",
4032+ "SHUTDOWN_SENT",
4033+ "SHUTDOWN_RECD",
4034+ "SHUTDOWN_ACK_SENT",
4035+};
4036+
4037+#define SECS * HZ
4038+#define MINS * 60 SECS
4039+#define HOURS * 60 MINS
4040+#define DAYS * 24 HOURS
4041+
4042+unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
4043+unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
4044+unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
4045+unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
4046+unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
4047+unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
4048+unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
4049+
4050+static unsigned long * sctp_timeouts[]
4051+= { 0, /* SCTP_CONNTRACK_NONE */
4052+ &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
4053+ &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
4054+ &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
4055+ &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
4056+ &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4057+ &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4058+ &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4059+ };
4060+
4061+#define sNO SCTP_CONNTRACK_NONE
4062+#define sCL SCTP_CONNTRACK_CLOSED
4063+#define sCW SCTP_CONNTRACK_COOKIE_WAIT
4064+#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
4065+#define sES SCTP_CONNTRACK_ESTABLISHED
4066+#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4067+#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4068+#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4069+#define sIV SCTP_CONNTRACK_MAX
4070+
4071+/*
4072+ These are the descriptions of the states:
4073+
4074+NOTE: These state names are tantalizingly similar to the states of an
4075+SCTP endpoint. But the interpretation of the states is a little different,
4076+considering that these are the states of the connection and not of an end
4077+point. Please note the subtleties. -Kiran
4078+
4079+NONE - Nothing so far.
4080+COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
4081+ an INIT_ACK chunk in the reply direction.
4082+COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
4083+ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
4084+SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
4085+SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
4086+SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4087+ to that of the SHUTDOWN chunk.
4088+CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
4089+ the SHUTDOWN chunk. Connection is closed.
4090+*/
4091+
4092+/* TODO
4093+ - I have assumed that the first INIT is in the original direction.
4094+ This messes things when an INIT comes in the reply direction in CLOSED
4095+ state.
4096+ - Check the error type in the reply dir before transitioning from
4097+cookie echoed to closed.
4098+ - Sec 5.2.4 of RFC 2960
4099+ - Multi Homing support.
4100+*/
4101+
4102+/* SCTP conntrack state transitions */
4103+static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4104+ {
4105+/* ORIGINAL */
4106+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4107+/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4108+/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4109+/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4110+/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4111+/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4112+/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4113+/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4114+/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4115+/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4116+ },
4117+ {
4118+/* REPLY */
4119+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4120+/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4121+/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4122+/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4123+/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4124+/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4125+/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4126+/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4127+/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4128+/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4129+ }
4130+};
4131+
4132+static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4133+ unsigned int dataoff,
4134+ struct ip_conntrack_tuple *tuple)
4135+{
4136+ sctp_sctphdr_t hdr;
4137+
4138+ DEBUGP(__FUNCTION__);
4139+ DEBUGP("\n");
4140+
4141+ /* Actually only need first 8 bytes. */
4142+ if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4143+ return 0;
4144+
4145+ tuple->src.u.sctp.port = hdr.source;
4146+ tuple->dst.u.sctp.port = hdr.dest;
4147+
4148+ return 1;
4149+}
4150+
4151+static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4152+ const struct ip_conntrack_tuple *orig)
4153+{
4154+ DEBUGP(__FUNCTION__);
4155+ DEBUGP("\n");
4156+
4157+ tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4158+ tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4159+ return 1;
4160+}
4161+
4162+/* Print out the per-protocol part of the tuple. */
4163+static unsigned int sctp_print_tuple(char *buffer,
4164+ const struct ip_conntrack_tuple *tuple)
4165+{
4166+ DEBUGP(__FUNCTION__);
4167+ DEBUGP("\n");
4168+
4169+ return sprintf(buffer, "sport=%hu dport=%hu ",
4170+ ntohs(tuple->src.u.sctp.port),
4171+ ntohs(tuple->dst.u.sctp.port));
4172+}
4173+
4174+/* Print out the private part of the conntrack. */
4175+static unsigned int sctp_print_conntrack(char *buffer,
4176+ const struct ip_conntrack *conntrack)
4177+{
4178+ enum sctp_conntrack state;
4179+
4180+ DEBUGP(__FUNCTION__);
4181+ DEBUGP("\n");
4182+
4183+ READ_LOCK(&sctp_lock);
4184+ state = conntrack->proto.sctp.state;
4185+ READ_UNLOCK(&sctp_lock);
4186+
4187+ return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4188+}
4189+
4190+#define for_each_sctp_chunk(skb, sch, offset, count) \
4191+for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
4192+ offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
4193+ offset += (htons(sch.length) + 3) & ~3, count++)
4194+
4195+/* Some validity checks to make sure the chunks are fine */
4196+static int do_basic_checks(struct ip_conntrack *conntrack,
4197+ const struct sk_buff *skb,
4198+ char *map)
4199+{
4200+ u_int32_t offset, count;
4201+ sctp_chunkhdr_t sch;
4202+ int flag;
4203+
4204+ DEBUGP(__FUNCTION__);
4205+ DEBUGP("\n");
4206+
4207+ flag = 0;
4208+
4209+ for_each_sctp_chunk (skb, sch, offset, count) {
4210+ DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
4211+
4212+ if (sch.type == SCTP_CID_INIT
4213+ || sch.type == SCTP_CID_INIT_ACK
4214+ || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4215+ flag = 1;
4216+ }
4217+
4218+ /* Cookie Ack/Echo chunks not the first OR
4219+ Init / Init Ack / Shutdown compl chunks not the only chunks */
4220+ if ((sch.type == SCTP_CID_COOKIE_ACK
4221+ || sch.type == SCTP_CID_COOKIE_ECHO
4222+ || flag)
4223+ && count !=0 ) {
4224+ DEBUGP("Basic checks failed\n");
4225+ return 1;
4226+ }
4227+
4228+ if (map) {
4229+ set_bit (sch.type, (void *)map);
4230+ }
4231+ }
4232+
4233+ DEBUGP("Basic checks passed\n");
4234+ return 0;
4235+}
4236+
4237+static int new_state(enum ip_conntrack_dir dir,
4238+ enum sctp_conntrack cur_state,
4239+ int chunk_type)
4240+{
4241+ int i;
4242+
4243+ DEBUGP(__FUNCTION__);
4244+ DEBUGP("\n");
4245+
4246+ DEBUGP("Chunk type: %d\n", chunk_type);
4247+
4248+ switch (chunk_type) {
4249+ case SCTP_CID_INIT:
4250+ DEBUGP("SCTP_CID_INIT\n");
4251+ i = 0; break;
4252+ case SCTP_CID_INIT_ACK:
4253+ DEBUGP("SCTP_CID_INIT_ACK\n");
4254+ i = 1; break;
4255+ case SCTP_CID_ABORT:
4256+ DEBUGP("SCTP_CID_ABORT\n");
4257+ i = 2; break;
4258+ case SCTP_CID_SHUTDOWN:
4259+ DEBUGP("SCTP_CID_SHUTDOWN\n");
4260+ i = 3; break;
4261+ case SCTP_CID_SHUTDOWN_ACK:
4262+ DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4263+ i = 4; break;
4264+ case SCTP_CID_ERROR:
4265+ DEBUGP("SCTP_CID_ERROR\n");
4266+ i = 5; break;
4267+ case SCTP_CID_COOKIE_ECHO:
4268+ DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4269+ i = 6; break;
4270+ case SCTP_CID_COOKIE_ACK:
4271+ DEBUGP("SCTP_CID_COOKIE_ACK\n");
4272+ i = 7; break;
4273+ case SCTP_CID_SHUTDOWN_COMPLETE:
4274+ DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4275+ i = 8; break;
4276+ default:
4277+ /* Other chunks like DATA, SACK, HEARTBEAT and
4278+ its ACK do not cause a change in state */
4279+ DEBUGP("Unknown chunk type, Will stay in %s\n",
4280+ sctp_conntrack_names[cur_state]);
4281+ return cur_state;
4282+ }
4283+
4284+ DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
4285+ dir, sctp_conntrack_names[cur_state], chunk_type,
4286+ sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4287+
4288+ return sctp_conntracks[dir][i][cur_state];
4289+}
4290+
4291+/* Returns verdict for packet, or -1 for invalid. */
4292+static int sctp_packet(struct ip_conntrack *conntrack,
4293+ const struct sk_buff *skb,
4294+ enum ip_conntrack_info ctinfo)
4295+{
4296+ enum sctp_conntrack newconntrack, oldsctpstate;
4297+ sctp_sctphdr_t sctph;
4298+ sctp_chunkhdr_t sch;
4299+ u_int32_t offset, count;
4300+ char map[256 / sizeof (char)] = {0};
4301+
4302+ DEBUGP(__FUNCTION__);
4303+ DEBUGP("\n");
4304+
4305+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4306+ return -1;
4307+
4308+ if (do_basic_checks(conntrack, skb, map) != 0)
4309+ return -1;
4310+
4311+ /* Check the verification tag (Sec 8.5) */
4312+ if (!test_bit(SCTP_CID_INIT, (void *)map)
4313+ && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4314+ && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4315+ && !test_bit(SCTP_CID_ABORT, (void *)map)
4316+ && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4317+ && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4318+ DEBUGP("Verification tag check failed\n");
4319+ return -1;
4320+ }
4321+
4322+ oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4323+ for_each_sctp_chunk (skb, sch, offset, count) {
4324+ WRITE_LOCK(&sctp_lock);
4325+
4326+ /* Special cases of Verification tag check (Sec 8.5.1) */
4327+ if (sch.type == SCTP_CID_INIT) {
4328+ /* Sec 8.5.1 (A) */
4329+ if (sctph.vtag != 0) {
4330+ WRITE_UNLOCK(&sctp_lock);
4331+ return -1;
4332+ }
4333+ } else if (sch.type == SCTP_CID_ABORT) {
4334+ /* Sec 8.5.1 (B) */
4335+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4336+ && !(sctph.vtag == conntrack->proto.sctp.vtag
4337+ [1 - CTINFO2DIR(ctinfo)])) {
4338+ WRITE_UNLOCK(&sctp_lock);
4339+ return -1;
4340+ }
4341+ } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4342+ /* Sec 8.5.1 (C) */
4343+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4344+ && !(sctph.vtag == conntrack->proto.sctp.vtag
4345+ [1 - CTINFO2DIR(ctinfo)]
4346+ && (sch.flags & 1))) {
4347+ WRITE_UNLOCK(&sctp_lock);
4348+ return -1;
4349+ }
4350+ } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4351+ /* Sec 8.5.1 (D) */
4352+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4353+ WRITE_UNLOCK(&sctp_lock);
4354+ return -1;
4355+ }
4356+ }
4357+
4358+ oldsctpstate = conntrack->proto.sctp.state;
4359+ newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4360+
4361+ /* Invalid */
4362+ if (newconntrack == SCTP_CONNTRACK_MAX) {
4363+ DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4364+ CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4365+ WRITE_UNLOCK(&sctp_lock);
4366+ return -1;
4367+ }
4368+
4369+ /* If it is an INIT or an INIT ACK note down the vtag */
4370+ if (sch.type == SCTP_CID_INIT
4371+ || sch.type == SCTP_CID_INIT_ACK) {
4372+ sctp_inithdr_t inithdr;
4373+
4374+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4375+ &inithdr, sizeof(inithdr)) != 0) {
4376+ WRITE_UNLOCK(&sctp_lock);
4377+ return -1;
4378+ }
4379+ DEBUGP("Setting vtag %x for dir %d\n",
4380+ inithdr.init_tag, CTINFO2DIR(ctinfo));
4381+ conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4382+ }
4383+
4384+ conntrack->proto.sctp.state = newconntrack;
4385+ WRITE_UNLOCK(&sctp_lock);
4386+ }
4387+
4388+ ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4389+
4390+ if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4391+ && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4392+ && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4393+ DEBUGP("Setting assured bit\n");
4394+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
4395+ }
4396+
4397+ return NF_ACCEPT;
4398+}
4399+
4400+/* Called when a new connection for this protocol found. */
4401+static int sctp_new(struct ip_conntrack *conntrack,
4402+ const struct sk_buff *skb)
4403+{
4404+ enum sctp_conntrack newconntrack;
4405+ sctp_sctphdr_t sctph;
4406+ sctp_chunkhdr_t sch;
4407+ u_int32_t offset, count;
4408+ char map[256 / sizeof (char)] = {0};
4409+
4410+ DEBUGP(__FUNCTION__);
4411+ DEBUGP("\n");
4412+
4413+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4414+ return -1;
4415+
4416+ if (do_basic_checks(conntrack, skb, map) != 0)
4417+ return -1;
4418+
4419+ /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4420+ if ((test_bit (SCTP_CID_ABORT, (void *)map))
4421+ || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4422+ || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4423+ return -1;
4424+ }
4425+
4426+ newconntrack = SCTP_CONNTRACK_MAX;
4427+ for_each_sctp_chunk (skb, sch, offset, count) {
4428+ /* Don't need lock here: this conntrack not in circulation yet */
4429+ newconntrack = new_state (IP_CT_DIR_ORIGINAL,
4430+ SCTP_CONNTRACK_NONE, sch.type);
4431+
4432+ /* Invalid: delete conntrack */
4433+ if (newconntrack == SCTP_CONNTRACK_MAX) {
4434+ DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4435+ return 0;
4436+ }
4437+
4438+ /* Copy the vtag into the state info */
4439+ if (sch.type == SCTP_CID_INIT) {
4440+ if (sctph.vtag == 0) {
4441+ sctp_inithdr_t inithdr;
4442+
4443+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4444+ &inithdr, sizeof(inithdr)) != 0) {
4445+ return -1;
4446+ }
4447+
4448+ DEBUGP("Setting vtag %x for new conn\n",
4449+ inithdr.init_tag);
4450+
4451+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
4452+ inithdr.init_tag;
4453+ } else {
4454+ /* Sec 8.5.1 (A) */
4455+ return -1;
4456+ }
4457+ }
4458+ /* If it is a shutdown ack OOTB packet, we expect a return
4459+ shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
4460+ else {
4461+ DEBUGP("Setting vtag %x for new conn OOTB\n",
4462+ sctph.vtag);
4463+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
4464+ }
4465+
4466+ conntrack->proto.sctp.state = newconntrack;
4467+ }
4468+
4469+ return 1;
4470+}
4471+
4472+static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
4473+ const struct sk_buff *skb)
4474+{
4475+ /* To be implemented */
4476+ return 0;
4477+}
4478+
4479+struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
4480+ .list = { NULL, NULL },
4481+ .proto = IPPROTO_SCTP,
4482+ .name = "sctp",
4483+ .pkt_to_tuple = sctp_pkt_to_tuple,
4484+ .invert_tuple = sctp_invert_tuple,
4485+ .print_tuple = sctp_print_tuple,
4486+ .print_conntrack = sctp_print_conntrack,
4487+ .packet = sctp_packet,
4488+ .new = sctp_new,
4489+ .destroy = NULL,
4490+ .exp_matches_pkt = sctp_exp_matches_pkt,
4491+ .me = THIS_MODULE
4492+};
4493+
4494+int __init init(void)
4495+{
4496+ int ret;
4497+
4498+ ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
4499+ DEBUGP("SCTP conntrack module loading %s\n",
4500+ ret ? "failed": "succeeded");
4501+ return ret;
4502+}
4503+
4504+void __exit fini(void)
4505+{
4506+ ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
4507+ DEBUGP("SCTP conntrack module unloaded\n");
4508+}
4509+
4510+module_init(init);
4511+module_exit(fini);
4512+
4513+MODULE_LICENSE("GPL");
4514+MODULE_AUTHOR("Kiran Kumar Immidi");
4515+MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
4516diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
4517--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
4518+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-04-30 09:13:29.000000000 +0200
4519@@ -0,0 +1,156 @@
4520+/* Quake3 extension for IP connection tracking
4521+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4522+ * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
4523+ *
4524+ * ip_conntrack_quake3.c v0.04 2002-08-31
4525+ *
4526+ * This program is free software; you can redistribute it and/or
4527+ * modify it under the terms of the GNU General Public License
4528+ * as published by the Free Software Foundation; either version
4529+ * 2 of the License, or (at your option) any later version.
4530+ *
4531+ * Module load syntax:
4532+ * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
4533+ *
4534+ * please give the ports of all Quake3 master servers You wish to
4535+ * connect to. If you don't specify ports, the default will be UDP
4536+ * port 27950.
4537+ *
4538+ * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
4539+ */
4540+
4541+#include <linux/module.h>
4542+#include <linux/ip.h>
4543+#include <linux/udp.h>
4544+
4545+#include <linux/netfilter.h>
4546+#include <linux/netfilter_ipv4/ip_tables.h>
4547+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4548+#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
4549+
4550+struct module *ip_conntrack_quake3 = THIS_MODULE;
4551+
4552+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4553+MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
4554+MODULE_LICENSE("GPL");
4555+
4556+#define MAX_PORTS 8
4557+static int ports[MAX_PORTS];
4558+static int ports_c = 0;
4559+#ifdef MODULE_PARM
4560+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4561+MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
4562+#endif
4563+
4564+/* Quake3 master server reply will add > 100 expectations per reply packet; when
4565+ doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
4566+#if 0
4567+#define DEBUGP printk
4568+#else
4569+#define DEBUGP(format, args...)
4570+#endif
4571+
4572+struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
4573+
4574+static int quake3_help(const struct iphdr *iph, size_t len,
4575+ struct ip_conntrack *ct,
4576+ enum ip_conntrack_info ctinfo)
4577+{
4578+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
4579+ int dir = CTINFO2DIR(ctinfo);
4580+ struct ip_conntrack_expect exp;
4581+ int i;
4582+
4583+ /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
4584+ if (ctinfo != IP_CT_ESTABLISHED
4585+ && ctinfo != IP_CT_IS_REPLY) {
4586+ DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
4587+ return NF_ACCEPT;
4588+ } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
4589+
4590+ if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
4591+ for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
4592+ i+6 < ntohs(udph->len);
4593+ i+=7) {
4594+ DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
4595+ i, ntohs(udph->len),
4596+ NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
4597+ ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
4598+
4599+ memset(&exp, 0, sizeof(exp));
4600+
4601+ exp.tuple = ((struct ip_conntrack_tuple)
4602+ { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4603+ { (u_int32_t) *((u_int32_t *)((int)udph + i)),
4604+ { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
4605+ IPPROTO_UDP } }
4606+ );
4607+ exp.mask = ((struct ip_conntrack_tuple)
4608+ { { 0xFFFFFFFF, { 0 } },
4609+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
4610+ exp.expectfn = NULL;
4611+
4612+ ip_conntrack_expect_related(ct, &exp);
4613+ }
4614+
4615+ }
4616+
4617+ return(NF_ACCEPT);
4618+}
4619+
4620+static struct ip_conntrack_helper quake3[MAX_PORTS];
4621+static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
4622+
4623+static void fini(void)
4624+{
4625+ int i;
4626+
4627+ for(i = 0 ; (i < ports_c); i++) {
4628+ DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
4629+ ports[i]);
4630+ ip_conntrack_helper_unregister(&quake3[i]);
4631+ }
4632+}
4633+
4634+static int __init init(void)
4635+{
4636+ int i, ret;
4637+ char *tmpname;
4638+
4639+ if(!ports[0])
4640+ ports[0]=QUAKE3_MASTER_PORT;
4641+
4642+ for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
4643+ /* Create helper structure */
4644+ memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
4645+
4646+ quake3[i].tuple.dst.protonum = IPPROTO_UDP;
4647+ quake3[i].tuple.src.u.udp.port = htons(ports[i]);
4648+ quake3[i].mask.dst.protonum = 0xFFFF;
4649+ quake3[i].mask.src.u.udp.port = 0xFFFF;
4650+ quake3[i].help = quake3_help;
4651+ quake3[i].me = THIS_MODULE;
4652+
4653+ tmpname = &quake3_names[i][0];
4654+ if (ports[i] == QUAKE3_MASTER_PORT)
4655+ sprintf(tmpname, "quake3");
4656+ else
4657+ sprintf(tmpname, "quake3-%d", i);
4658+ quake3[i].name = tmpname;
4659+
4660+ DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
4661+ ports[i]);
4662+
4663+ ret=ip_conntrack_helper_register(&quake3[i]);
4664+ if(ret) {
4665+ fini();
4666+ return(ret);
4667+ }
4668+ ports_c++;
4669+ }
4670+
4671+ return(0);
4672+}
4673+
4674+module_init(init);
4675+module_exit(fini);
4676diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
4677--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
4678+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-04-30 09:13:59.000000000 +0200
4679@@ -0,0 +1,331 @@
4680+/* RSH extension for IP connection tracking, Version 1.0
4681+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4682+ * based on HW's ip_conntrack_irc.c
4683+ *
4684+ * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
4685+ *
4686+ * This program is free software; you can redistribute it and/or
4687+ * modify it under the terms of the GNU General Public License
4688+ * as published by the Free Software Foundation; either version
4689+ * 2 of the License, or (at your option) any later version.
4690+ **
4691+ * Module load syntax:
4692+ * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
4693+ *
4694+ * please give the ports of all RSH servers You wish to connect to.
4695+ * If You don't specify ports, the default will be port 514
4696+ **
4697+ * Note to all:
4698+ * RSH blows ... you should use SSH (openssh.org) to replace it,
4699+ * unfortunately I babysit some sysadmins that won't migrate
4700+ * their legacy crap, in our second tier.
4701+ */
4702+
4703+
4704+/*
4705+ * Some docco ripped from the net to teach me all there is to know about
4706+ * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
4707+ * this module).
4708+ *
4709+ * I have no idea what "unix rshd man pages" these guys have .. but that
4710+ * is some pretty detailed docco!
4711+ **
4712+ *
4713+ * 4. Of the rsh protocol.
4714+ * -----------------------
4715+ *
4716+ * The rshd listens on TCP port #514. The following info is from the unix
4717+ * rshd man pages :
4718+ *
4719+ * "Service Request Protocol
4720+ *
4721+ * When the rshd daemon receives a service request, it initiates the
4722+ * following protocol:
4723+ *
4724+ * 1. The rshd daemon checks the source port number for the request.
4725+ * If the port number is not in the range 0 through 1023, the rshd daemon
4726+ * terminates the connection.
4727+ *
4728+ * 2. The rshd daemon reads characters from the socket up to a null byte.
4729+ * The string read is interpreted as an ASCII number (base 10). If this
4730+ * number is nonzero, the rshd daemon interprets it as the port number
4731+ * of a secondary stream to be used as standard error. A second connection
4732+ * is created to the specified port on the client host. The source port
4733+ * on the local host is in the range 0 through 1023.
4734+ *
4735+ * 3. The rshd daemon uses the source address of the initial connection
4736+ * request to determine the name of the client host. If the name cannot
4737+ * be determined, the rshd daemon uses the dotted decimal representation
4738+ * of the client host's address.
4739+ *
4740+ * 4. The rshd daemon retrieves the following information from the initial
4741+ * socket:
4742+ *
4743+ * * A null-terminated string of at most 16 bytes interpreted as
4744+ * the user name of the user on the client host.
4745+ *
4746+ * * A null-terminated string of at most 16 bytes interpreted as
4747+ * the user name to be used on the local server host.
4748+ *
4749+ * * Another null-terminated string interpreted as a command line
4750+ * to be passed to a shell on the local server host.
4751+ *
4752+ * 5. The rshd daemon attempts to validate the user using the following steps:
4753+ *
4754+ * a. The rshd daemon looks up the local user name in the /etc/passwd
4755+ * file and tries to switch to the home directory (using the chdir
4756+ * subroutine). If either the lookup or the directory change fails,
4757+ * the rshd daemon terminates the connection.
4758+ *
4759+ * b. If the local user ID is a nonzero value, the rshd daemon searches
4760+ * the /etc/hosts.equiv file to see if the name of the client
4761+ * workstation is listed. If the client workstation is listed as an
4762+ * equivalent host, the rshd daemon validates the user.
4763+ *
4764+ * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4765+ * authenticate the user by checking the .rhosts file.
4766+ *
4767+ * d. If either the $HOME/.rhosts authentication fails or the
4768+ * client host is not an equivalent host, the rshd daemon
4769+ * terminates the connection.
4770+ *
4771+ * 6. Once rshd validates the user, the rshd daemon returns a null byte
4772+ * on the initial connection and passes the command line to the user's
4773+ * local login shell. The shell then inherits the network connections
4774+ * established by the rshd daemon."
4775+ *
4776+ */
4777+
4778+
4779+#include <linux/module.h>
4780+#include <linux/netfilter.h>
4781+#include <linux/ip.h>
4782+#include <net/checksum.h>
4783+#include <net/tcp.h>
4784+
4785+#include <linux/netfilter_ipv4/lockhelp.h>
4786+#include <linux/netfilter_ipv4/ip_tables.h>
4787+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4788+#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4789+
4790+#define MAX_PORTS 8
4791+static int ports[MAX_PORTS];
4792+static int ports_n_c = 0;
4793+
4794+MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4795+MODULE_DESCRIPTION("RSH connection tracking module");
4796+MODULE_LICENSE("GPL");
4797+#ifdef MODULE_PARM
4798+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4799+MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4800+#endif
4801+
4802+DECLARE_LOCK(ip_rsh_lock);
4803+struct module *ip_conntrack_rsh = THIS_MODULE;
4804+
4805+#if 0
4806+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4807+ format, ## args)
4808+#else
4809+#define DEBUGP(format, args...)
4810+#endif
4811+
4812+
4813+
4814+/* FIXME: This should be in userspace. Later. */
4815+static int help(const struct iphdr *iph, size_t len,
4816+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4817+{
4818+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4819+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4820+ const char *data = (const char *) tcph + tcph->doff * 4;
4821+ u_int32_t tcplen = len - iph->ihl * 4;
4822+ int dir = CTINFO2DIR(ctinfo);
4823+ struct ip_conntrack_expect expect, *exp = &expect;
4824+ struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4825+ u_int16_t port;
4826+ int maxoctet;
4827+
4828+ /* note that "maxoctet" is used to maintain sanity (8 was the
4829+ * original array size used in rshd/glibc) -- is there a
4830+ * vulnerability in rshd.c in the looped port *= 10?
4831+ */
4832+
4833+
4834+ DEBUGP("entered\n");
4835+
4836+ /* bail if packet is not from RSH client */
4837+ if (dir == IP_CT_DIR_REPLY)
4838+ return NF_ACCEPT;
4839+
4840+ /* Until there's been traffic both ways, don't look in packets. */
4841+ if (ctinfo != IP_CT_ESTABLISHED
4842+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4843+ DEBUGP("Conntrackinfo = %u\n", ctinfo);
4844+ return NF_ACCEPT;
4845+ }
4846+
4847+ /* Not whole TCP header? */
4848+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4849+ DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4850+ return NF_ACCEPT;
4851+ }
4852+
4853+ /* Checksum invalid? Ignore. */
4854+ /* FIXME: Source route IP option packets --RR */
4855+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4856+ csum_partial((char *) tcph, tcplen, 0))) {
4857+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4858+ tcph, tcplen, NIPQUAD(iph->saddr),
4859+ NIPQUAD(iph->daddr));
4860+ return NF_ACCEPT;
4861+ }
4862+
4863+ /* find the rsh stderr port */
4864+ maxoctet = 4;
4865+ port = 0;
4866+ for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4867+ if (*data < 0)
4868+ return(1);
4869+ if (*data == 0)
4870+ break;
4871+ if (*data < 48 || *data > 57) {
4872+ DEBUGP("these aren't the packets you're looking for ..\n");
4873+ return NF_ACCEPT;
4874+ }
4875+ port = port * 10 + ( *data - 48 );
4876+ }
4877+
4878+ /* dont relate sessions that try to expose the client */
4879+ DEBUGP("found port %u\n", port);
4880+ if (port > 1023) {
4881+ DEBUGP("skipping, expected port size is greater than 1023!\n");
4882+ return NF_ACCEPT;
4883+ }
4884+
4885+
4886+ LOCK_BH(&ip_rsh_lock);
4887+
4888+ /* new(,related) connection is;
4889+ * reply + dst (uint)port + src port (0:1023)
4890+ */
4891+ memset(&expect, 0, sizeof(expect));
4892+
4893+ /* save some discovered data, in case someone ever wants to write
4894+ * a NAT module for this bastard ..
4895+ */
4896+ exp_rsh_info->port = port;
4897+
4898+ DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4899+
4900+
4901+ /* Watch out, Radioactive-Man! */
4902+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4903+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4904+ exp->tuple.src.u.tcp.port = 0;
4905+ exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4906+ exp->tuple.dst.protonum = IPPROTO_TCP;
4907+
4908+ exp->mask.src.ip = 0xffffffff;
4909+ exp->mask.dst.ip = 0xffffffff;
4910+
4911+ exp->mask.src.u.tcp.port = htons(0xfc00);
4912+ exp->mask.dst.u.tcp.port = htons(0xfc00);
4913+ exp->mask.dst.protonum = 0xffff;
4914+
4915+ exp->expectfn = NULL;
4916+
4917+ ip_conntrack_expect_related(ct, &expect);
4918+
4919+ DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4920+ NIPQUAD(exp->tuple.src.ip),
4921+ ntohs(exp->tuple.src.u.tcp.port),
4922+ NIPQUAD(exp->tuple.dst.ip),
4923+ ntohs(exp->tuple.dst.u.tcp.port));
4924+
4925+ DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4926+ NIPQUAD(exp->mask.src.ip),
4927+ ntohs(exp->mask.src.u.tcp.port),
4928+ NIPQUAD(exp->mask.dst.ip),
4929+ ntohs(exp->mask.dst.u.tcp.port));
4930+ UNLOCK_BH(&ip_rsh_lock);
4931+
4932+ return NF_ACCEPT;
4933+}
4934+
4935+static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4936+
4937+static void fini(void);
4938+
4939+static int __init init(void)
4940+{
4941+ int port, ret;
4942+ static char name[10];
4943+
4944+
4945+ /* If no port given, default to standard RSH port */
4946+ if (ports[0] == 0)
4947+ ports[0] = RSH_PORT;
4948+
4949+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4950+ memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4951+
4952+ if (ports[port] == RSH_PORT)
4953+ sprintf(name, "rsh");
4954+ else
4955+ sprintf(name, "rsh-%d", port);
4956+
4957+ rsh_helpers[port].name = name;
4958+ rsh_helpers[port].me = THIS_MODULE;
4959+ rsh_helpers[port].max_expected = 1;
4960+ rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4961+ rsh_helpers[port].timeout = 0;
4962+
4963+ rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4964+ rsh_helpers[port].mask.dst.protonum = 0xffff;
4965+
4966+ /* RSH must come from ports 0:1023 to ports[port] (514) */
4967+ rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4968+ rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4969+ rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4970+
4971+ rsh_helpers[port].help = help;
4972+
4973+ DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4974+ DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4975+ NIPQUAD(rsh_helpers[port].tuple.src.ip),
4976+ ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4977+ NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4978+ ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4979+ DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4980+ NIPQUAD(rsh_helpers[port].mask.src.ip),
4981+ ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4982+ NIPQUAD(rsh_helpers[port].mask.dst.ip),
4983+ ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4984+
4985+ ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4986+
4987+ if (ret) {
4988+ printk("ERROR registering port %d\n",
4989+ ports[port]);
4990+ fini();
4991+ return -EBUSY;
4992+ }
4993+ ports_n_c++;
4994+ }
4995+ return 0;
4996+}
4997+
4998+/* This function is intentionally _NOT_ defined as __exit, because
4999+ * it is needed by the init function */
5000+static void fini(void)
5001+{
5002+ int port;
5003+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5004+ DEBUGP("unregistering port %d\n", ports[port]);
5005+ ip_conntrack_helper_unregister(&rsh_helpers[port]);
5006+ }
5007+}
5008+
5009+module_init(init);
5010+module_exit(fini);
5011diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
5012--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
5013+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-04-30 09:14:05.000000000 +0200
5014@@ -0,0 +1,507 @@
5015+/*
5016+ * RTSP extension for IP connection tracking
5017+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
5018+ * based on ip_conntrack_irc.c
5019+ *
5020+ * This program is free software; you can redistribute it and/or
5021+ * modify it under the terms of the GNU General Public License
5022+ * as published by the Free Software Foundation; either version
5023+ * 2 of the License, or (at your option) any later version.
5024+ *
5025+ * Module load syntax:
5026+ * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5027+ * max_outstanding=n setup_timeout=secs
5028+ *
5029+ * If no ports are specified, the default will be port 554.
5030+ *
5031+ * With max_outstanding you can define the maximum number of not yet
5032+ * answered SETUP requests per RTSP session (default 8).
5033+ * With setup_timeout you can specify how long the system waits for
5034+ * an expected data channel (default 300 seconds).
5035+ */
5036+
5037+#include <linux/config.h>
5038+#include <linux/module.h>
5039+#include <linux/netfilter.h>
5040+#include <linux/ip.h>
5041+#include <net/checksum.h>
5042+#include <net/tcp.h>
5043+
5044+#include <linux/netfilter_ipv4/lockhelp.h>
5045+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5046+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5047+
5048+#include <linux/ctype.h>
5049+#define NF_NEED_STRNCASECMP
5050+#define NF_NEED_STRTOU16
5051+#define NF_NEED_STRTOU32
5052+#define NF_NEED_NEXTLINE
5053+#include <linux/netfilter_helpers.h>
5054+#define NF_NEED_MIME_NEXTLINE
5055+#include <linux/netfilter_mime.h>
5056+
5057+#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5058+
5059+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5060+#ifdef IP_NF_RTSP_DEBUG
5061+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5062+#else
5063+#define DEBUGP(fmt, args...)
5064+#endif
5065+
5066+#define MAX_PORTS 8
5067+static int ports[MAX_PORTS];
5068+static int num_ports = 0;
5069+static int max_outstanding = 8;
5070+static unsigned int setup_timeout = 300;
5071+
5072+MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5073+MODULE_DESCRIPTION("RTSP connection tracking module");
5074+MODULE_LICENSE("GPL");
5075+#ifdef MODULE_PARM
5076+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5077+MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5078+MODULE_PARM(max_outstanding, "i");
5079+MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5080+MODULE_PARM(setup_timeout, "i");
5081+MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5082+#endif
5083+
5084+DECLARE_LOCK(ip_rtsp_lock);
5085+struct module* ip_conntrack_rtsp = THIS_MODULE;
5086+
5087+/*
5088+ * Max mappings we will allow for one RTSP connection (for RTP, the number
5089+ * of allocated ports is twice this value). Note that SMIL burns a lot of
5090+ * ports so keep this reasonably high. If this is too low, you will see a
5091+ * lot of "no free client map entries" messages.
5092+ */
5093+#define MAX_PORT_MAPS 16
5094+
5095+/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5096+
5097+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5098+
5099+/*
5100+ * Parse an RTSP packet.
5101+ *
5102+ * Returns zero if parsing failed.
5103+ *
5104+ * Parameters:
5105+ * IN ptcp tcp data pointer
5106+ * IN tcplen tcp data len
5107+ * IN/OUT ptcpoff points to current tcp offset
5108+ * OUT phdrsoff set to offset of rtsp headers
5109+ * OUT phdrslen set to length of rtsp headers
5110+ * OUT pcseqoff set to offset of CSeq header
5111+ * OUT pcseqlen set to length of CSeq header
5112+ */
5113+static int
5114+rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5115+ uint* phdrsoff, uint* phdrslen,
5116+ uint* pcseqoff, uint* pcseqlen)
5117+{
5118+ uint entitylen = 0;
5119+ uint lineoff;
5120+ uint linelen;
5121+
5122+ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5123+ {
5124+ return 0;
5125+ }
5126+
5127+ *phdrsoff = *ptcpoff;
5128+ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5129+ {
5130+ if (linelen == 0)
5131+ {
5132+ if (entitylen > 0)
5133+ {
5134+ *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5135+ }
5136+ break;
5137+ }
5138+ if (lineoff+linelen > tcplen)
5139+ {
5140+ INFOP("!! overrun !!\n");
5141+ break;
5142+ }
5143+
5144+ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5145+ {
5146+ *pcseqoff = lineoff;
5147+ *pcseqlen = linelen;
5148+ }
5149+ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5150+ {
5151+ uint off = lineoff+15;
5152+ SKIP_WSPACE(ptcp+lineoff, linelen, off);
5153+ nf_strtou32(ptcp+off, &entitylen);
5154+ }
5155+ }
5156+ *phdrslen = (*ptcpoff) - (*phdrsoff);
5157+
5158+ return 1;
5159+}
5160+
5161+/*
5162+ * Find lo/hi client ports (if any) in transport header
5163+ * In:
5164+ * ptcp, tcplen = packet
5165+ * tranoff, tranlen = buffer to search
5166+ *
5167+ * Out:
5168+ * pport_lo, pport_hi = lo/hi ports (host endian)
5169+ *
5170+ * Returns nonzero if any client ports found
5171+ *
5172+ * Note: it is valid (and expected) for the client to request multiple
5173+ * transports, so we need to parse the entire line.
5174+ */
5175+static int
5176+rtsp_parse_transport(char* ptran, uint tranlen,
5177+ struct ip_ct_rtsp_expect* prtspexp)
5178+{
5179+ int rc = 0;
5180+ uint off = 0;
5181+
5182+ if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5183+ nf_strncasecmp(ptran, "Transport:", 10) != 0)
5184+ {
5185+ INFOP("sanity check failed\n");
5186+ return 0;
5187+ }
5188+ DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5189+ off += 10;
5190+ SKIP_WSPACE(ptran, tranlen, off);
5191+
5192+ /* Transport: tran;field;field=val,tran;field;field=val,... */
5193+ while (off < tranlen)
5194+ {
5195+ const char* pparamend;
5196+ uint nextparamoff;
5197+
5198+ pparamend = memchr(ptran+off, ',', tranlen-off);
5199+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5200+ nextparamoff = pparamend-ptran;
5201+
5202+ while (off < nextparamoff)
5203+ {
5204+ const char* pfieldend;
5205+ uint nextfieldoff;
5206+
5207+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5208+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5209+
5210+ if (strncmp(ptran+off, "client_port=", 12) == 0)
5211+ {
5212+ u_int16_t port;
5213+ uint numlen;
5214+
5215+ off += 12;
5216+ numlen = nf_strtou16(ptran+off, &port);
5217+ off += numlen;
5218+ if (prtspexp->loport != 0 && prtspexp->loport != port)
5219+ {
5220+ DEBUGP("multiple ports found, port %hu ignored\n", port);
5221+ }
5222+ else
5223+ {
5224+ prtspexp->loport = prtspexp->hiport = port;
5225+ if (ptran[off] == '-')
5226+ {
5227+ off++;
5228+ numlen = nf_strtou16(ptran+off, &port);
5229+ off += numlen;
5230+ prtspexp->pbtype = pb_range;
5231+ prtspexp->hiport = port;
5232+
5233+ // If we have a range, assume rtp:
5234+ // loport must be even, hiport must be loport+1
5235+ if ((prtspexp->loport & 0x0001) != 0 ||
5236+ prtspexp->hiport != prtspexp->loport+1)
5237+ {
5238+ DEBUGP("incorrect range: %hu-%hu, correcting\n",
5239+ prtspexp->loport, prtspexp->hiport);
5240+ prtspexp->loport &= 0xfffe;
5241+ prtspexp->hiport = prtspexp->loport+1;
5242+ }
5243+ }
5244+ else if (ptran[off] == '/')
5245+ {
5246+ off++;
5247+ numlen = nf_strtou16(ptran+off, &port);
5248+ off += numlen;
5249+ prtspexp->pbtype = pb_discon;
5250+ prtspexp->hiport = port;
5251+ }
5252+ rc = 1;
5253+ }
5254+ }
5255+
5256+ /*
5257+ * Note we don't look for the destination parameter here.
5258+ * If we are using NAT, the NAT module will handle it. If not,
5259+ * and the client is sending packets elsewhere, the expectation
5260+ * will quietly time out.
5261+ */
5262+
5263+ off = nextfieldoff;
5264+ }
5265+
5266+ off = nextparamoff;
5267+ }
5268+
5269+ return rc;
5270+}
5271+
5272+/*** conntrack functions ***/
5273+
5274+/* outbound packet: client->server */
5275+static int
5276+help_out(const struct iphdr* iph, size_t pktlen,
5277+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5278+{
5279+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5280+ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5281+ uint tcplen = pktlen - iph->ihl * 4;
5282+ char* pdata = (char*)tcph + tcph->doff * 4;
5283+ uint datalen = tcplen - tcph->doff * 4;
5284+ uint dataoff = 0;
5285+
5286+ struct ip_conntrack_expect exp;
5287+
5288+ while (dataoff < datalen)
5289+ {
5290+ uint cmdoff = dataoff;
5291+ uint hdrsoff = 0;
5292+ uint hdrslen = 0;
5293+ uint cseqoff = 0;
5294+ uint cseqlen = 0;
5295+ uint lineoff = 0;
5296+ uint linelen = 0;
5297+ uint off;
5298+ int rc;
5299+
5300+ if (!rtsp_parse_message(pdata, datalen, &dataoff,
5301+ &hdrsoff, &hdrslen,
5302+ &cseqoff, &cseqlen))
5303+ {
5304+ break; /* not a valid message */
5305+ }
5306+
5307+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5308+ {
5309+ continue; /* not a SETUP message */
5310+ }
5311+ DEBUGP("found a setup message\n");
5312+
5313+ memset(&exp, 0, sizeof(exp));
5314+
5315+ off = 0;
5316+ while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5317+ &lineoff, &linelen))
5318+ {
5319+ if (linelen == 0)
5320+ {
5321+ break;
5322+ }
5323+ if (off > hdrsoff+hdrslen)
5324+ {
5325+ INFOP("!! overrun !!");
5326+ break;
5327+ }
5328+
5329+ if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5330+ {
5331+ rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5332+ &exp.help.exp_rtsp_info);
5333+ }
5334+ }
5335+
5336+ if (exp.help.exp_rtsp_info.loport == 0)
5337+ {
5338+ DEBUGP("no udp transports found\n");
5339+ continue; /* no udp transports found */
5340+ }
5341+
5342+ DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5343+ (int)exp.help.exp_rtsp_info.pbtype,
5344+ exp.help.exp_rtsp_info.loport,
5345+ exp.help.exp_rtsp_info.hiport);
5346+
5347+ LOCK_BH(&ip_rtsp_lock);
5348+ exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5349+ exp.help.exp_rtsp_info.len = hdrslen;
5350+
5351+ exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5352+ exp.mask.src.ip = 0xffffffff;
5353+ exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5354+ exp.mask.dst.ip = 0xffffffff;
5355+ exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5356+ exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5357+ exp.tuple.dst.protonum = IPPROTO_UDP;
5358+ exp.mask.dst.protonum = 0xffff;
5359+
5360+ DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5361+ NIPQUAD(exp.tuple.src.ip),
5362+ ntohs(exp.tuple.src.u.tcp.port),
5363+ NIPQUAD(exp.tuple.dst.ip),
5364+ ntohs(exp.tuple.dst.u.tcp.port));
5365+
5366+ /* pass the request off to the nat helper */
5367+ rc = ip_conntrack_expect_related(ct, &exp);
5368+ UNLOCK_BH(&ip_rtsp_lock);
5369+ if (rc == 0)
5370+ {
5371+ DEBUGP("ip_conntrack_expect_related succeeded\n");
5372+ }
5373+ else
5374+ {
5375+ INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5376+ }
5377+ }
5378+
5379+ return NF_ACCEPT;
5380+}
5381+
5382+/* inbound packet: server->client */
5383+static int
5384+help_in(const struct iphdr* iph, size_t pktlen,
5385+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5386+{
5387+ return NF_ACCEPT;
5388+}
5389+
5390+static int
5391+help(const struct iphdr* iph, size_t pktlen,
5392+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5393+{
5394+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5395+ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5396+ u_int32_t tcplen = pktlen - iph->ihl * 4;
5397+
5398+ /* Until there's been traffic both ways, don't look in packets. */
5399+ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5400+ {
5401+ DEBUGP("conntrackinfo = %u\n", ctinfo);
5402+ return NF_ACCEPT;
5403+ }
5404+
5405+ /* Not whole TCP header? */
5406+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5407+ {
5408+ DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5409+ return NF_ACCEPT;
5410+ }
5411+
5412+ /* Checksum invalid? Ignore. */
5413+ /* FIXME: Source route IP option packets --RR */
5414+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5415+ csum_partial((char*)tcph, tcplen, 0)))
5416+ {
5417+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5418+ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5419+ return NF_ACCEPT;
5420+ }
5421+
5422+ switch (CTINFO2DIR(ctinfo))
5423+ {
5424+ case IP_CT_DIR_ORIGINAL:
5425+ help_out(iph, pktlen, ct, ctinfo);
5426+ break;
5427+ case IP_CT_DIR_REPLY:
5428+ help_in(iph, pktlen, ct, ctinfo);
5429+ break;
5430+ }
5431+
5432+ return NF_ACCEPT;
5433+}
5434+
5435+static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5436+static char rtsp_names[MAX_PORTS][10];
5437+
5438+/* This function is intentionally _NOT_ defined as __exit */
5439+static void
5440+fini(void)
5441+{
5442+ int i;
5443+ for (i = 0; i < num_ports; i++)
5444+ {
5445+ DEBUGP("unregistering port %d\n", ports[i]);
5446+ ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5447+ }
5448+}
5449+
5450+static int __init
5451+init(void)
5452+{
5453+ int i, ret;
5454+ struct ip_conntrack_helper *hlpr;
5455+ char *tmpname;
5456+
5457+ printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5458+
5459+ if (max_outstanding < 1)
5460+ {
5461+ printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5462+ return -EBUSY;
5463+ }
5464+ if (setup_timeout < 0)
5465+ {
5466+ printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5467+ return -EBUSY;
5468+ }
5469+
5470+ /* If no port given, default to standard rtsp port */
5471+ if (ports[0] == 0)
5472+ {
5473+ ports[0] = RTSP_PORT;
5474+ }
5475+
5476+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5477+ {
5478+ hlpr = &rtsp_helpers[i];
5479+ memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5480+ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5481+ hlpr->tuple.dst.protonum = IPPROTO_TCP;
5482+ hlpr->mask.src.u.tcp.port = 0xFFFF;
5483+ hlpr->mask.dst.protonum = 0xFFFF;
5484+ hlpr->max_expected = max_outstanding;
5485+ hlpr->timeout = setup_timeout;
5486+ hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5487+ hlpr->me = ip_conntrack_rtsp;
5488+ hlpr->help = help;
5489+
5490+ tmpname = &rtsp_names[i][0];
5491+ if (ports[i] == RTSP_PORT)
5492+ {
5493+ sprintf(tmpname, "rtsp");
5494+ }
5495+ else
5496+ {
5497+ sprintf(tmpname, "rtsp-%d", i);
5498+ }
5499+ hlpr->name = tmpname;
5500+
5501+ DEBUGP("port #%d: %d\n", i, ports[i]);
5502+
5503+ ret = ip_conntrack_helper_register(hlpr);
5504+
5505+ if (ret)
5506+ {
5507+ printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5508+ fini();
5509+ return -EBUSY;
5510+ }
5511+ num_ports++;
5512+ }
5513+ return 0;
5514+}
5515+
5516+#ifdef CONFIG_IP_NF_NAT_NEEDED
5517+EXPORT_SYMBOL(ip_rtsp_lock);
5518+#endif
5519+
5520+module_init(init);
5521+module_exit(fini);
5522diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
5523--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-28 03:35:45.000000000 +0200
5524+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-30 09:12:41.000000000 +0200
5525@@ -110,6 +110,9 @@
5526 len += sprintf(buffer + len, "[ASSURED] ");
5527 len += sprintf(buffer + len, "use=%u ",
5528 atomic_read(&conntrack->ct_general.use));
5529+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5530+ len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5531+#endif
5532 len += sprintf(buffer + len, "\n");
5533
5534 return len;
5535@@ -633,6 +636,7 @@
5536 EXPORT_SYMBOL(ip_conntrack_alter_reply);
5537 EXPORT_SYMBOL(ip_conntrack_destroyed);
5538 EXPORT_SYMBOL(ip_conntrack_get);
5539+EXPORT_SYMBOL(__ip_conntrack_confirm);
5540 EXPORT_SYMBOL(need_ip_conntrack);
5541 EXPORT_SYMBOL(ip_conntrack_helper_register);
5542 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5543diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
5544--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
5545+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c 2004-04-30 09:14:39.000000000 +0200
5546@@ -0,0 +1,360 @@
5547+/*
5548+ * talk extension for IP connection tracking.
5549+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5550+ *
5551+ * This program is free software; you can redistribute it and/or
5552+ * modify it under the terms of the GNU General Public License
5553+ * as published by the Free Software Foundation; either version
5554+ * 2 of the License, or (at your option) any later version.
5555+ **
5556+ * Module load syntax:
5557+ * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5558+ *
5559+ * talk=[0|1] disable|enable old talk support
5560+ * ntalk=[0|1] disable|enable ntalk support
5561+ * ntalk2=[0|1] disable|enable ntalk2 support
5562+ *
5563+ * The default is talk=1 ntalk=1 ntalk2=1
5564+ *
5565+ * The helper does not support simultaneous talk requests.
5566+ **
5567+ *
5568+ * ASCII art on talk protocols
5569+ *
5570+ *
5571+ * caller server callee server
5572+ * | \ /
5573+ * | \ /
5574+ * | \ /
5575+ * | /
5576+ * | / \
5577+ * 2 | 1 / \ 3
5578+ * caller client ----------- callee client
5579+ * 4
5580+ *
5581+ * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
5582+ * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5583+ * 3. callee client <-> caller server: LOOK_UP invitation
5584+ * 4. callee client <-> caller client: talk data channel
5585+ *
5586+ * [1]: M. Hunter, talk: a historical protocol for interactive communication
5587+ * draft-hunter-talk-00.txt
5588+ * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
5589+ */
5590+#include <linux/config.h>
5591+#include <linux/module.h>
5592+#include <linux/netfilter.h>
5593+#include <linux/ip.h>
5594+#include <net/checksum.h>
5595+#include <net/udp.h>
5596+
5597+#include <linux/netfilter_ipv4/lockhelp.h>
5598+#include <linux/netfilter_ipv4/ip_conntrack.h>
5599+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5600+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5601+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5602+
5603+/* Default all talk protocols are supported */
5604+static int talk = 1;
5605+static int ntalk = 1;
5606+static int ntalk2 = 1;
5607+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5608+MODULE_DESCRIPTION("talk connection tracking module");
5609+MODULE_LICENSE("GPL");
5610+#ifdef MODULE_PARM
5611+MODULE_PARM(talk, "i");
5612+MODULE_PARM_DESC(talk, "support (old) talk protocol");
5613+MODULE_PARM(ntalk, "i");
5614+MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5615+MODULE_PARM(ntalk2, "i");
5616+MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5617+#endif
5618+
5619+DECLARE_LOCK(ip_talk_lock);
5620+struct module *ip_conntrack_talk = THIS_MODULE;
5621+
5622+#if 0
5623+#define DEBUGP printk
5624+#else
5625+#define DEBUGP(format, args...)
5626+#endif
5627+
5628+static int talk_expect(struct ip_conntrack *ct);
5629+static int ntalk_expect(struct ip_conntrack *ct);
5630+
5631+static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
5632+
5633+static int talk_help_response(const struct iphdr *iph, size_t len,
5634+ struct ip_conntrack *ct,
5635+ enum ip_conntrack_info ctinfo,
5636+ int talk_port,
5637+ u_char mode,
5638+ u_char type,
5639+ u_char answer,
5640+ struct talk_addr *addr)
5641+{
5642+ int dir = CTINFO2DIR(ctinfo);
5643+ struct ip_conntrack_expect expect, *exp = &expect;
5644+ struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
5645+
5646+ DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
5647+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5648+ type, answer);
5649+
5650+ if (!(answer == SUCCESS && type == mode))
5651+ return NF_ACCEPT;
5652+
5653+ memset(&expect, 0, sizeof(expect));
5654+
5655+ if (type == ANNOUNCE) {
5656+
5657+ DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
5658+
5659+ /* update the talk info */
5660+ LOCK_BH(&ip_talk_lock);
5661+ exp_talk_info->port = htons(talk_port);
5662+
5663+ /* expect callee client -> caller server message */
5664+ exp->tuple = ((struct ip_conntrack_tuple)
5665+ { { ct->tuplehash[dir].tuple.src.ip,
5666+ { 0 } },
5667+ { ct->tuplehash[dir].tuple.dst.ip,
5668+ { .tcp = { htons(talk_port) } },
5669+ IPPROTO_UDP }});
5670+ exp->mask = ((struct ip_conntrack_tuple)
5671+ { { 0xFFFFFFFF, { 0 } },
5672+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
5673+
5674+ exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
5675+
5676+ DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
5677+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
5678+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
5679+
5680+ /* Ignore failure; should only happen with NAT */
5681+ ip_conntrack_expect_related(ct, &expect);
5682+ UNLOCK_BH(&ip_talk_lock);
5683+ }
5684+ if (type == LOOK_UP) {
5685+
5686+ DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
5687+
5688+ /* update the talk info */
5689+ LOCK_BH(&ip_talk_lock);
5690+ exp_talk_info->port = addr->ta_port;
5691+
5692+ /* expect callee client -> caller client connection */
5693+ exp->tuple = ((struct ip_conntrack_tuple)
5694+ { { ct->tuplehash[!dir].tuple.src.ip,
5695+ { 0 } },
5696+ { addr->ta_addr,
5697+ { addr->ta_port },
5698+ IPPROTO_TCP }});
5699+ exp->mask = ((struct ip_conntrack_tuple)
5700+ { { 0xFFFFFFFF, { 0 } },
5701+ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5702+
5703+ exp->expectfn = NULL;
5704+
5705+ DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
5706+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
5707+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
5708+
5709+ /* Ignore failure; should only happen with NAT */
5710+ ip_conntrack_expect_related(ct, &expect);
5711+ UNLOCK_BH(&ip_talk_lock);
5712+ }
5713+
5714+ return NF_ACCEPT;
5715+}
5716+
5717+/* FIXME: This should be in userspace. Later. */
5718+static int talk_help(const struct iphdr *iph, size_t len,
5719+ struct ip_conntrack *ct,
5720+ enum ip_conntrack_info ctinfo,
5721+ int talk_port,
5722+ u_char mode)
5723+{
5724+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
5725+ const char *data = (const char *)udph + sizeof(struct udphdr);
5726+ int dir = CTINFO2DIR(ctinfo);
5727+ size_t udplen;
5728+
5729+ DEBUGP("ip_ct_talk_help: help entered\n");
5730+
5731+ /* Until there's been traffic both ways, don't look in packets. */
5732+ if (ctinfo != IP_CT_ESTABLISHED
5733+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5734+ DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
5735+ return NF_ACCEPT;
5736+ }
5737+
5738+ /* Not whole UDP header? */
5739+ udplen = len - iph->ihl * 4;
5740+ if (udplen < sizeof(struct udphdr)) {
5741+ DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
5742+ return NF_ACCEPT;
5743+ }
5744+
5745+ /* Checksum invalid? Ignore. */
5746+ /* FIXME: Source route IP option packets --RR */
5747+ if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5748+ csum_partial((char *)udph, udplen, 0))) {
5749+ DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5750+ udph, udplen, NIPQUAD(iph->saddr),
5751+ NIPQUAD(iph->daddr));
5752+ return NF_ACCEPT;
5753+ }
5754+
5755+ DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5756+ NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
5757+
5758+ if (dir == IP_CT_DIR_ORIGINAL)
5759+ return NF_ACCEPT;
5760+
5761+ if (talk_port == TALK_PORT
5762+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
5763+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5764+ ((struct talk_response *)data)->type,
5765+ ((struct talk_response *)data)->answer,
5766+ &(((struct talk_response *)data)->addr));
5767+ else if (talk_port == NTALK_PORT
5768+ && ntalk
5769+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5770+ && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5771+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5772+ ((struct ntalk_response *)data)->type,
5773+ ((struct ntalk_response *)data)->answer,
5774+ &(((struct ntalk_response *)data)->addr));
5775+ else if (talk_port == NTALK_PORT
5776+ && ntalk2
5777+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5778+ && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5779+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5780+ ((struct ntalk2_response *)data)->type,
5781+ ((struct ntalk2_response *)data)->answer,
5782+ &(((struct ntalk2_response *)data)->addr));
5783+ else {
5784+ DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
5785+ (unsigned)udplen - sizeof(struct udphdr),
5786+ sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5787+ return NF_ACCEPT;
5788+ }
5789+}
5790+
5791+static int lookup_help(const struct iphdr *iph, size_t len,
5792+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5793+{
5794+ return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5795+}
5796+
5797+static int lookup_nhelp(const struct iphdr *iph, size_t len,
5798+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5799+{
5800+ return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5801+}
5802+
5803+static struct ip_conntrack_helper lookup_helpers[2] =
5804+ { { { NULL, NULL },
5805+ "talk", /* name */
5806+ 0, /* flags */
5807+ NULL, /* module */
5808+ 1, /* max_expected */
5809+ 240, /* timeout */
5810+ { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5811+ { 0, { 0 }, IPPROTO_UDP } },
5812+ { { 0, { 0xFFFF } }, /* mask */
5813+ { 0, { 0 }, 0xFFFF } },
5814+ lookup_help }, /* helper */
5815+ { { NULL, NULL },
5816+ "ntalk", /* name */
5817+ 0, /* flags */
5818+ NULL, /* module */
5819+ 1, /* max_expected */
5820+ 240, /* timeout */
5821+ { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5822+ { 0, { 0 }, IPPROTO_UDP } },
5823+ { { 0, { 0xFFFF } }, /* mask */
5824+ { 0, { 0 }, 0xFFFF } },
5825+ lookup_nhelp } /* helper */
5826+ };
5827+
5828+static int talk_expect(struct ip_conntrack *ct)
5829+{
5830+ DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5831+ WRITE_LOCK(&ip_conntrack_lock);
5832+ ct->helper = &lookup_helpers[0];
5833+ WRITE_UNLOCK(&ip_conntrack_lock);
5834+
5835+ return NF_ACCEPT; /* unused */
5836+}
5837+
5838+static int ntalk_expect(struct ip_conntrack *ct)
5839+{
5840+ DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5841+ WRITE_LOCK(&ip_conntrack_lock);
5842+ ct->helper = &lookup_helpers[1];
5843+ WRITE_UNLOCK(&ip_conntrack_lock);
5844+
5845+ return NF_ACCEPT; /* unused */
5846+}
5847+
5848+static int help(const struct iphdr *iph, size_t len,
5849+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5850+{
5851+ return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5852+}
5853+
5854+static int nhelp(const struct iphdr *iph, size_t len,
5855+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5856+{
5857+ return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5858+}
5859+
5860+static struct ip_conntrack_helper talk_helpers[2] =
5861+ { { { NULL, NULL },
5862+ "talk", /* name */
5863+ 0, /* flags */
5864+ THIS_MODULE, /* module */
5865+ 1, /* max_expected */
5866+ 240, /* timeout */
5867+ { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5868+ { 0, { 0 }, IPPROTO_UDP } },
5869+ { { 0, { 0xFFFF } }, /* mask */
5870+ { 0, { 0 }, 0xFFFF } },
5871+ help }, /* helper */
5872+ { { NULL, NULL },
5873+ "ntalk", /* name */
5874+ 0, /* flags */
5875+ THIS_MODULE, /* module */
5876+ 1, /* max_expected */
5877+ 240, /* timeout */
5878+ { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5879+ { 0, { 0 }, IPPROTO_UDP } },
5880+ { { 0, { 0xFFFF } }, /* mask */
5881+ { 0, { 0 }, 0xFFFF } },
5882+ nhelp } /* helper */
5883+ };
5884+
5885+static int __init init(void)
5886+{
5887+ if (talk > 0)
5888+ ip_conntrack_helper_register(&talk_helpers[0]);
5889+ if (ntalk > 0 || ntalk2 > 0)
5890+ ip_conntrack_helper_register(&talk_helpers[1]);
5891+
5892+ return 0;
5893+}
5894+
5895+static void __exit fini(void)
5896+{
5897+ if (talk > 0)
5898+ ip_conntrack_helper_unregister(&talk_helpers[0]);
5899+ if (ntalk > 0 || ntalk2 > 0)
5900+ ip_conntrack_helper_unregister(&talk_helpers[1]);
5901+}
5902+
5903+EXPORT_SYMBOL(ip_talk_lock);
5904+
5905+module_init(init);
5906+module_exit(fini);
5907diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c
5908--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c 2004-04-28 03:35:10.000000000 +0200
5909+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c 2004-04-30 09:09:25.000000000 +0200
5910@@ -816,7 +816,7 @@
5911
5912 /* Have to grab read lock before sibling_list traversal */
5913 READ_LOCK(&ip_conntrack_lock);
5914- list_for_each(cur_item, &ct->sibling_list) {
5915+ list_for_each_prev(cur_item, &ct->sibling_list) {
5916 exp = list_entry(cur_item, struct ip_conntrack_expect,
5917 expected_list);
5918
5919diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c
5920--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
5921+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c 2004-04-30 09:12:34.000000000 +0200
5922@@ -0,0 +1,419 @@
5923+/*
5924+ * H.323 'brute force' extension for NAT alteration.
5925+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5926+ *
5927+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
5928+ * (http://www.coritel.it/projects/sofia/nat.html)
5929+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
5930+ * the unregistered helpers to the conntrack entries.
5931+ */
5932+
5933+
5934+#include <linux/module.h>
5935+#include <linux/netfilter.h>
5936+#include <linux/ip.h>
5937+#include <net/checksum.h>
5938+#include <net/tcp.h>
5939+
5940+#include <linux/netfilter_ipv4/lockhelp.h>
5941+#include <linux/netfilter_ipv4/ip_nat.h>
5942+#include <linux/netfilter_ipv4/ip_nat_helper.h>
5943+#include <linux/netfilter_ipv4/ip_nat_rule.h>
5944+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
5945+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5946+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
5947+
5948+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5949+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
5950+MODULE_LICENSE("GPL");
5951+
5952+DECLARE_LOCK_EXTERN(ip_h323_lock);
5953+struct module *ip_nat_h323 = THIS_MODULE;
5954+
5955+#if 0
5956+#define DEBUGP printk
5957+#else
5958+#define DEBUGP(format, args...)
5959+#endif
5960+
5961+/* FIXME: Time out? --RR */
5962+
5963+static unsigned int
5964+h225_nat_expected(struct sk_buff **pskb,
5965+ unsigned int hooknum,
5966+ struct ip_conntrack *ct,
5967+ struct ip_nat_info *info);
5968+
5969+static unsigned int h225_nat_help(struct ip_conntrack *ct,
5970+ struct ip_conntrack_expect *exp,
5971+ struct ip_nat_info *info,
5972+ enum ip_conntrack_info ctinfo,
5973+ unsigned int hooknum,
5974+ struct sk_buff **pskb);
5975+
5976+static struct ip_nat_helper h245 =
5977+ { { NULL, NULL },
5978+ "H.245", /* name */
5979+ 0, /* flags */
5980+ NULL, /* module */
5981+ { { 0, { 0 } }, /* tuple */
5982+ { 0, { 0 }, IPPROTO_TCP } },
5983+ { { 0, { 0xFFFF } }, /* mask */
5984+ { 0, { 0 }, 0xFFFF } },
5985+ h225_nat_help, /* helper */
5986+ h225_nat_expected /* expectfn */
5987+ };
5988+
5989+static unsigned int
5990+h225_nat_expected(struct sk_buff **pskb,
5991+ unsigned int hooknum,
5992+ struct ip_conntrack *ct,
5993+ struct ip_nat_info *info)
5994+{
5995+ struct ip_nat_multi_range mr;
5996+ u_int32_t newdstip, newsrcip, newip;
5997+ u_int16_t port;
5998+ struct ip_ct_h225_expect *exp_info;
5999+ struct ip_ct_h225_master *master_info;
6000+ struct ip_conntrack *master = master_ct(ct);
6001+ unsigned int is_h225, ret;
6002+
6003+ IP_NF_ASSERT(info);
6004+ IP_NF_ASSERT(master);
6005+
6006+ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6007+
6008+ DEBUGP("h225_nat_expected: We have a connection!\n");
6009+ master_info = &ct->master->expectant->help.ct_h225_info;
6010+ exp_info = &ct->master->help.exp_h225_info;
6011+
6012+ LOCK_BH(&ip_h323_lock);
6013+
6014+ DEBUGP("master: ");
6015+ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6016+ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6017+ DEBUGP("conntrack: ");
6018+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6019+ if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6020+ /* Make connection go to the client. */
6021+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6022+ newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6023+ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6024+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
6025+ } else {
6026+ /* Make the connection go to the server */
6027+ newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6028+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6029+ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6030+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
6031+ }
6032+ port = exp_info->port;
6033+ is_h225 = master_info->is_h225 == H225_PORT;
6034+ UNLOCK_BH(&ip_h323_lock);
6035+
6036+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6037+ newip = newsrcip;
6038+ else
6039+ newip = newdstip;
6040+
6041+ DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6042+
6043+ mr.rangesize = 1;
6044+ /* We don't want to manip the per-protocol, just the IPs... */
6045+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6046+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
6047+
6048+ /* ... unless we're doing a MANIP_DST, in which case, make
6049+ sure we map to the correct port */
6050+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6051+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6052+ mr.range[0].min = mr.range[0].max
6053+ = ((union ip_conntrack_manip_proto)
6054+ { .tcp = { port } });
6055+ }
6056+
6057+ ret = ip_nat_setup_info(ct, &mr, hooknum);
6058+
6059+ if (is_h225) {
6060+ DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6061+ /* NAT expectfn called with ip_nat_lock write-locked */
6062+ info->helper = &h245;
6063+ }
6064+ return ret;
6065+}
6066+
6067+static int h323_signal_address_fixup(struct ip_conntrack *ct,
6068+ struct sk_buff **pskb,
6069+ enum ip_conntrack_info ctinfo)
6070+{
6071+ struct iphdr *iph = (*pskb)->nh.iph;
6072+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6073+ char *data = (char *) tcph + tcph->doff * 4;
6074+ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6075+ u_int32_t datalen = tcplen - tcph->doff*4;
6076+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6077+ u_int32_t newip;
6078+ u_int16_t port;
6079+ int i;
6080+
6081+ MUST_BE_LOCKED(&ip_h323_lock);
6082+
6083+ DEBUGP("h323_signal_address_fixup: %s %s\n",
6084+ between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6085+ ? "yes" : "no",
6086+ between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6087+ ? "yes" : "no");
6088+ if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6089+ || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6090+ return 1;
6091+
6092+ DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
6093+ info->offset[IP_CT_DIR_ORIGINAL],
6094+ info->offset[IP_CT_DIR_REPLY],
6095+ tcplen);
6096+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6097+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6098+
6099+ for (i = 0; i < IP_CT_DIR_MAX; i++) {
6100+ DEBUGP("h323_signal_address_fixup: %s %s\n",
6101+ info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6102+ i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6103+ if (!between(info->seq[i], ntohl(tcph->seq),
6104+ ntohl(tcph->seq) + datalen))
6105+ continue;
6106+ if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6107+ ntohl(tcph->seq) + datalen)) {
6108+ /* Partial retransmisison. It's a cracker being funky. */
6109+ if (net_ratelimit()) {
6110+ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6111+ info->seq[i],
6112+ ntohl(tcph->seq),
6113+ ntohl(tcph->seq) + datalen);
6114+ }
6115+ return 0;
6116+ }
6117+
6118+ /* Change address inside packet to match way we're mapping
6119+ this connection. */
6120+ if (i == IP_CT_DIR_ORIGINAL) {
6121+ newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6122+ port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6123+ } else {
6124+ newip = ct->tuplehash[!info->dir].tuple.src.ip;
6125+ port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6126+ }
6127+
6128+ DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
6129+ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6130+ NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6131+ ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6132+
6133+ /* Modify the packet */
6134+ *(u_int32_t *)(data + info->offset[i]) = newip;
6135+ *(u_int16_t *)(data + info->offset[i] + 4) = port;
6136+
6137+ DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6138+ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6139+ NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6140+ ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6141+ }
6142+
6143+ /* fix checksum information */
6144+
6145+ (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6146+ datalen, 0);
6147+
6148+ tcph->check = 0;
6149+ tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6150+ csum_partial((char *)tcph, tcph->doff*4,
6151+ (*pskb)->csum));
6152+ ip_send_check(iph);
6153+
6154+ return 1;
6155+}
6156+
6157+static int h323_data_fixup(struct ip_ct_h225_expect *info,
6158+ struct ip_conntrack *ct,
6159+ struct sk_buff **pskb,
6160+ enum ip_conntrack_info ctinfo,
6161+ struct ip_conntrack_expect *expect)
6162+{
6163+ u_int32_t newip;
6164+ u_int16_t port;
6165+ struct ip_conntrack_tuple newtuple;
6166+ struct iphdr *iph = (*pskb)->nh.iph;
6167+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6168+ char *data = (char *) tcph + tcph->doff * 4;
6169+ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6170+ struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6171+ int is_h225;
6172+
6173+ MUST_BE_LOCKED(&ip_h323_lock);
6174+ DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6175+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6176+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6177+
6178+ if (!between(expect->seq + 6, ntohl(tcph->seq),
6179+ ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6180+ /* Partial retransmisison. It's a cracker being funky. */
6181+ if (net_ratelimit()) {
6182+ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6183+ expect->seq,
6184+ ntohl(tcph->seq),
6185+ ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6186+ }
6187+ return 0;
6188+ }
6189+
6190+ /* Change address inside packet to match way we're mapping
6191+ this connection. */
6192+ if (info->dir == IP_CT_DIR_REPLY) {
6193+ /* Must be where client thinks server is */
6194+ newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6195+ /* Expect something from client->server */
6196+ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6197+ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6198+ } else {
6199+ /* Must be where server thinks client is */
6200+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6201+ /* Expect something from server->client */
6202+ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6203+ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6204+ }
6205+
6206+ is_h225 = (master_info->is_h225 == H225_PORT);
6207+
6208+ if (is_h225) {
6209+ newtuple.dst.protonum = IPPROTO_TCP;
6210+ newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6211+ } else {
6212+ newtuple.dst.protonum = IPPROTO_UDP;
6213+ newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6214+ }
6215+
6216+ /* Try to get same port: if not, try to change it. */
6217+ for (port = ntohs(info->port); port != 0; port++) {
6218+ if (is_h225)
6219+ newtuple.dst.u.tcp.port = htons(port);
6220+ else
6221+ newtuple.dst.u.udp.port = htons(port);
6222+
6223+ if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6224+ break;
6225+ }
6226+ if (port == 0) {
6227+ DEBUGP("h323_data_fixup: no free port found!\n");
6228+ return 0;
6229+ }
6230+
6231+ port = htons(port);
6232+
6233+ DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6234+ NIPQUAD(*((u_int32_t *)(data + info->offset))),
6235+ ntohs(*((u_int16_t *)(data + info->offset + 4))));
6236+
6237+ /* Modify the packet */
6238+ *(u_int32_t *)(data + info->offset) = newip;
6239+ *(u_int16_t *)(data + info->offset + 4) = port;
6240+
6241+ DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6242+ NIPQUAD(*((u_int32_t *)(data + info->offset))),
6243+ ntohs(*((u_int16_t *)(data + info->offset + 4))));
6244+
6245+ /* fix checksum information */
6246+ /* FIXME: usually repeated multiple times in the case of H.245! */
6247+
6248+ (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6249+ tcplen - tcph->doff*4, 0);
6250+
6251+ tcph->check = 0;
6252+ tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6253+ csum_partial((char *)tcph, tcph->doff*4,
6254+ (*pskb)->csum));
6255+ ip_send_check(iph);
6256+
6257+ return 1;
6258+}
6259+
6260+static unsigned int h225_nat_help(struct ip_conntrack *ct,
6261+ struct ip_conntrack_expect *exp,
6262+ struct ip_nat_info *info,
6263+ enum ip_conntrack_info ctinfo,
6264+ unsigned int hooknum,
6265+ struct sk_buff **pskb)
6266+{
6267+ int dir;
6268+ struct ip_ct_h225_expect *exp_info;
6269+
6270+ /* Only mangle things once: original direction in POST_ROUTING
6271+ and reply direction on PRE_ROUTING. */
6272+ dir = CTINFO2DIR(ctinfo);
6273+ DEBUGP("nat_h323: dir %s at hook %s\n",
6274+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6275+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6276+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6277+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6278+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6279+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6280+ DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6281+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6282+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6283+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6284+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6285+ return NF_ACCEPT;
6286+ }
6287+
6288+ if (!exp) {
6289+ LOCK_BH(&ip_h323_lock);
6290+ if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6291+ UNLOCK_BH(&ip_h323_lock);
6292+ return NF_DROP;
6293+ }
6294+ UNLOCK_BH(&ip_h323_lock);
6295+ return NF_ACCEPT;
6296+ }
6297+
6298+ exp_info = &exp->help.exp_h225_info;
6299+
6300+ LOCK_BH(&ip_h323_lock);
6301+ if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6302+ UNLOCK_BH(&ip_h323_lock);
6303+ return NF_DROP;
6304+ }
6305+ UNLOCK_BH(&ip_h323_lock);
6306+
6307+ return NF_ACCEPT;
6308+}
6309+
6310+static struct ip_nat_helper h225 =
6311+ { { NULL, NULL },
6312+ "H.225", /* name */
6313+ IP_NAT_HELPER_F_ALWAYS, /* flags */
6314+ THIS_MODULE, /* module */
6315+ { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
6316+ { 0, { 0 }, IPPROTO_TCP } },
6317+ { { 0, { .tcp = { 0xFFFF } } }, /* mask */
6318+ { 0, { 0 }, 0xFFFF } },
6319+ h225_nat_help, /* helper */
6320+ h225_nat_expected /* expectfn */
6321+ };
6322+
6323+static int __init init(void)
6324+{
6325+ int ret;
6326+
6327+ ret = ip_nat_helper_register(&h225);
6328+
6329+ if (ret != 0)
6330+ printk("ip_nat_h323: cannot initialize the module!\n");
6331+
6332+ return ret;
6333+}
6334+
6335+static void __exit fini(void)
6336+{
6337+ ip_nat_helper_unregister(&h225);
6338+}
6339+
6340+module_init(init);
6341+module_exit(fini);
6342diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c
6343--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6344+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c 2004-04-30 09:12:58.000000000 +0200
6345@@ -0,0 +1,350 @@
6346+/* MMS extension for TCP NAT alteration.
6347+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6348+ * based on ip_nat_ftp.c and ip_nat_irc.c
6349+ *
6350+ * ip_nat_mms.c v0.3 2002-09-22
6351+ *
6352+ * This program is free software; you can redistribute it and/or
6353+ * modify it under the terms of the GNU General Public License
6354+ * as published by the Free Software Foundation; either version
6355+ * 2 of the License, or (at your option) any later version.
6356+ *
6357+ * Module load syntax:
6358+ * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6359+ *
6360+ * Please give the ports of all MMS servers You wish to connect to.
6361+ * If you don't specify ports, the default will be TCP port 1755.
6362+ *
6363+ * More info on MMS protocol, firewalls and NAT:
6364+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6365+ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6366+ *
6367+ * The SDP project people are reverse-engineering MMS:
6368+ * http://get.to/sdp
6369+ */
6370+
6371+/* FIXME: issue with UDP & fragmentation with this URL:
6372+ http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6373+ may be related to out-of-order first packets:
6374+ basically the expectation is set up correctly, then the server sends
6375+ a first UDP packet which is fragmented plus arrives out-of-order.
6376+ the MASQUERADING firewall with ip_nat_mms loaded responds with
6377+ an ICMP unreachable back to the server */
6378+
6379+#include <linux/module.h>
6380+#include <linux/netfilter_ipv4.h>
6381+#include <linux/ip.h>
6382+#include <linux/tcp.h>
6383+#include <net/tcp.h>
6384+#include <linux/netfilter_ipv4/ip_nat.h>
6385+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6386+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6387+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6388+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6389+
6390+#if 0
6391+#define DEBUGP printk
6392+#define DUMP_BYTES(address, counter) \
6393+({ \
6394+ int temp_counter; \
6395+ for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6396+ DEBUGP("%u ", (u8)*(address+temp_counter)); \
6397+ }; \
6398+ DEBUGP("\n"); \
6399+})
6400+#else
6401+#define DEBUGP(format, args...)
6402+#define DUMP_BYTES(address, counter)
6403+#endif
6404+
6405+#define MAX_PORTS 8
6406+static int ports[MAX_PORTS];
6407+static int ports_c = 0;
6408+
6409+#ifdef MODULE_PARM
6410+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6411+#endif
6412+
6413+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6414+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6415+MODULE_LICENSE("GPL");
6416+
6417+DECLARE_LOCK_EXTERN(ip_mms_lock);
6418+
6419+/* FIXME: Time out? --RR */
6420+
6421+static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6422+ struct ip_conntrack *ct,
6423+ struct sk_buff **pskb,
6424+ enum ip_conntrack_info ctinfo,
6425+ struct ip_conntrack_expect *expect)
6426+{
6427+ u_int32_t newip;
6428+ struct ip_conntrack_tuple t;
6429+ struct iphdr *iph = (*pskb)->nh.iph;
6430+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6431+ char *data = (char *)tcph + tcph->doff * 4;
6432+ int i, j, k, port;
6433+ u_int16_t mms_proto;
6434+
6435+ u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6436+ u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6437+ u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6438+
6439+ int zero_padding;
6440+
6441+ char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6442+ char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6443+ char proto_string[6];
6444+
6445+ MUST_BE_LOCKED(&ip_mms_lock);
6446+
6447+ /* what was the protocol again ? */
6448+ mms_proto = expect->tuple.dst.protonum;
6449+ sprintf(proto_string, "%u", mms_proto);
6450+
6451+ DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6452+ expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6453+ mms_proto == IPPROTO_UDP ? "UDP"
6454+ : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6455+
6456+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6457+
6458+ /* Alter conntrack's expectations. */
6459+ t = expect->tuple;
6460+ t.dst.ip = newip;
6461+ for (port = ct_mms_info->port; port != 0; port++) {
6462+ t.dst.u.tcp.port = htons(port);
6463+ if (ip_conntrack_change_expect(expect, &t) == 0) {
6464+ DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6465+ break;
6466+ }
6467+ }
6468+
6469+ if(port == 0)
6470+ return 0;
6471+
6472+ sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6473+ NIPQUAD(newip),
6474+ expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6475+ : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6476+ port);
6477+ DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6478+
6479+ memset(unicode_buffer, 0, sizeof(char)*75);
6480+
6481+ for (i=0; i<strlen(buffer); ++i)
6482+ *(unicode_buffer+i*2)=*(buffer+i);
6483+
6484+ DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6485+ DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6486+ DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6487+
6488+ /* add end of packet to it */
6489+ for (j=0; j<ct_mms_info->padding; ++j) {
6490+ DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6491+ i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6492+ *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6493+ }
6494+
6495+ /* pad with zeroes at the end ? see explanation of weird math below */
6496+ zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6497+ for (k=0; k<zero_padding; ++k)
6498+ *(unicode_buffer+i*2+j+k)= (char)0;
6499+
6500+ DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6501+ DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6502+ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6503+
6504+ /* explanation, before I forget what I did:
6505+ strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6506+ divide by 8 and add 3 to compute the mms_chunkLenLM field,
6507+ but note that things may have to be padded with zeroes to align by 8
6508+ bytes, hence we add 7 and divide by 8 to get the correct length */
6509+ *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6510+ *mms_chunkLenLV = *mms_chunkLenLM+2;
6511+ *mms_messageLength = *mms_chunkLenLV*8;
6512+
6513+ DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6514+ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6515+
6516+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6517+ expect->seq - ntohl(tcph->seq),
6518+ ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6519+ strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6520+ DUMP_BYTES(unicode_buffer, 60);
6521+
6522+ return 1;
6523+}
6524+
6525+static unsigned int
6526+mms_nat_expected(struct sk_buff **pskb,
6527+ unsigned int hooknum,
6528+ struct ip_conntrack *ct,
6529+ struct ip_nat_info *info)
6530+{
6531+ struct ip_nat_multi_range mr;
6532+ u_int32_t newdstip, newsrcip, newip;
6533+
6534+ struct ip_conntrack *master = master_ct(ct);
6535+
6536+ IP_NF_ASSERT(info);
6537+ IP_NF_ASSERT(master);
6538+
6539+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6540+
6541+ DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6542+
6543+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6544+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6545+ DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6546+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6547+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6548+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6549+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
6550+
6551+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6552+ newip = newsrcip;
6553+ else
6554+ newip = newdstip;
6555+
6556+ DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6557+
6558+ mr.rangesize = 1;
6559+ /* We don't want to manip the per-protocol, just the IPs. */
6560+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6561+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
6562+
6563+ return ip_nat_setup_info(ct, &mr, hooknum);
6564+}
6565+
6566+
6567+static unsigned int mms_nat_help(struct ip_conntrack *ct,
6568+ struct ip_conntrack_expect *exp,
6569+ struct ip_nat_info *info,
6570+ enum ip_conntrack_info ctinfo,
6571+ unsigned int hooknum,
6572+ struct sk_buff **pskb)
6573+{
6574+ struct iphdr *iph = (*pskb)->nh.iph;
6575+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6576+ unsigned int datalen;
6577+ int dir;
6578+ struct ip_ct_mms_expect *ct_mms_info;
6579+
6580+ if (!exp)
6581+ DEBUGP("ip_nat_mms: no exp!!");
6582+
6583+ ct_mms_info = &exp->help.exp_mms_info;
6584+
6585+ /* Only mangle things once: original direction in POST_ROUTING
6586+ and reply direction on PRE_ROUTING. */
6587+ dir = CTINFO2DIR(ctinfo);
6588+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6589+ ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6590+ DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6591+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6592+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6593+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6594+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6595+ return NF_ACCEPT;
6596+ }
6597+ DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6598+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6599+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6600+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6601+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6602+
6603+ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6604+
6605+ DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6606+ exp->seq + ct_mms_info->len,
6607+ ntohl(tcph->seq),
6608+ ntohl(tcph->seq) + datalen);
6609+
6610+ LOCK_BH(&ip_mms_lock);
6611+ /* Check wether the whole IP/proto/port pattern is carried in the payload */
6612+ if (between(exp->seq + ct_mms_info->len,
6613+ ntohl(tcph->seq),
6614+ ntohl(tcph->seq) + datalen)) {
6615+ if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6616+ UNLOCK_BH(&ip_mms_lock);
6617+ return NF_DROP;
6618+ }
6619+ } else {
6620+ /* Half a match? This means a partial retransmisison.
6621+ It's a cracker being funky. */
6622+ if (net_ratelimit()) {
6623+ printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6624+ exp->seq, ct_mms_info->len,
6625+ ntohl(tcph->seq),
6626+ ntohl(tcph->seq) + datalen);
6627+ }
6628+ UNLOCK_BH(&ip_mms_lock);
6629+ return NF_DROP;
6630+ }
6631+ UNLOCK_BH(&ip_mms_lock);
6632+
6633+ return NF_ACCEPT;
6634+}
6635+
6636+static struct ip_nat_helper mms[MAX_PORTS];
6637+static char mms_names[MAX_PORTS][10];
6638+
6639+/* Not __exit: called from init() */
6640+static void fini(void)
6641+{
6642+ int i;
6643+
6644+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6645+ DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6646+ ip_nat_helper_unregister(&mms[i]);
6647+ }
6648+}
6649+
6650+static int __init init(void)
6651+{
6652+ int i, ret = 0;
6653+ char *tmpname;
6654+
6655+ if (ports[0] == 0)
6656+ ports[0] = MMS_PORT;
6657+
6658+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6659+
6660+ memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6661+
6662+ mms[i].tuple.dst.protonum = IPPROTO_TCP;
6663+ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6664+ mms[i].mask.dst.protonum = 0xFFFF;
6665+ mms[i].mask.src.u.tcp.port = 0xFFFF;
6666+ mms[i].help = mms_nat_help;
6667+ mms[i].me = THIS_MODULE;
6668+ mms[i].flags = 0;
6669+ mms[i].expect = mms_nat_expected;
6670+
6671+ tmpname = &mms_names[i][0];
6672+ if (ports[i] == MMS_PORT)
6673+ sprintf(tmpname, "mms");
6674+ else
6675+ sprintf(tmpname, "mms-%d", i);
6676+ mms[i].name = tmpname;
6677+
6678+ DEBUGP("ip_nat_mms: register helper for port %d\n",
6679+ ports[i]);
6680+ ret = ip_nat_helper_register(&mms[i]);
6681+
6682+ if (ret) {
6683+ printk("ip_nat_mms: error registering "
6684+ "helper for port %d\n", ports[i]);
6685+ fini();
6686+ return ret;
6687+ }
6688+ ports_c++;
6689+ }
6690+
6691+ return ret;
6692+}
6693+
6694+module_init(init);
6695+module_exit(fini);
6696diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c
6697--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
6698+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c 2004-04-30 09:13:29.000000000 +0200
6699@@ -0,0 +1,249 @@
6700+/* Quake3 extension for UDP NAT alteration.
6701+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6702+ * based on ip_nat_ftp.c and ip_nat_tftp.c
6703+ *
6704+ * ip_nat_quake3.c v0.0.3 2002-08-31
6705+ *
6706+ * This program is free software; you can redistribute it and/or
6707+ * modify it under the terms of the GNU General Public License
6708+ * as published by the Free Software Foundation; either version
6709+ * 2 of the License, or (at your option) any later version.
6710+ *
6711+ * Module load syntax:
6712+ * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6713+ *
6714+ * please give the ports of all Quake3 master servers You wish to
6715+ * connect to. If you don't specify ports, the default will be UDP
6716+ * port 27950.
6717+ *
6718+ * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6719+ *
6720+ * Notes:
6721+ * - If you're one of those people who would try anything to lower
6722+ * latency while playing Quake (and who isn't :-) ), you may want to
6723+ * consider not loading ip_nat_quake3 at all and just MASQUERADE all
6724+ * outgoing UDP traffic.
6725+ * This will make ip_conntrack_quake3 add the necessary expectations,
6726+ * but there will be no overhead for client->server UDP streams. If
6727+ * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6728+ * hook for every packet in the client->server UDP stream.
6729+ * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6730+ * The IP addresses in the master connection payload (=IP addresses
6731+ * of Quake servers) have no relation with the master server so
6732+ * DNAT'ing the master connection to a server should not change the
6733+ * expected connections.
6734+ * - Not tested due to lack of equipment:
6735+ * - multiple Quake3 clients behind one MASQUERADE gateway
6736+ * - what if Quake3 client is running on router too
6737+ */
6738+
6739+#include <linux/module.h>
6740+#include <linux/netfilter_ipv4.h>
6741+#include <linux/ip.h>
6742+#include <linux/udp.h>
6743+
6744+#include <linux/netfilter.h>
6745+#include <linux/netfilter_ipv4/ip_tables.h>
6746+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6747+#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6748+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6749+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6750+
6751+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6752+MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6753+MODULE_LICENSE("GPL");
6754+
6755+#define MAX_PORTS 8
6756+
6757+static int ports[MAX_PORTS];
6758+static int ports_c = 0;
6759+#ifdef MODULE_PARM
6760+MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
6761+MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
6762+#endif
6763+
6764+/* Quake3 master server reply will add > 100 expectations per reply packet; when
6765+ doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
6766+#if 0
6767+#define DEBUGP printk
6768+#else
6769+#define DEBUGP(format, args...)
6770+#endif
6771+
6772+static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
6773+
6774+static unsigned int
6775+quake3_nat_help(struct ip_conntrack *ct,
6776+ struct ip_conntrack_expect *exp,
6777+ struct ip_nat_info *info,
6778+ enum ip_conntrack_info ctinfo,
6779+ unsigned int hooknum,
6780+ struct sk_buff **pskb)
6781+{
6782+ struct iphdr *iph = (*pskb)->nh.iph;
6783+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
6784+ struct ip_conntrack_tuple repl;
6785+ int dir = CTINFO2DIR(ctinfo);
6786+ int i;
6787+
6788+ DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
6789+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6790+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6791+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6792+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6793+ );
6794+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6795+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6796+
6797+ /* Only mangle things once: original direction in POST_ROUTING
6798+ and reply direction on PRE_ROUTING. */
6799+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6800+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6801+ DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
6802+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6803+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6804+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6805+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6806+ return NF_ACCEPT;
6807+ }
6808+
6809+ if (!exp) {
6810+ DEBUGP("no conntrack expectation to modify\n");
6811+ return NF_ACCEPT;
6812+ }
6813+
6814+ if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
6815+ for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
6816+ i+6 < ntohs(udph->len);
6817+ i+=7) {
6818+ DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
6819+ i, ntohs(udph->len),
6820+ NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
6821+ ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
6822+
6823+ memset(&repl, 0, sizeof(repl));
6824+
6825+ repl.dst.protonum = IPPROTO_UDP;
6826+ repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6827+ repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
6828+ repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
6829+
6830+ ip_conntrack_change_expect(exp, &repl);
6831+ }
6832+ }
6833+ return NF_ACCEPT;
6834+}
6835+
6836+static unsigned int
6837+quake3_nat_expected(struct sk_buff **pskb,
6838+ unsigned int hooknum,
6839+ struct ip_conntrack *ct,
6840+ struct ip_nat_info *info)
6841+{
6842+ const struct ip_conntrack *master = ct->master->expectant;
6843+ struct ip_nat_multi_range mr;
6844+ u_int32_t newsrcip, newdstip, newip;
6845+#if 0
6846+ const struct ip_conntrack_tuple *repl =
6847+ &master->tuplehash[IP_CT_DIR_REPLY].tuple;
6848+ struct iphdr *iph = (*pskb)->nh.iph;
6849+ struct udphdr *udph = (void *)iph + iph->ihl*4;
6850+#endif
6851+
6852+ DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
6853+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6854+
6855+ IP_NF_ASSERT(info);
6856+ IP_NF_ASSERT(master);
6857+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6858+
6859+ newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6860+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6861+
6862+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
6863+ newip = newsrcip;
6864+ DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6865+ "newsrc: %u.%u.%u.%u\n",
6866+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6867+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6868+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6869+ NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6870+ NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6871+ NIPQUAD(newip));
6872+
6873+ } else {
6874+ newip = newdstip;
6875+ DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6876+ "newdst: %u.%u.%u.%u\n",
6877+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6878+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6879+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6880+ NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6881+ NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6882+ NIPQUAD(newip));
6883+ }
6884+
6885+ mr.rangesize = 1;
6886+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6887+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
6888+
6889+ return ip_nat_setup_info(ct,&mr,hooknum);
6890+}
6891+
6892+static struct ip_nat_helper quake3[MAX_PORTS];
6893+static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
6894+
6895+static void fini(void)
6896+{
6897+ int i;
6898+
6899+ for (i = 0 ; i < ports_c; i++) {
6900+ DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
6901+ ip_nat_helper_unregister(&quake3[i]);
6902+ }
6903+}
6904+
6905+static int __init init(void)
6906+ {
6907+ int i, ret = 0;
6908+ char *tmpname;
6909+
6910+ if (!ports[0])
6911+ ports[0] = QUAKE3_MASTER_PORT;
6912+
6913+ for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6914+ memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
6915+
6916+ quake3[i].tuple.dst.protonum = IPPROTO_UDP;
6917+ quake3[i].tuple.src.u.udp.port = htons(ports[i]);
6918+ quake3[i].mask.dst.protonum = 0xFFFF;
6919+ quake3[i].mask.src.u.udp.port = 0xFFFF;
6920+ quake3[i].help = quake3_nat_help;
6921+ quake3[i].flags = 0;
6922+ quake3[i].me = THIS_MODULE;
6923+ quake3[i].expect = quake3_nat_expected;
6924+
6925+ tmpname = &quake3_names[i][0];
6926+ if (ports[i] == QUAKE3_MASTER_PORT)
6927+ sprintf(tmpname, "quake3");
6928+ else
6929+ sprintf(tmpname, "quake3-%d", i);
6930+ quake3[i].name = tmpname;
6931+
6932+ DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
6933+ ports[i], quake3[i].name);
6934+ ret = ip_nat_helper_register(&quake3[i]);
6935+
6936+ if (ret) {
6937+ printk("ip_nat_quake3: unable to register helper for port %d\n",
6938+ ports[i]);
6939+ fini();
6940+ return ret;
6941+ }
6942+ ports_c++;
6943+ }
6944+ return ret;
6945+ }
6946+
6947+module_init(init);
6948+module_exit(fini);
6949diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
6950--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
6951+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c 2004-04-30 09:14:05.000000000 +0200
6952@@ -0,0 +1,621 @@
6953+/*
6954+ * RTSP extension for TCP NAT alteration
6955+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
6956+ * based on ip_nat_irc.c
6957+ *
6958+ * This program is free software; you can redistribute it and/or
6959+ * modify it under the terms of the GNU General Public License
6960+ * as published by the Free Software Foundation; either version
6961+ * 2 of the License, or (at your option) any later version.
6962+ *
6963+ * Module load syntax:
6964+ * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6965+ * stunaddr=<address>
6966+ * destaction=[auto|strip|none]
6967+ *
6968+ * If no ports are specified, the default will be port 554 only.
6969+ *
6970+ * stunaddr specifies the address used to detect that a client is using STUN.
6971+ * If this address is seen in the destination parameter, it is assumed that
6972+ * the client has already punched a UDP hole in the firewall, so we don't
6973+ * mangle the client_port. If none is specified, it is autodetected. It
6974+ * only needs to be set if you have multiple levels of NAT. It should be
6975+ * set to the external address that the STUN clients detect. Note that in
6976+ * this case, it will not be possible for clients to use UDP with servers
6977+ * between the NATs.
6978+ *
6979+ * If no destaction is specified, auto is used.
6980+ * destaction=auto: strip destination parameter if it is not stunaddr.
6981+ * destaction=strip: always strip destination parameter (not recommended).
6982+ * destaction=none: do not touch destination parameter (not recommended).
6983+ */
6984+
6985+#include <linux/module.h>
6986+#include <linux/netfilter_ipv4.h>
6987+#include <linux/ip.h>
6988+#include <linux/tcp.h>
6989+#include <linux/kernel.h>
6990+#include <net/tcp.h>
6991+#include <linux/netfilter_ipv4/ip_nat.h>
6992+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6993+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6994+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6995+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6996+
6997+#include <linux/inet.h>
6998+#include <linux/ctype.h>
6999+#define NF_NEED_STRNCASECMP
7000+#define NF_NEED_STRTOU16
7001+#include <linux/netfilter_helpers.h>
7002+#define NF_NEED_MIME_NEXTLINE
7003+#include <linux/netfilter_mime.h>
7004+
7005+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7006+#ifdef IP_NF_RTSP_DEBUG
7007+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7008+#else
7009+#define DEBUGP(fmt, args...)
7010+#endif
7011+
7012+#define MAX_PORTS 8
7013+#define DSTACT_AUTO 0
7014+#define DSTACT_STRIP 1
7015+#define DSTACT_NONE 2
7016+
7017+static int ports[MAX_PORTS];
7018+static char* stunaddr = NULL;
7019+static char* destaction = NULL;
7020+
7021+static int num_ports = 0;
7022+static u_int32_t extip = 0;
7023+static int dstact = 0;
7024+
7025+MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7026+MODULE_DESCRIPTION("RTSP network address translation module");
7027+MODULE_LICENSE("GPL");
7028+#ifdef MODULE_PARM
7029+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7030+MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7031+MODULE_PARM(stunaddr, "s");
7032+MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7033+MODULE_PARM(destaction, "s");
7034+MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7035+#endif
7036+
7037+/* protects rtsp part of conntracks */
7038+DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7039+
7040+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7041+
7042+/*** helper functions ***/
7043+
7044+static void
7045+get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7046+{
7047+ struct iphdr* iph = (struct iphdr*)skb->nh.iph;
7048+ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7049+
7050+ *pptcpdata = (char*)tcph + tcph->doff*4;
7051+ *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7052+}
7053+
7054+/*** nat functions ***/
7055+
7056+/*
7057+ * Mangle the "Transport:" header:
7058+ * - Replace all occurences of "client_port=<spec>"
7059+ * - Handle destination parameter
7060+ *
7061+ * In:
7062+ * ct, ctinfo = conntrack context
7063+ * pskb = packet
7064+ * tranoff = Transport header offset from TCP data
7065+ * tranlen = Transport header length (incl. CRLF)
7066+ * rport_lo = replacement low port (host endian)
7067+ * rport_hi = replacement high port (host endian)
7068+ *
7069+ * Returns packet size difference.
7070+ *
7071+ * Assumes that a complete transport header is present, ending with CR or LF
7072+ */
7073+static int
7074+rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7075+ struct ip_conntrack_expect* exp,
7076+ struct sk_buff** pskb, uint tranoff, uint tranlen)
7077+{
7078+ char* ptcp;
7079+ uint tcplen;
7080+ char* ptran;
7081+ char rbuf1[16]; /* Replacement buffer (one port) */
7082+ uint rbuf1len; /* Replacement len (one port) */
7083+ char rbufa[16]; /* Replacement buffer (all ports) */
7084+ uint rbufalen; /* Replacement len (all ports) */
7085+ u_int32_t newip;
7086+ u_int16_t loport, hiport;
7087+ uint off = 0;
7088+ uint diff; /* Number of bytes we removed */
7089+
7090+ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7091+ struct ip_conntrack_tuple t;
7092+
7093+ char szextaddr[15+1];
7094+ uint extaddrlen;
7095+ int is_stun;
7096+
7097+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7098+ ptran = ptcp+tranoff;
7099+
7100+ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7101+ tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7102+ nf_strncasecmp(ptran, "Transport:", 10) != 0)
7103+ {
7104+ INFOP("sanity check failed\n");
7105+ return 0;
7106+ }
7107+ off += 10;
7108+ SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7109+
7110+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7111+ t = exp->tuple;
7112+ t.dst.ip = newip;
7113+
7114+ extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7115+ : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7116+ DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7117+
7118+ rbuf1len = rbufalen = 0;
7119+ switch (prtspexp->pbtype)
7120+ {
7121+ case pb_single:
7122+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7123+ {
7124+ t.dst.u.udp.port = htons(loport);
7125+ if (ip_conntrack_change_expect(exp, &t) == 0)
7126+ {
7127+ DEBUGP("using port %hu\n", loport);
7128+ break;
7129+ }
7130+ }
7131+ if (loport != 0)
7132+ {
7133+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7134+ rbufalen = sprintf(rbufa, "%hu", loport);
7135+ }
7136+ break;
7137+ case pb_range:
7138+ for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7139+ {
7140+ t.dst.u.udp.port = htons(loport);
7141+ if (ip_conntrack_change_expect(exp, &t) == 0)
7142+ {
7143+ hiport = loport + ~exp->mask.dst.u.udp.port;
7144+ DEBUGP("using ports %hu-%hu\n", loport, hiport);
7145+ break;
7146+ }
7147+ }
7148+ if (loport != 0)
7149+ {
7150+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7151+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7152+ }
7153+ break;
7154+ case pb_discon:
7155+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7156+ {
7157+ t.dst.u.udp.port = htons(loport);
7158+ if (ip_conntrack_change_expect(exp, &t) == 0)
7159+ {
7160+ DEBUGP("using port %hu (1 of 2)\n", loport);
7161+ break;
7162+ }
7163+ }
7164+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7165+ {
7166+ t.dst.u.udp.port = htons(hiport);
7167+ if (ip_conntrack_change_expect(exp, &t) == 0)
7168+ {
7169+ DEBUGP("using port %hu (2 of 2)\n", hiport);
7170+ break;
7171+ }
7172+ }
7173+ if (loport != 0 && hiport != 0)
7174+ {
7175+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7176+ if (hiport == loport+1)
7177+ {
7178+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7179+ }
7180+ else
7181+ {
7182+ rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7183+ }
7184+ }
7185+ break;
7186+ }
7187+
7188+ if (rbuf1len == 0)
7189+ {
7190+ return 0; /* cannot get replacement port(s) */
7191+ }
7192+
7193+ /* Transport: tran;field;field=val,tran;field;field=val,... */
7194+ while (off < tranlen)
7195+ {
7196+ uint saveoff;
7197+ const char* pparamend;
7198+ uint nextparamoff;
7199+
7200+ pparamend = memchr(ptran+off, ',', tranlen-off);
7201+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7202+ nextparamoff = pparamend-ptcp;
7203+
7204+ /*
7205+ * We pass over each param twice. On the first pass, we look for a
7206+ * destination= field. It is handled by the security policy. If it
7207+ * is present, allowed, and equal to our external address, we assume
7208+ * that STUN is being used and we leave the client_port= field alone.
7209+ */
7210+ is_stun = 0;
7211+ saveoff = off;
7212+ while (off < nextparamoff)
7213+ {
7214+ const char* pfieldend;
7215+ uint nextfieldoff;
7216+
7217+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7218+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7219+
7220+ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7221+ {
7222+ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7223+ {
7224+ is_stun = 1;
7225+ }
7226+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7227+ {
7228+ diff = nextfieldoff-off;
7229+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7230+ off, diff, NULL, 0))
7231+ {
7232+ /* mangle failed, all we can do is bail */
7233+ return 0;
7234+ }
7235+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7236+ ptran = ptcp+tranoff;
7237+ tranlen -= diff;
7238+ nextparamoff -= diff;
7239+ nextfieldoff -= diff;
7240+ }
7241+ }
7242+
7243+ off = nextfieldoff;
7244+ }
7245+ if (is_stun)
7246+ {
7247+ continue;
7248+ }
7249+ off = saveoff;
7250+ while (off < nextparamoff)
7251+ {
7252+ const char* pfieldend;
7253+ uint nextfieldoff;
7254+
7255+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7256+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7257+
7258+ if (strncmp(ptran+off, "client_port=", 12) == 0)
7259+ {
7260+ u_int16_t port;
7261+ uint numlen;
7262+ uint origoff;
7263+ uint origlen;
7264+ char* rbuf = rbuf1;
7265+ uint rbuflen = rbuf1len;
7266+
7267+ off += 12;
7268+ origoff = (ptran-ptcp)+off;
7269+ origlen = 0;
7270+ numlen = nf_strtou16(ptran+off, &port);
7271+ off += numlen;
7272+ origlen += numlen;
7273+ if (port != prtspexp->loport)
7274+ {
7275+ DEBUGP("multiple ports found, port %hu ignored\n", port);
7276+ }
7277+ else
7278+ {
7279+ if (ptran[off] == '-' || ptran[off] == '/')
7280+ {
7281+ off++;
7282+ origlen++;
7283+ numlen = nf_strtou16(ptran+off, &port);
7284+ off += numlen;
7285+ origlen += numlen;
7286+ rbuf = rbufa;
7287+ rbuflen = rbufalen;
7288+ }
7289+
7290+ /*
7291+ * note we cannot just memcpy() if the sizes are the same.
7292+ * the mangle function does skb resizing, checks for a
7293+ * cloned skb, and updates the checksums.
7294+ *
7295+ * parameter 4 below is offset from start of tcp data.
7296+ */
7297+ diff = origlen-rbuflen;
7298+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7299+ origoff, origlen, rbuf, rbuflen))
7300+ {
7301+ /* mangle failed, all we can do is bail */
7302+ return 0;
7303+ }
7304+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7305+ ptran = ptcp+tranoff;
7306+ tranlen -= diff;
7307+ nextparamoff -= diff;
7308+ nextfieldoff -= diff;
7309+ }
7310+ }
7311+
7312+ off = nextfieldoff;
7313+ }
7314+
7315+ off = nextparamoff;
7316+ }
7317+
7318+ return 1;
7319+}
7320+
7321+static unsigned int
7322+expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7323+{
7324+ struct ip_nat_multi_range mr;
7325+ u_int32_t newdstip, newsrcip, newip;
7326+
7327+ struct ip_conntrack *master = master_ct(ct);
7328+
7329+ IP_NF_ASSERT(info);
7330+ IP_NF_ASSERT(master);
7331+
7332+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7333+
7334+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7335+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7336+ newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7337+
7338+ DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7339+ NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7340+
7341+ mr.rangesize = 1;
7342+ /* We don't want to manip the per-protocol, just the IPs. */
7343+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7344+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
7345+
7346+ return ip_nat_setup_info(ct, &mr, hooknum);
7347+}
7348+
7349+static uint
7350+help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7351+ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7352+{
7353+ char* ptcp;
7354+ uint tcplen;
7355+ uint hdrsoff;
7356+ uint hdrslen;
7357+ uint lineoff;
7358+ uint linelen;
7359+ uint off;
7360+
7361+ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7362+ struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7363+
7364+ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7365+
7366+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7367+
7368+ hdrsoff = exp->seq - ntohl(tcph->seq);
7369+ hdrslen = prtspexp->len;
7370+ off = hdrsoff;
7371+
7372+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7373+ {
7374+ if (linelen == 0)
7375+ {
7376+ break;
7377+ }
7378+ if (off > hdrsoff+hdrslen)
7379+ {
7380+ INFOP("!! overrun !!");
7381+ break;
7382+ }
7383+ DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7384+
7385+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7386+ {
7387+ uint oldtcplen = tcplen;
7388+ if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7389+ {
7390+ break;
7391+ }
7392+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7393+ hdrslen -= (oldtcplen-tcplen);
7394+ off -= (oldtcplen-tcplen);
7395+ lineoff -= (oldtcplen-tcplen);
7396+ linelen -= (oldtcplen-tcplen);
7397+ DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7398+ }
7399+ }
7400+
7401+ return NF_ACCEPT;
7402+}
7403+
7404+static uint
7405+help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7406+ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7407+{
7408+ /* XXX: unmangle */
7409+ return NF_ACCEPT;
7410+}
7411+
7412+static uint
7413+help(struct ip_conntrack* ct,
7414+ struct ip_conntrack_expect* exp,
7415+ struct ip_nat_info* info,
7416+ enum ip_conntrack_info ctinfo,
7417+ unsigned int hooknum,
7418+ struct sk_buff** pskb)
7419+{
7420+ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7421+ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7422+ uint datalen;
7423+ int dir;
7424+ struct ip_ct_rtsp_expect* ct_rtsp_info;
7425+ int rc = NF_ACCEPT;
7426+
7427+ if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7428+ {
7429+ DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7430+ return NF_ACCEPT;
7431+ }
7432+
7433+ ct_rtsp_info = &exp->help.exp_rtsp_info;
7434+
7435+ /*
7436+ * Only mangle things once: original direction in POST_ROUTING
7437+ * and reply direction on PRE_ROUTING.
7438+ */
7439+ dir = CTINFO2DIR(ctinfo);
7440+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7441+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7442+ {
7443+ DEBUGP("Not touching dir %s at hook %s\n",
7444+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7445+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7446+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7447+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7448+ return NF_ACCEPT;
7449+ }
7450+ DEBUGP("got beyond not touching\n");
7451+
7452+ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7453+
7454+ LOCK_BH(&ip_rtsp_lock);
7455+ /* Ensure the packet contains all of the marked data */
7456+ if (!between(exp->seq + ct_rtsp_info->len,
7457+ ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7458+ {
7459+ /* Partial retransmission? Probably a hacker. */
7460+ if (net_ratelimit())
7461+ {
7462+ INFOP("partial packet %u/%u in %u/%u\n",
7463+ exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7464+ }
7465+ UNLOCK_BH(&ip_rtsp_lock);
7466+ return NF_DROP;
7467+ }
7468+
7469+ switch (dir)
7470+ {
7471+ case IP_CT_DIR_ORIGINAL:
7472+ rc = help_out(ct, ctinfo, exp, pskb);
7473+ break;
7474+ case IP_CT_DIR_REPLY:
7475+ rc = help_in(ct, ctinfo, exp, pskb);
7476+ break;
7477+ }
7478+ UNLOCK_BH(&ip_rtsp_lock);
7479+
7480+ return rc;
7481+}
7482+
7483+static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7484+static char rtsp_names[MAX_PORTS][10];
7485+
7486+/* This function is intentionally _NOT_ defined as __exit */
7487+static void
7488+fini(void)
7489+{
7490+ int i;
7491+
7492+ for (i = 0; i < num_ports; i++)
7493+ {
7494+ DEBUGP("unregistering helper for port %d\n", ports[i]);
7495+ ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7496+ }
7497+}
7498+
7499+static int __init
7500+init(void)
7501+{
7502+ int ret = 0;
7503+ int i;
7504+ struct ip_nat_helper* hlpr;
7505+ char* tmpname;
7506+
7507+ printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7508+
7509+ if (ports[0] == 0)
7510+ {
7511+ ports[0] = RTSP_PORT;
7512+ }
7513+
7514+ for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7515+ {
7516+ hlpr = &ip_nat_rtsp_helpers[i];
7517+ memset(hlpr, 0, sizeof(struct ip_nat_helper));
7518+
7519+ hlpr->tuple.dst.protonum = IPPROTO_TCP;
7520+ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7521+ hlpr->mask.src.u.tcp.port = 0xFFFF;
7522+ hlpr->mask.dst.protonum = 0xFFFF;
7523+ hlpr->help = help;
7524+ hlpr->flags = 0;
7525+ hlpr->me = THIS_MODULE;
7526+ hlpr->expect = expected;
7527+
7528+ tmpname = &rtsp_names[i][0];
7529+ if (ports[i] == RTSP_PORT)
7530+ {
7531+ sprintf(tmpname, "rtsp");
7532+ }
7533+ else
7534+ {
7535+ sprintf(tmpname, "rtsp-%d", i);
7536+ }
7537+ hlpr->name = tmpname;
7538+
7539+ DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7540+ ret = ip_nat_helper_register(hlpr);
7541+
7542+ if (ret)
7543+ {
7544+ printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7545+ fini();
7546+ return 1;
7547+ }
7548+ num_ports++;
7549+ }
7550+ if (stunaddr != NULL)
7551+ {
7552+ extip = in_aton(stunaddr);
7553+ }
7554+ if (destaction != NULL)
7555+ {
7556+ if (strcmp(destaction, "auto") == 0)
7557+ {
7558+ dstact = DSTACT_AUTO;
7559+ }
7560+ if (strcmp(destaction, "strip") == 0)
7561+ {
7562+ dstact = DSTACT_STRIP;
7563+ }
7564+ if (strcmp(destaction, "none") == 0)
7565+ {
7566+ dstact = DSTACT_NONE;
7567+ }
7568+ }
7569+ return ret;
7570+}
7571+
7572+module_init(init);
7573+module_exit(fini);
7574diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c
7575--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c 2004-04-28 03:35:44.000000000 +0200
7576+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c 2004-04-30 09:11:53.000000000 +0200
7577@@ -75,7 +75,7 @@
7578 0,
7579 sizeof(struct ipt_entry),
7580 sizeof(struct ipt_standard),
7581- 0, { 0, 0 }, { } },
7582+ 0, NULL, 0, { 0, 0 }, { } },
7583 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7584 -NF_ACCEPT - 1 } },
7585 /* POST_ROUTING */
7586@@ -83,7 +83,7 @@
7587 0,
7588 sizeof(struct ipt_entry),
7589 sizeof(struct ipt_standard),
7590- 0, { 0, 0 }, { } },
7591+ 0, NULL, 0, { 0, 0 }, { } },
7592 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7593 -NF_ACCEPT - 1 } },
7594 /* LOCAL_OUT */
7595@@ -91,7 +91,7 @@
7596 0,
7597 sizeof(struct ipt_entry),
7598 sizeof(struct ipt_standard),
7599- 0, { 0, 0 }, { } },
7600+ 0, NULL, 0, { 0, 0 }, { } },
7601 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7602 -NF_ACCEPT - 1 } }
7603 },
7604@@ -100,7 +100,7 @@
7605 0,
7606 sizeof(struct ipt_entry),
7607 sizeof(struct ipt_error),
7608- 0, { 0, 0 }, { } },
7609+ 0, NULL, 0, { 0, 0 }, { } },
7610 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7611 { } },
7612 "ERROR"
7613diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c
7614--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-28 03:36:29.000000000 +0200
7615+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-30 09:12:41.000000000 +0200
7616@@ -175,6 +175,45 @@
7617 return do_bindings(ct, ctinfo, info, hooknum, pskb);
7618 }
7619
7620+struct nat_route_key
7621+{
7622+ u_int32_t addr;
7623+#ifdef CONFIG_XFRM
7624+ u_int16_t port;
7625+#endif
7626+};
7627+
7628+static inline void
7629+nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
7630+{
7631+ struct iphdr *iph = skb->nh.iph;
7632+
7633+ key->addr = which ? iph->daddr : iph->saddr;
7634+#ifdef CONFIG_XFRM
7635+ key->port = 0;
7636+ if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7637+ u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7638+ key->port = ports[which];
7639+ }
7640+#endif
7641+}
7642+
7643+static inline int
7644+nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
7645+{
7646+ struct iphdr *iph = skb->nh.iph;
7647+
7648+ if (key->addr != (which ? iph->daddr : iph->saddr))
7649+ return 1;
7650+#ifdef CONFIG_XFRM
7651+ if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7652+ u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7653+ if (key->port != ports[which])
7654+ return 1;
7655+ }
7656+#endif
7657+}
7658+
7659 static unsigned int
7660 ip_nat_out(unsigned int hooknum,
7661 struct sk_buff **pskb,
7662@@ -182,6 +221,9 @@
7663 const struct net_device *out,
7664 int (*okfn)(struct sk_buff *))
7665 {
7666+ struct nat_route_key key;
7667+ unsigned int ret;
7668+
7669 /* root is playing with raw sockets. */
7670 if ((*pskb)->len < sizeof(struct iphdr)
7671 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7672@@ -204,7 +246,29 @@
7673 return NF_STOLEN;
7674 }
7675
7676- return ip_nat_fn(hooknum, pskb, in, out, okfn);
7677+ nat_route_key_get(*pskb, &key, 0);
7678+ ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7679+
7680+ if (ret != NF_DROP && ret != NF_STOLEN
7681+ && nat_route_key_compare(*pskb, &key, 0)) {
7682+ if (ip_route_me_harder(pskb) != 0)
7683+ ret = NF_DROP;
7684+#ifdef CONFIG_XFRM
7685+ /*
7686+ * POST_ROUTING hook is called with fixed outfn, we need
7687+ * to manually confirm the packet and direct it to the
7688+ * transformers if a policy matches.
7689+ */
7690+ else if ((*pskb)->dst->xfrm != NULL) {
7691+ ret = ip_conntrack_confirm(*pskb);
7692+ if (ret != NF_DROP) {
7693+ dst_output(*pskb);
7694+ ret = NF_STOLEN;
7695+ }
7696+ }
7697+#endif
7698+ }
7699+ return ret;
7700 }
7701
7702 #ifdef CONFIG_IP_NF_NAT_LOCAL
7703@@ -215,7 +279,7 @@
7704 const struct net_device *out,
7705 int (*okfn)(struct sk_buff *))
7706 {
7707- u_int32_t saddr, daddr;
7708+ struct nat_route_key key;
7709 unsigned int ret;
7710
7711 /* root is playing with raw sockets. */
7712@@ -223,14 +287,14 @@
7713 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7714 return NF_ACCEPT;
7715
7716- saddr = (*pskb)->nh.iph->saddr;
7717- daddr = (*pskb)->nh.iph->daddr;
7718-
7719+ nat_route_key_get(*pskb, &key, 1);
7720 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7721+
7722 if (ret != NF_DROP && ret != NF_STOLEN
7723- && ((*pskb)->nh.iph->saddr != saddr
7724- || (*pskb)->nh.iph->daddr != daddr))
7725- return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
7726+ && nat_route_key_compare(*pskb, &key, 1)) {
7727+ if (ip_route_me_harder(pskb) != 0)
7728+ ret = NF_DROP;
7729+ }
7730 return ret;
7731 }
7732 #endif
7733diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c
7734--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
7735+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c 2004-04-30 09:14:39.000000000 +0200
7736@@ -0,0 +1,473 @@
7737+/*
7738+ * talk extension for UDP NAT alteration.
7739+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7740+ *
7741+ * This program is free software; you can redistribute it and/or
7742+ * modify it under the terms of the GNU General Public License
7743+ * as published by the Free Software Foundation; either version
7744+ * 2 of the License, or (at your option) any later version.
7745+ **
7746+ * Module load syntax:
7747+ * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7748+ *
7749+ * talk=[0|1] disable|enable old talk support
7750+ * ntalk=[0|1] disable|enable ntalk support
7751+ * ntalk2=[0|1] disable|enable ntalk2 support
7752+ *
7753+ * The default is talk=1 ntalk=1 ntalk2=1
7754+ *
7755+ *
7756+ */
7757+#include <linux/module.h>
7758+#include <linux/netfilter_ipv4.h>
7759+#include <linux/ip.h>
7760+#include <linux/udp.h>
7761+#include <linux/kernel.h>
7762+#include <net/tcp.h>
7763+#include <net/udp.h>
7764+
7765+#include <linux/netfilter_ipv4/ip_nat.h>
7766+#include <linux/netfilter_ipv4/ip_nat_helper.h>
7767+#include <linux/netfilter_ipv4/ip_nat_rule.h>
7768+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7769+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7770+
7771+/* Default all talk protocols are supported */
7772+static int talk = 1;
7773+static int ntalk = 1;
7774+static int ntalk2 = 1;
7775+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7776+MODULE_DESCRIPTION("talk network address translation module");
7777+#ifdef MODULE_PARM
7778+MODULE_PARM(talk, "i");
7779+MODULE_PARM_DESC(talk, "support (old) talk protocol");
7780+MODULE_PARM(ntalk, "i");
7781+MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7782+MODULE_PARM(ntalk2, "i");
7783+MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7784+#endif
7785+
7786+#if 0
7787+#define DEBUGP printk
7788+#define IP_NAT_TALK_DEBUG
7789+#else
7790+#define DEBUGP(format, args...)
7791+#endif
7792+
7793+/* FIXME: Time out? --RR */
7794+
7795+static int
7796+mangle_packet(struct sk_buff **pskb,
7797+ struct ip_conntrack *ct,
7798+ u_int32_t newip,
7799+ u_int16_t port,
7800+ struct talk_addr *addr,
7801+ struct talk_addr *ctl_addr)
7802+{
7803+ struct iphdr *iph = (*pskb)->nh.iph;
7804+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
7805+ size_t udplen = (*pskb)->len - iph->ihl * 4;
7806+
7807+ /* Fortunately talk sends a structure with the address and
7808+ port in it. The size of the packet won't change. */
7809+
7810+ if (ctl_addr == NULL) {
7811+ /* response */
7812+ if (addr->ta_addr == INADDR_ANY)
7813+ return 1;
7814+ DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7815+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7816+ NIPQUAD(newip), ntohs(port));
7817+ addr->ta_addr = newip;
7818+ addr->ta_port = port;
7819+ } else {
7820+ /* message */
7821+ if (addr->ta_addr != INADDR_ANY) {
7822+ /* Change address inside packet to match way we're mapping
7823+ this connection. */
7824+ DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7825+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7826+ NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7827+ ntohs(addr->ta_port));
7828+ addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7829+ }
7830+ DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7831+ NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7832+ NIPQUAD(newip), ntohs(port));
7833+ ctl_addr->ta_addr = newip;
7834+ ctl_addr->ta_port = port;
7835+ }
7836+
7837+ /* Fix checksums */
7838+ (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
7839+ udph->check = 0;
7840+ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7841+ csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
7842+
7843+ ip_send_check(iph);
7844+ return 1;
7845+}
7846+
7847+static int talk_help_msg(struct ip_conntrack *ct,
7848+ struct sk_buff **pskb,
7849+ u_char type,
7850+ struct talk_addr *addr,
7851+ struct talk_addr *ctl_addr)
7852+{
7853+ u_int32_t newip;
7854+ u_int16_t port;
7855+
7856+ unsigned int verdict = NF_ACCEPT;
7857+
7858+ DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
7859+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7860+ NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7861+ type);
7862+
7863+ /* Change address inside packet to match way we're mapping
7864+ this connection. */
7865+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7866+ port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7867+ DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
7868+ NIPQUAD(newip), ntohs(port));
7869+
7870+ if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
7871+ verdict = NF_DROP;
7872+
7873+ return verdict;
7874+}
7875+
7876+static int talk_help_response(struct ip_conntrack *ct,
7877+ struct ip_conntrack_expect *exp,
7878+ struct sk_buff **pskb,
7879+ u_char type,
7880+ u_char answer,
7881+ struct talk_addr *addr)
7882+{
7883+ u_int32_t newip;
7884+ u_int16_t port;
7885+ struct ip_conntrack_tuple t;
7886+ struct ip_ct_talk_expect *ct_talk_info;
7887+
7888+ DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
7889+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7890+ type, answer);
7891+
7892+ LOCK_BH(&ip_talk_lock);
7893+ ct_talk_info = &exp->help.exp_talk_info;
7894+
7895+ if (!(answer == SUCCESS
7896+ && (type == LOOK_UP || type == ANNOUNCE)
7897+ && exp != NULL)) {
7898+ UNLOCK_BH(&ip_talk_lock);
7899+ return NF_ACCEPT;
7900+ }
7901+
7902+ DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
7903+ ntohs(ct_talk_info->port),
7904+ type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
7905+
7906+ /* Change address inside packet to match way we're mapping
7907+ this connection. */
7908+ newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
7909+ IP_CT_DIR_REPLY].tuple.dst.ip;
7910+ /* We can read expect here without conntrack lock, since it's
7911+ only set in ip_conntrack_talk , with ip_talk_lock held
7912+ writable */
7913+ t = exp->tuple;
7914+ t.dst.ip = newip;
7915+
7916+ /* Try to get same port: if not, try to change it. */
7917+ for (port = ntohs(ct_talk_info->port); port != 0; port++) {
7918+ if (type == LOOK_UP)
7919+ t.dst.u.tcp.port = htons(port);
7920+ else
7921+ t.dst.u.udp.port = htons(port);
7922+
7923+ if (ip_conntrack_change_expect(exp, &t) == 0) {
7924+ DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
7925+ break;
7926+ }
7927+ }
7928+ UNLOCK_BH(&ip_talk_lock);
7929+
7930+ if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
7931+ return NF_DROP;
7932+
7933+ return NF_ACCEPT;
7934+}
7935+
7936+static unsigned int talk_help(struct ip_conntrack *ct,
7937+ struct ip_conntrack_expect *exp,
7938+ struct ip_nat_info *info,
7939+ enum ip_conntrack_info ctinfo,
7940+ unsigned int hooknum,
7941+ struct sk_buff **pskb,
7942+ int talk_port)
7943+{
7944+ struct iphdr *iph = (*pskb)->nh.iph;
7945+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
7946+ unsigned int udplen = (*pskb)->len - iph->ihl * 4;
7947+ char *data = (char *)udph + sizeof(struct udphdr);
7948+ int dir;
7949+
7950+ /* Only mangle things once: original direction in POST_ROUTING
7951+ and reply direction on PRE_ROUTING. */
7952+ dir = CTINFO2DIR(ctinfo);
7953+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7954+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7955+ DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
7956+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7957+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7958+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7959+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7960+ return NF_ACCEPT;
7961+ }
7962+ DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
7963+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7964+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7965+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7966+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7967+ NIPQUAD(iph->saddr), ntohs(udph->source),
7968+ NIPQUAD(iph->daddr), ntohs(udph->dest),
7969+ talk_port);
7970+
7971+ /* Because conntrack does not drop packets, checking must be repeated here... */
7972+ if (talk_port == TALK_PORT) {
7973+ if (dir == IP_CT_DIR_ORIGINAL
7974+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
7975+ return talk_help_msg(ct, pskb,
7976+ ((struct talk_msg *)data)->type,
7977+ &(((struct talk_msg *)data)->addr),
7978+ &(((struct talk_msg *)data)->ctl_addr));
7979+ else if (dir == IP_CT_DIR_REPLY
7980+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7981+ return talk_help_response(ct, exp, pskb,
7982+ ((struct talk_response *)data)->type,
7983+ ((struct talk_response *)data)->answer,
7984+ &(((struct talk_response *)data)->addr));
7985+ else {
7986+ DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
7987+ dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
7988+ (unsigned)udplen - sizeof(struct udphdr),
7989+ dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
7990+ return NF_DROP;
7991+ }
7992+ } else {
7993+ if (dir == IP_CT_DIR_ORIGINAL) {
7994+ if (ntalk
7995+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
7996+ && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
7997+ return talk_help_msg(ct, pskb,
7998+ ((struct ntalk_msg *)data)->type,
7999+ &(((struct ntalk_msg *)data)->addr),
8000+ &(((struct ntalk_msg *)data)->ctl_addr));
8001+ else if (ntalk2
8002+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8003+ && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8004+ && udplen == sizeof(struct udphdr)
8005+ + sizeof(struct ntalk2_msg)
8006+ + ((struct ntalk2_msg *)data)->extended)
8007+ return talk_help_msg(ct, pskb,
8008+ ((struct ntalk2_msg *)data)->type,
8009+ &(((struct ntalk2_msg *)data)->addr),
8010+ &(((struct ntalk2_msg *)data)->ctl_addr));
8011+ else {
8012+ DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
8013+ (unsigned)udplen - sizeof(struct udphdr),
8014+ sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8015+ return NF_DROP;
8016+ }
8017+ } else {
8018+ if (ntalk
8019+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8020+ && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8021+ return talk_help_response(ct, exp, pskb,
8022+ ((struct ntalk_response *)data)->type,
8023+ ((struct ntalk_response *)data)->answer,
8024+ &(((struct ntalk_response *)data)->addr));
8025+ else if (ntalk2
8026+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8027+ && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8028+ return talk_help_response(ct, exp, pskb,
8029+ ((struct ntalk2_response *)data)->type,
8030+ ((struct ntalk2_response *)data)->answer,
8031+ &(((struct ntalk2_response *)data)->addr));
8032+ else {
8033+ DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
8034+ (unsigned)udplen - sizeof(struct udphdr),
8035+ sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8036+ return NF_DROP;
8037+ }
8038+ }
8039+ }
8040+}
8041+
8042+static unsigned int help(struct ip_conntrack *ct,
8043+ struct ip_conntrack_expect *exp,
8044+ struct ip_nat_info *info,
8045+ enum ip_conntrack_info ctinfo,
8046+ unsigned int hooknum,
8047+ struct sk_buff **pskb)
8048+{
8049+ return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8050+}
8051+
8052+static unsigned int nhelp(struct ip_conntrack *ct,
8053+ struct ip_conntrack_expect *exp,
8054+ struct ip_nat_info *info,
8055+ enum ip_conntrack_info ctinfo,
8056+ unsigned int hooknum,
8057+ struct sk_buff **pskb)
8058+{
8059+ return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8060+}
8061+
8062+static unsigned int
8063+talk_nat_expected(struct sk_buff **pskb,
8064+ unsigned int hooknum,
8065+ struct ip_conntrack *ct,
8066+ struct ip_nat_info *info);
8067+
8068+static struct ip_nat_helper talk_helpers[2] =
8069+ { { { NULL, NULL },
8070+ "talk", /* name */
8071+ IP_NAT_HELPER_F_ALWAYS, /* flags */
8072+ THIS_MODULE, /* module */
8073+ { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8074+ { 0, { 0 }, IPPROTO_UDP } },
8075+ { { 0, { .udp = { 0xFFFF } } }, /* mask */
8076+ { 0, { 0 }, 0xFFFF } },
8077+ help, /* helper */
8078+ talk_nat_expected }, /* expectfn */
8079+ { { NULL, NULL },
8080+ "ntalk", /* name */
8081+ IP_NAT_HELPER_F_ALWAYS, /* flags */
8082+ THIS_MODULE, /* module */
8083+ { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8084+ { 0, { 0 }, IPPROTO_UDP } },
8085+ { { 0, { .udp = { 0xFFFF } } }, /* mask */
8086+ { 0, { 0 }, 0xFFFF } },
8087+ nhelp, /* helper */
8088+ talk_nat_expected } /* expectfn */
8089+ };
8090+
8091+static unsigned int
8092+talk_nat_expected(struct sk_buff **pskb,
8093+ unsigned int hooknum,
8094+ struct ip_conntrack *ct,
8095+ struct ip_nat_info *info)
8096+{
8097+ struct ip_nat_multi_range mr;
8098+ u_int32_t newdstip, newsrcip, newip;
8099+ u_int16_t port;
8100+ unsigned int ret;
8101+
8102+ struct ip_conntrack *master = master_ct(ct);
8103+
8104+ IP_NF_ASSERT(info);
8105+ IP_NF_ASSERT(master);
8106+
8107+ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8108+
8109+ DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8110+
8111+ LOCK_BH(&ip_talk_lock);
8112+ port = ct->master->help.exp_talk_info.port;
8113+ UNLOCK_BH(&ip_talk_lock);
8114+
8115+ DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8116+ CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8117+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8118+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8119+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8120+ ct, master);
8121+
8122+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8123+ /* Callee client -> caller server */
8124+#ifdef IP_NAT_TALK_DEBUG
8125+ struct iphdr *iph = (*pskb)->nh.iph;
8126+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
8127+
8128+ DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8129+ NIPQUAD(iph->saddr), ntohs(udph->source),
8130+ NIPQUAD(iph->daddr), ntohs(udph->dest));
8131+#endif
8132+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8133+ newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8134+ DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8135+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
8136+ } else {
8137+ /* Callee client -> caller client */
8138+#ifdef IP_NAT_TALK_DEBUG
8139+ struct iphdr *iph = (*pskb)->nh.iph;
8140+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8141+
8142+ DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8143+ NIPQUAD(iph->saddr), ntohs(tcph->source),
8144+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
8145+#endif
8146+ newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8147+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8148+ DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8149+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
8150+ }
8151+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8152+ newip = newsrcip;
8153+ else
8154+ newip = newdstip;
8155+
8156+ DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8157+
8158+ mr.rangesize = 1;
8159+ /* We don't want to manip the per-protocol, just the IPs... */
8160+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8161+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
8162+
8163+ /* ... unless we're doing a MANIP_DST, in which case, make
8164+ sure we map to the correct port */
8165+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8166+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8167+ mr.range[0].min = mr.range[0].max
8168+ = ((union ip_conntrack_manip_proto)
8169+ { .udp = { port } });
8170+ }
8171+ ret = ip_nat_setup_info(ct, &mr, hooknum);
8172+
8173+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8174+ DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8175+ /* NAT expectfn called with ip_nat_lock write-locked */
8176+ info->helper = &talk_helpers[htons(port) - TALK_PORT];
8177+ }
8178+ return ret;
8179+}
8180+
8181+static int __init init(void)
8182+{
8183+ int ret = 0;
8184+
8185+ if (talk > 0) {
8186+ ret = ip_nat_helper_register(&talk_helpers[0]);
8187+
8188+ if (ret != 0)
8189+ return ret;
8190+ }
8191+ if (ntalk > 0 || ntalk2 > 0) {
8192+ ret = ip_nat_helper_register(&talk_helpers[1]);
8193+
8194+ if (ret != 0 && talk > 0)
8195+ ip_nat_helper_unregister(&talk_helpers[0]);
8196+ }
8197+ return ret;
8198+}
8199+
8200+static void __exit fini(void)
8201+{
8202+ if (talk > 0)
8203+ ip_nat_helper_unregister(&talk_helpers[0]);
8204+ if (ntalk > 0 || ntalk2 > 0)
8205+ ip_nat_helper_unregister(&talk_helpers[1]);
8206+}
8207+
8208+module_init(init);
8209+module_exit(fini);
8210diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c
8211--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
8212+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c 2004-04-30 09:10:40.000000000 +0200
8213@@ -0,0 +1,334 @@
8214+/* Kernel module for IP pool management */
8215+
8216+#include <linux/module.h>
8217+#include <linux/ip.h>
8218+#include <linux/skbuff.h>
8219+#include <linux/netfilter_ipv4/ip_tables.h>
8220+#include <linux/netfilter_ipv4/ip_pool.h>
8221+#include <linux/errno.h>
8222+#include <asm/uaccess.h>
8223+#include <asm/bitops.h>
8224+#include <linux/interrupt.h>
8225+#include <linux/spinlock.h>
8226+
8227+#if 0
8228+#define DP printk
8229+#else
8230+#define DP(format, args...)
8231+#endif
8232+
8233+MODULE_LICENSE("GPL");
8234+
8235+#define NR_POOL 16
8236+static int nr_pool = NR_POOL;/* overwrite this when loading module */
8237+
8238+struct ip_pool {
8239+ u_int32_t first_ip; /* host byte order, included in range */
8240+ u_int32_t last_ip; /* host byte order, included in range */
8241+ void *members; /* the bitmap proper */
8242+ int nr_use; /* total nr. of tests through this */
8243+ int nr_match; /* total nr. of matches through this */
8244+ rwlock_t lock;
8245+};
8246+
8247+static struct ip_pool *POOL;
8248+
8249+static inline struct ip_pool *lookup(ip_pool_t index)
8250+{
8251+ if (index < 0 || index >= nr_pool) {
8252+ DP("ip_pool:lookup: bad index %d\n", index);
8253+ return 0;
8254+ }
8255+ return POOL+index;
8256+}
8257+
8258+int ip_pool_match(ip_pool_t index, u_int32_t addr)
8259+{
8260+ struct ip_pool *pool = lookup(index);
8261+ int res = 0;
8262+
8263+ if (!pool || !pool->members)
8264+ return 0;
8265+ read_lock_bh(&pool->lock);
8266+ if (pool->members) {
8267+ if (addr >= pool->first_ip && addr <= pool->last_ip) {
8268+ addr -= pool->first_ip;
8269+ if (test_bit(addr, pool->members)) {
8270+ res = 1;
8271+#ifdef CONFIG_IP_POOL_STATISTICS
8272+ pool->nr_match++;
8273+#endif
8274+ }
8275+ }
8276+#ifdef CONFIG_IP_POOL_STATISTICS
8277+ pool->nr_use++;
8278+#endif
8279+ }
8280+ read_unlock_bh(&pool->lock);
8281+ return res;
8282+}
8283+EXPORT_SYMBOL(ip_pool_match);
8284+
8285+static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8286+{
8287+ struct ip_pool *pool;
8288+ int res = -1;
8289+
8290+ pool = lookup(index);
8291+ if ( !pool || !pool->members
8292+ || addr < pool->first_ip || addr > pool->last_ip)
8293+ return -1;
8294+ read_lock_bh(&pool->lock);
8295+ if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8296+ addr -= pool->first_ip;
8297+ res = isdel
8298+ ? (0 != test_and_clear_bit(addr, pool->members))
8299+ : (0 != test_and_set_bit(addr, pool->members));
8300+ }
8301+ read_unlock_bh(&pool->lock);
8302+ return res;
8303+}
8304+
8305+int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8306+{
8307+ int res = pool_change(index,addr,isdel);
8308+
8309+ if (!isdel) res = !res;
8310+ return res;
8311+}
8312+EXPORT_SYMBOL(ip_pool_mod);
8313+
8314+static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8315+{
8316+ return 4*((((b-a+8)/8)+3)/4);
8317+}
8318+
8319+static inline int poolbytes(ip_pool_t index)
8320+{
8321+ struct ip_pool *pool = lookup(index);
8322+
8323+ return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8324+}
8325+
8326+static int setpool(
8327+ struct sock *sk,
8328+ int optval,
8329+ void *user,
8330+ unsigned int len
8331+) {
8332+ struct ip_pool_request req;
8333+
8334+ DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8335+ if (!capable(CAP_NET_ADMIN))
8336+ return -EPERM;
8337+ if (optval != SO_IP_POOL)
8338+ return -EBADF;
8339+ if (len != sizeof(req))
8340+ return -EINVAL;
8341+ if (copy_from_user(&req, user, sizeof(req)) != 0)
8342+ return -EFAULT;
8343+ printk("obsolete op - upgrade your ippool(8) utility.\n");
8344+ return -EINVAL;
8345+}
8346+
8347+static int getpool(
8348+ struct sock *sk,
8349+ int optval,
8350+ void *user,
8351+ int *len
8352+) {
8353+ struct ip_pool_request req;
8354+ struct ip_pool *pool;
8355+ ip_pool_t i;
8356+ int newbytes;
8357+ void *newmembers;
8358+ int res;
8359+
8360+ DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
8361+ if (!capable(CAP_NET_ADMIN))
8362+ return -EINVAL;
8363+ if (optval != SO_IP_POOL)
8364+ return -EINVAL;
8365+ if (*len != sizeof(req)) {
8366+ return -EFAULT;
8367+ }
8368+ if (copy_from_user(&req, user, sizeof(req)) != 0)
8369+ return -EFAULT;
8370+ DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
8371+ if (req.op < IP_POOL_BAD001) {
8372+ printk("obsolete op - upgrade your ippool(8) utility.\n");
8373+ return -EFAULT;
8374+ }
8375+ switch(req.op) {
8376+ case IP_POOL_HIGH_NR:
8377+ DP("ip_pool HIGH_NR\n");
8378+ req.index = IP_POOL_NONE;
8379+ for (i=0; i<nr_pool; i++)
8380+ if (POOL[i].members)
8381+ req.index = i;
8382+ return copy_to_user(user, &req, sizeof(req));
8383+ case IP_POOL_LOOKUP:
8384+ DP("ip_pool LOOKUP\n");
8385+ pool = lookup(req.index);
8386+ if (!pool)
8387+ return -EINVAL;
8388+ if (!pool->members)
8389+ return -EBADF;
8390+ req.addr = htonl(pool->first_ip);
8391+ req.addr2 = htonl(pool->last_ip);
8392+ return copy_to_user(user, &req, sizeof(req));
8393+ case IP_POOL_USAGE:
8394+ DP("ip_pool USE\n");
8395+ pool = lookup(req.index);
8396+ if (!pool)
8397+ return -EINVAL;
8398+ if (!pool->members)
8399+ return -EBADF;
8400+ req.addr = pool->nr_use;
8401+ req.addr2 = pool->nr_match;
8402+ return copy_to_user(user, &req, sizeof(req));
8403+ case IP_POOL_TEST_ADDR:
8404+ DP("ip_pool TEST 0x%08x\n", req.addr);
8405+ pool = lookup(req.index);
8406+ if (!pool)
8407+ return -EINVAL;
8408+ res = 0;
8409+ read_lock_bh(&pool->lock);
8410+ if (!pool->members) {
8411+ DP("ip_pool TEST_ADDR no members in pool\n");
8412+ res = -EBADF;
8413+ goto unlock_and_return_res;
8414+ }
8415+ req.addr = ntohl(req.addr);
8416+ if (req.addr < pool->first_ip) {
8417+ DP("ip_pool TEST_ADDR address < pool bounds\n");
8418+ res = -ERANGE;
8419+ goto unlock_and_return_res;
8420+ }
8421+ if (req.addr > pool->last_ip) {
8422+ DP("ip_pool TEST_ADDR address > pool bounds\n");
8423+ res = -ERANGE;
8424+ goto unlock_and_return_res;
8425+ }
8426+ req.addr = (0 != test_bit((req.addr - pool->first_ip),
8427+ pool->members));
8428+ read_unlock_bh(&pool->lock);
8429+ return copy_to_user(user, &req, sizeof(req));
8430+ case IP_POOL_FLUSH:
8431+ DP("ip_pool FLUSH not yet implemented.\n");
8432+ return -EBUSY;
8433+ case IP_POOL_DESTROY:
8434+ DP("ip_pool DESTROY not yet implemented.\n");
8435+ return -EBUSY;
8436+ case IP_POOL_INIT:
8437+ DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
8438+ pool = lookup(req.index);
8439+ if (!pool)
8440+ return -EINVAL;
8441+ req.addr = ntohl(req.addr);
8442+ req.addr2 = ntohl(req.addr2);
8443+ if (req.addr > req.addr2) {
8444+ DP("ip_pool INIT bad ip range\n");
8445+ return -EINVAL;
8446+ }
8447+ newbytes = bitmap_bytes(req.addr, req.addr2);
8448+ newmembers = kmalloc(newbytes, GFP_KERNEL);
8449+ if (!newmembers) {
8450+ DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
8451+ return -ENOMEM;
8452+ }
8453+ memset(newmembers, 0, newbytes);
8454+ write_lock_bh(&pool->lock);
8455+ if (pool->members) {
8456+ DP("ip_pool INIT pool %d exists\n", req.index);
8457+ kfree(newmembers);
8458+ res = -EBUSY;
8459+ goto unlock_and_return_res;
8460+ }
8461+ pool->first_ip = req.addr;
8462+ pool->last_ip = req.addr2;
8463+ pool->nr_use = 0;
8464+ pool->nr_match = 0;
8465+ pool->members = newmembers;
8466+ write_unlock_bh(&pool->lock);
8467+ return 0;
8468+ case IP_POOL_ADD_ADDR:
8469+ DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
8470+ req.addr = pool_change(req.index, ntohl(req.addr), 0);
8471+ return copy_to_user(user, &req, sizeof(req));
8472+ case IP_POOL_DEL_ADDR:
8473+ DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
8474+ req.addr = pool_change(req.index, ntohl(req.addr), 1);
8475+ return copy_to_user(user, &req, sizeof(req));
8476+ default:
8477+ DP("ip_pool:getpool bad op %d\n", req.op);
8478+ return -EINVAL;
8479+ }
8480+ return -EINVAL;
8481+
8482+unlock_and_return_res:
8483+ if (pool)
8484+ read_unlock_bh(&pool->lock);
8485+ return res;
8486+}
8487+
8488+static struct nf_sockopt_ops so_pool
8489+= { { NULL, NULL }, PF_INET,
8490+ SO_IP_POOL, SO_IP_POOL+1, &setpool,
8491+ SO_IP_POOL, SO_IP_POOL+1, &getpool,
8492+ 0, NULL };
8493+
8494+MODULE_PARM(nr_pool, "i");
8495+
8496+static int __init init(void)
8497+{
8498+ ip_pool_t i;
8499+ int res;
8500+
8501+ if (nr_pool < 1) {
8502+ printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
8503+ return -EINVAL;
8504+ }
8505+ POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
8506+ if (!POOL) {
8507+ printk("ip_pool module init: out of memory for nr_pool %d\n",
8508+ nr_pool);
8509+ return -ENOMEM;
8510+ }
8511+ for (i=0; i<nr_pool; i++) {
8512+ POOL[i].first_ip = 0;
8513+ POOL[i].last_ip = 0;
8514+ POOL[i].members = 0;
8515+ POOL[i].nr_use = 0;
8516+ POOL[i].nr_match = 0;
8517+ POOL[i].lock = RW_LOCK_UNLOCKED;
8518+ }
8519+ res = nf_register_sockopt(&so_pool);
8520+ DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
8521+ if (res != 0) {
8522+ kfree(POOL);
8523+ POOL = 0;
8524+ }
8525+ return res;
8526+}
8527+
8528+static void __exit fini(void)
8529+{
8530+ ip_pool_t i;
8531+
8532+ DP("ip_pool:fini BYEBYE\n");
8533+ nf_unregister_sockopt(&so_pool);
8534+ for (i=0; i<nr_pool; i++) {
8535+ if (POOL[i].members) {
8536+ kfree(POOL[i].members);
8537+ POOL[i].members = 0;
8538+ }
8539+ }
8540+ kfree(POOL);
8541+ POOL = 0;
8542+ DP("ip_pool:fini these are the famous last words\n");
8543+ return;
8544+}
8545+
8546+module_init(init);
8547+module_exit(fini);
8548diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c
8549--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-04-28 03:35:21.000000000 +0200
8550+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c 2004-04-30 09:11:53.000000000 +0200
8551@@ -29,6 +29,14 @@
8552
8553 #include <linux/netfilter_ipv4/ip_tables.h>
8554
8555+static const char *hooknames[] = {
8556+ [NF_IP_PRE_ROUTING] "PREROUTING",
8557+ [NF_IP_LOCAL_IN] "INPUT",
8558+ [NF_IP_FORWARD] "FORWARD",
8559+ [NF_IP_LOCAL_OUT] "OUTPUT",
8560+ [NF_IP_POST_ROUTING] "POSTROUTING",
8561+};
8562+
8563 MODULE_LICENSE("GPL");
8564 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8565 MODULE_DESCRIPTION("IPv4 packet filter");
8566@@ -326,6 +334,12 @@
8567
8568 t = ipt_get_target(e);
8569 IP_NF_ASSERT(t->u.kernel.target);
8570+
8571+ /* The packet traced and the rule isn't an unconditional return/END. */
8572+ if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
8573+ nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8574+ table->name, e->chainname, e->rulenum);
8575+ }
8576 /* Standard target? */
8577 if (!t->u.kernel.target->target) {
8578 int v;
8579@@ -352,7 +366,6 @@
8580 /* set back pointer to next entry */
8581 back = next;
8582 }
8583-
8584 e = get_entry(table_base, v);
8585 } else {
8586 /* Targets which reenter must return
8587@@ -478,6 +491,29 @@
8588 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8589 }
8590
8591+static inline int
8592+find_error_target(struct ipt_entry *s,
8593+ struct ipt_entry *e,
8594+ char **chainname)
8595+{
8596+ struct ipt_entry_target *t;
8597+ static struct ipt_entry *found = NULL;
8598+
8599+ if (s == e) {
8600+ if (!found)
8601+ return 0;
8602+ t = ipt_get_target(found);
8603+ if (strcmp(t->u.user.name,
8604+ IPT_ERROR_TARGET) == 0) {
8605+ *chainname = t->data;
8606+ return 1;
8607+ }
8608+ } else
8609+ found = s;
8610+
8611+ return 0;
8612+}
8613+
8614 /* All zeroes == unconditional rule. */
8615 static inline int
8616 unconditional(const struct ipt_ip *ip)
8617@@ -497,6 +533,8 @@
8618 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
8619 {
8620 unsigned int hook;
8621+ char *chainname = NULL;
8622+ u_int32_t rulenum;
8623
8624 /* No recursion; use packet counter to save back ptrs (reset
8625 to 0 as we leave), and comefrom to save source hook bitmask */
8626@@ -510,6 +548,8 @@
8627
8628 /* Set initial back pointer. */
8629 e->counters.pcnt = pos;
8630+ rulenum = 1;
8631+ chainname = (char *) hooknames[hook];
8632
8633 for (;;) {
8634 struct ipt_standard_target *t
8635@@ -522,6 +562,8 @@
8636 }
8637 e->comefrom
8638 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
8639+ e->rulenum = rulenum++;
8640+ e->chainname = chainname;
8641
8642 /* Unconditional return/END. */
8643 if (e->target_offset == sizeof(struct ipt_entry)
8644@@ -531,6 +573,10 @@
8645 && unconditional(&e->ip)) {
8646 unsigned int oldpos, size;
8647
8648+ /* Set unconditional rulenum to zero. */
8649+ e->rulenum = 0;
8650+ e->counters.bcnt = 0;
8651+
8652 /* Return: backtrack through the last
8653 big jump. */
8654 do {
8655@@ -556,6 +602,11 @@
8656 (newinfo->entries + pos);
8657 } while (oldpos == pos + e->next_offset);
8658
8659+ /* Restore chainname, rulenum. */
8660+ chainname = e->chainname;
8661+ rulenum = e->counters.bcnt;
8662+ e->counters.bcnt = 0;
8663+
8664 /* Move along one */
8665 size = e->next_offset;
8666 e = (struct ipt_entry *)
8667@@ -571,6 +622,17 @@
8668 /* This a jump; chase it. */
8669 duprintf("Jump rule %u -> %u\n",
8670 pos, newpos);
8671+ e->counters.bcnt = rulenum++;
8672+ rulenum = 1;
8673+ e = (struct ipt_entry *)
8674+ (newinfo->entries + newpos);
8675+ if (IPT_ENTRY_ITERATE(newinfo->entries,
8676+ newinfo->size,
8677+ find_error_target,
8678+ e, &chainname) == 0) {
8679+ printk("ip_tables: table screwed up!\n");
8680+ return 0;
8681+ }
8682 } else {
8683 /* ... this is a fallthru */
8684 newpos = pos + e->next_offset;
8685@@ -1716,9 +1778,9 @@
8686 };
8687
8688 #ifdef CONFIG_PROC_FS
8689-static inline int print_name(const char *i,
8690- off_t start_offset, char *buffer, int length,
8691- off_t *pos, unsigned int *count)
8692+static int print_name(const char *i,
8693+ off_t start_offset, char *buffer, int length,
8694+ off_t *pos, unsigned int *count)
8695 {
8696 if ((*count)++ >= start_offset) {
8697 unsigned int namelen;
8698@@ -1752,6 +1814,15 @@
8699 return pos;
8700 }
8701
8702+static inline int print_target(const struct ipt_target *t,
8703+ off_t start_offset, char *buffer, int length,
8704+ off_t *pos, unsigned int *count)
8705+{
8706+ if (t != &ipt_standard_target && t != &ipt_error_target)
8707+ return 0;
8708+ return print_name((char *)t, start_offset, buffer, length, pos, count);
8709+}
8710+
8711 static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
8712 {
8713 off_t pos = 0;
8714@@ -1760,7 +1831,7 @@
8715 if (down_interruptible(&ipt_mutex) != 0)
8716 return 0;
8717
8718- LIST_FIND(&ipt_target, print_name, void *,
8719+ LIST_FIND(&ipt_target, print_target, struct ipt_target *,
8720 offset, buffer, length, &pos, &count);
8721
8722 up(&ipt_mutex);
8723diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
8724--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
8725+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c 2004-04-30 09:11:35.000000000 +0200
8726@@ -0,0 +1,118 @@
8727+/* This kernel module is used to modify the connection mark values, or
8728+ * to optionally restore the skb nfmark from the connection mark
8729+ *
8730+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8731+ * by Henrik Nordstrom <hno@marasystems.com>
8732+ *
8733+ * This program is free software; you can redistribute it and/or modify
8734+ * it under the terms of the GNU General Public License as published by
8735+ * the Free Software Foundation; either version 2 of the License, or
8736+ * (at your option) any later version.
8737+ *
8738+ * This program is distributed in the hope that it will be useful,
8739+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8740+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8741+ * GNU General Public License for more details.
8742+ *
8743+ * You should have received a copy of the GNU General Public License
8744+ * along with this program; if not, write to the Free Software
8745+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8746+ */
8747+#include <linux/module.h>
8748+#include <linux/skbuff.h>
8749+#include <linux/ip.h>
8750+#include <net/checksum.h>
8751+
8752+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8753+MODULE_DESCRIPTION("IP tables CONNMARK matching module");
8754+MODULE_LICENSE("GPL");
8755+
8756+#include <linux/netfilter_ipv4/ip_tables.h>
8757+#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
8758+#include <linux/netfilter_ipv4/ip_conntrack.h>
8759+
8760+static unsigned int
8761+target(struct sk_buff **pskb,
8762+ const struct net_device *in,
8763+ const struct net_device *out,
8764+ unsigned int hooknum,
8765+ const void *targinfo,
8766+ void *userinfo)
8767+{
8768+ const struct ipt_connmark_target_info *markinfo = targinfo;
8769+ unsigned long diff;
8770+ unsigned long nfmark;
8771+ unsigned long newmark;
8772+
8773+ enum ip_conntrack_info ctinfo;
8774+ struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
8775+ if (ct) {
8776+ switch(markinfo->mode) {
8777+ case IPT_CONNMARK_SET:
8778+ newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
8779+ if (newmark != ct->mark)
8780+ ct->mark = newmark;
8781+ break;
8782+ case IPT_CONNMARK_SAVE:
8783+ newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
8784+ if (ct->mark != newmark)
8785+ ct->mark = newmark;
8786+ break;
8787+ case IPT_CONNMARK_RESTORE:
8788+ nfmark = (*pskb)->nfmark;
8789+ diff = (ct->mark ^ nfmark & markinfo->mask);
8790+ if (diff != 0) {
8791+ (*pskb)->nfmark = nfmark ^ diff;
8792+ (*pskb)->nfcache |= NFC_ALTERED;
8793+ }
8794+ break;
8795+ }
8796+ }
8797+
8798+ return IPT_CONTINUE;
8799+}
8800+
8801+static int
8802+checkentry(const char *tablename,
8803+ const struct ipt_entry *e,
8804+ void *targinfo,
8805+ unsigned int targinfosize,
8806+ unsigned int hook_mask)
8807+{
8808+ struct ipt_connmark_target_info *matchinfo = targinfo;
8809+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
8810+ printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
8811+ targinfosize,
8812+ IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
8813+ return 0;
8814+ }
8815+
8816+ if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
8817+ if (strcmp(tablename, "mangle") != 0) {
8818+ printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8819+ return 0;
8820+ }
8821+ }
8822+
8823+ return 1;
8824+}
8825+
8826+static struct ipt_target ipt_connmark_reg = {
8827+ .name = "CONNMARK",
8828+ .target = &target,
8829+ .checkentry = &checkentry,
8830+ .me = THIS_MODULE
8831+};
8832+
8833+static int __init init(void)
8834+{
8835+ return ipt_register_target(&ipt_connmark_reg);
8836+}
8837+
8838+static void __exit fini(void)
8839+{
8840+ ipt_unregister_target(&ipt_connmark_reg);
8841+}
8842+
8843+module_init(init);
8844+module_exit(fini);
8845diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c
8846--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
8847+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c 2004-04-30 09:11:38.000000000 +0200
8848@@ -0,0 +1,81 @@
8849+/* This is a module which is used for setting the NFMARK field of an skb. */
8850+#include <linux/module.h>
8851+#include <linux/skbuff.h>
8852+#include <linux/ip.h>
8853+#include <net/checksum.h>
8854+
8855+#include <linux/netfilter_ipv4/ip_tables.h>
8856+#include <linux/netfilter_ipv4/ipt_IPMARK.h>
8857+
8858+MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
8859+MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
8860+MODULE_LICENSE("GPL");
8861+
8862+static unsigned int
8863+target(struct sk_buff **pskb,
8864+ const struct net_device *in,
8865+ const struct net_device *out,
8866+ unsigned int hooknum,
8867+ const void *targinfo,
8868+ void *userinfo)
8869+{
8870+ const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
8871+ struct iphdr *iph = (*pskb)->nh.iph;
8872+ unsigned long mark;
8873+
8874+ if (ipmarkinfo->addr == IPT_IPMARK_SRC)
8875+ mark = (unsigned long) ntohl(iph->saddr);
8876+ else
8877+ mark = (unsigned long) ntohl(iph->daddr);
8878+
8879+ mark &= ipmarkinfo->andmask;
8880+ mark |= ipmarkinfo->ormask;
8881+
8882+ if ((*pskb)->nfmark != mark) {
8883+ (*pskb)->nfmark = mark;
8884+ (*pskb)->nfcache |= NFC_ALTERED;
8885+ }
8886+ return IPT_CONTINUE;
8887+}
8888+
8889+static int
8890+checkentry(const char *tablename,
8891+ const struct ipt_entry *e,
8892+ void *targinfo,
8893+ unsigned int targinfosize,
8894+ unsigned int hook_mask)
8895+{
8896+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
8897+ printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
8898+ targinfosize,
8899+ IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
8900+ return 0;
8901+ }
8902+
8903+ if (strcmp(tablename, "mangle") != 0) {
8904+ printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8905+ return 0;
8906+ }
8907+
8908+ return 1;
8909+}
8910+
8911+static struct ipt_target ipt_ipmark_reg = {
8912+ .name = "IPMARK",
8913+ .target = target,
8914+ .checkentry = checkentry,
8915+ .me = THIS_MODULE
8916+};
8917+
8918+static int __init init(void)
8919+{
8920+ return ipt_register_target(&ipt_ipmark_reg);
8921+}
8922+
8923+static void __exit fini(void)
8924+{
8925+ ipt_unregister_target(&ipt_ipmark_reg);
8926+}
8927+
8928+module_init(init);
8929+module_exit(fini);
8930diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
8931--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
8932+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-04-30 09:10:05.000000000 +0200
8933@@ -0,0 +1,89 @@
8934+/**
8935+ * Strip all IP options in the IP packet header.
8936+ *
8937+ * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
8938+ * This software is distributed under GNU GPL v2, 1991
8939+ */
8940+
8941+#include <linux/module.h>
8942+#include <linux/skbuff.h>
8943+#include <linux/ip.h>
8944+#include <net/checksum.h>
8945+
8946+#include <linux/netfilter_ipv4/ip_tables.h>
8947+
8948+MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
8949+MODULE_DESCRIPTION("Strip all options in IPv4 packets");
8950+MODULE_LICENSE("GPL");
8951+
8952+static unsigned int
8953+target(struct sk_buff **pskb,
8954+ const struct net_device *in,
8955+ const struct net_device *out,
8956+ unsigned int hooknum,
8957+ const void *targinfo,
8958+ void *userinfo)
8959+{
8960+ struct iphdr *iph;
8961+ struct sk_buff *skb;
8962+ struct ip_options *opt;
8963+ unsigned char *optiph;
8964+ int l;
8965+
8966+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
8967+ return NF_DROP;
8968+
8969+ skb = (*pskb);
8970+ iph = (*pskb)->nh.iph;
8971+ optiph = skb->nh.raw;
8972+ l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
8973+
8974+ /* if no options in packet then nothing to clear. */
8975+ if (iph->ihl * 4 == sizeof(struct iphdr))
8976+ return IPT_CONTINUE;
8977+
8978+ /* else clear all options */
8979+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
8980+ memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
8981+ opt = &(IPCB(skb)->opt);
8982+ opt->is_data = 0;
8983+ opt->optlen = l;
8984+
8985+ skb->nfcache |= NFC_ALTERED;
8986+
8987+ return IPT_CONTINUE;
8988+}
8989+
8990+static int
8991+checkentry(const char *tablename,
8992+ const struct ipt_entry *e,
8993+ void *targinfo,
8994+ unsigned int targinfosize,
8995+ unsigned int hook_mask)
8996+{
8997+ if (strcmp(tablename, "mangle")) {
8998+ printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8999+ return 0;
9000+ }
9001+ /* nothing else to check because no parameters */
9002+ return 1;
9003+}
9004+
9005+static struct ipt_target ipt_ipv4optsstrip_reg = {
9006+ .name = "IPV4OPTSSTRIP",
9007+ .target = target,
9008+ .checkentry = checkentry,
9009+ .me = THIS_MODULE };
9010+
9011+static int __init init(void)
9012+{
9013+ return ipt_register_target(&ipt_ipv4optsstrip_reg);
9014+}
9015+
9016+static void __exit fini(void)
9017+{
9018+ ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9019+}
9020+
9021+module_init(init);
9022+module_exit(fini);
9023diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c
9024--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
9025+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c 2004-04-30 09:10:09.000000000 +0200
9026@@ -0,0 +1,119 @@
9027+#include <linux/module.h>
9028+#include <linux/version.h>
9029+#include <linux/config.h>
9030+#include <linux/socket.h>
9031+#include <linux/skbuff.h>
9032+#include <linux/kernel.h>
9033+#include <linux/netlink.h>
9034+#include <linux/netdevice.h>
9035+#include <linux/mm.h>
9036+#include <linux/socket.h>
9037+#include <linux/netfilter_ipv4/ip_tables.h>
9038+#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9039+#include <net/sock.h>
9040+
9041+MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9042+MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9043+MODULE_LICENSE("GPL");
9044+
9045+#if 0
9046+#define DEBUGP printk
9047+#else
9048+#define DEBUGP(format, args...)
9049+#endif
9050+
9051+static struct sock *ipfwsk;
9052+
9053+static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9054+ unsigned int hooknum,
9055+ const struct net_device *in,
9056+ const struct net_device *out,
9057+ const void *targinfo, void *userinfo)
9058+{
9059+ struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9060+ struct iphdr *ip = (*pskb)->nh.iph;
9061+ struct sk_buff *outskb;
9062+ struct netlink_t nlhdr;
9063+ size_t len=0;
9064+
9065+ /* Allocate a socket buffer */
9066+ if ( MASK(nld->flags, USE_SIZE) )
9067+ len = nld->size+sizeof(nlhdr);
9068+ else
9069+ len = ntohs(ip->tot_len)+sizeof(nlhdr);
9070+
9071+ outskb=alloc_skb(len, GFP_ATOMIC);
9072+
9073+ if (outskb) {
9074+ nlhdr.len=len;
9075+
9076+ if ( MASK(nld->flags, USE_MARK) )
9077+ nlhdr.mark=(*pskb)->nfmark=nld->mark;
9078+ else
9079+ nlhdr.mark=(*pskb)->nfmark;
9080+
9081+ if ( in && in->name ) {
9082+ strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9083+ }else if ( out && out->name ){
9084+ strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9085+ }
9086+
9087+ skb_put(outskb, len);
9088+ memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9089+ memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9090+ netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9091+ }else{
9092+ if (net_ratelimit())
9093+ printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9094+ }
9095+
9096+ if ( MASK(nld->flags, USE_DROP) )
9097+ return NF_DROP;
9098+
9099+ return IPT_CONTINUE;
9100+}
9101+
9102+static int ipt_netlink_checkentry(const char *tablename,
9103+ const struct ipt_entry *e,
9104+ void *targinfo,
9105+ unsigned int targinfosize,
9106+ unsigned int hookmask)
9107+{
9108+ //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9109+
9110+ return 1;
9111+}
9112+
9113+static struct ipt_target ipt_netlink_reg = {
9114+ {NULL, NULL},
9115+ "NETLINK",
9116+ ipt_netlink_target,
9117+ ipt_netlink_checkentry,
9118+ NULL,
9119+ THIS_MODULE
9120+};
9121+
9122+static int __init init(void)
9123+{
9124+ DEBUGP("ipt_NETLINK: init module\n");
9125+
9126+ if (ipt_register_target(&ipt_netlink_reg) != 0) {
9127+ return -EINVAL;
9128+ }
9129+
9130+ if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9131+ return -EINVAL;
9132+ }
9133+
9134+ return 0;
9135+}
9136+
9137+static void __exit fini(void)
9138+{
9139+ DEBUGP("ipt_NETLINK: cleanup_module\n");
9140+ ipt_unregister_target(&ipt_netlink_reg);
9141+ if(ipfwsk->sk_socket) sock_release(ipfwsk->sk_socket);
9142+}
9143+
9144+module_init(init);
9145+module_exit(fini);
9146diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c
9147--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
9148+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c 2004-04-30 09:10:40.000000000 +0200
9149@@ -0,0 +1,116 @@
9150+/* ipt_POOL.c - netfilter target to manipulate IP pools
9151+ *
9152+ * This target can be used almost everywhere. It acts on some specified
9153+ * IP pool, adding or deleting some IP address in the pool. The address
9154+ * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9155+ * of the packet under inspection.
9156+ *
9157+ * The target normally returns IPT_CONTINUE.
9158+ */
9159+
9160+#include <linux/types.h>
9161+#include <linux/ip.h>
9162+#include <linux/timer.h>
9163+#include <linux/module.h>
9164+#include <linux/netfilter.h>
9165+#include <linux/netdevice.h>
9166+#include <linux/if.h>
9167+#include <linux/inetdevice.h>
9168+#include <net/protocol.h>
9169+#include <net/checksum.h>
9170+#include <linux/netfilter_ipv4.h>
9171+#include <linux/netfilter_ipv4/ip_nat_rule.h>
9172+#include <linux/netfilter_ipv4/ipt_pool.h>
9173+
9174+#if 0
9175+#define DEBUGP printk
9176+#else
9177+#define DEBUGP(format, args...)
9178+#endif
9179+
9180+/*** NOTE NOTE NOTE NOTE ***
9181+**
9182+** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9183+** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9184+** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9185+** is modified for the source IP address of the packet under inspection.
9186+** The same way, the ipt_pool_info.dst pool is modified for the destination.
9187+**
9188+** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9189+** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9190+**
9191+** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9192+** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9193+** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9194+** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9195+*/
9196+
9197+static int
9198+do_check(const char *tablename,
9199+ const struct ipt_entry *e,
9200+ void *targinfo,
9201+ unsigned int targinfosize,
9202+ unsigned int hook_mask)
9203+{
9204+ const struct ipt_pool_info *ipi = targinfo;
9205+
9206+ if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9207+ DEBUGP("POOL_check: size %u.\n", targinfosize);
9208+ return 0;
9209+ }
9210+ DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9211+ return 1;
9212+}
9213+
9214+static unsigned int
9215+do_target(struct sk_buff **pskb,
9216+ unsigned int hooknum,
9217+ const struct net_device *in,
9218+ const struct net_device *out,
9219+ const void *targinfo,
9220+ void *userinfo)
9221+{
9222+ const struct ipt_pool_info *ipi = targinfo;
9223+ int modified;
9224+ unsigned int verdict = IPT_CONTINUE;
9225+
9226+ if (ipi->src != IP_POOL_NONE) {
9227+ modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9228+ ipi->flags & IPT_POOL_DEL_SRC);
9229+ if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9230+ if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9231+ verdict = NF_ACCEPT;
9232+ else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9233+ verdict = NF_DROP;
9234+ }
9235+ }
9236+ if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9237+ modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9238+ ipi->flags & IPT_POOL_DEL_DST);
9239+ if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9240+ if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9241+ verdict = NF_ACCEPT;
9242+ else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9243+ verdict = NF_DROP;
9244+ }
9245+ }
9246+ return verdict;
9247+}
9248+
9249+static struct ipt_target pool_reg
9250+= { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9251+
9252+static int __init init(void)
9253+{
9254+ DEBUGP("init ipt_POOL\n");
9255+ return ipt_register_target(&pool_reg);
9256+}
9257+
9258+static void __exit fini(void)
9259+{
9260+ DEBUGP("fini ipt_POOL\n");
9261+ ipt_unregister_target(&pool_reg);
9262+}
9263+
9264+module_init(init);
9265+module_exit(fini);
9266diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c
9267--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
9268+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c 2004-04-30 09:11:46.000000000 +0200
9269@@ -0,0 +1,289 @@
9270+/*
9271+ * Kernel module to capture and hold incoming TCP connections using
9272+ * no local per-connection resources.
9273+ *
9274+ * Based on ipt_REJECT.c and offering functionality similar to
9275+ * LaBrea <http://www.hackbusters.net/LaBrea/>.
9276+ *
9277+ * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
9278+ *
9279+ * This program is free software; you can redistribute it and/or modify
9280+ * it under the terms of the GNU General Public License as published by
9281+ * the Free Software Foundation; either version 2 of the License, or
9282+ * (at your option) any later version.
9283+ *
9284+ * This program is distributed in the hope that it will be useful,
9285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9287+ * GNU General Public License for more details.
9288+ *
9289+ * You should have received a copy of the GNU General Public License
9290+ * along with this program; if not, write to the Free Software
9291+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
9292+ *
9293+ * Goal:
9294+ * - Allow incoming TCP connections to be established.
9295+ * - Passing data should result in the connection being switched to the
9296+ * persist state (0 byte window), in which the remote side stops sending
9297+ * data and asks to continue every 60 seconds.
9298+ * - Attempts to shut down the connection should be ignored completely, so
9299+ * the remote side ends up having to time it out.
9300+ *
9301+ * This means:
9302+ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
9303+ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
9304+ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
9305+ */
9306+
9307+#include <linux/config.h>
9308+#include <linux/module.h>
9309+#include <linux/skbuff.h>
9310+#include <linux/ip.h>
9311+#include <net/ip.h>
9312+#include <net/tcp.h>
9313+#include <net/icmp.h>
9314+struct in_device;
9315+#include <net/route.h>
9316+#include <linux/random.h>
9317+#include <linux/netfilter_ipv4/ip_tables.h>
9318+
9319+#if 0
9320+#define DEBUGP printk
9321+#else
9322+#define DEBUGP(format, args...)
9323+#endif
9324+
9325+MODULE_LICENSE("GPL");
9326+MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
9327+
9328+/* Stolen from ip_finish_output2 */
9329+static int ip_direct_send(struct sk_buff *skb)
9330+{
9331+ struct dst_entry *dst = skb->dst;
9332+ struct hh_cache *hh = dst->hh;
9333+
9334+ if (hh) {
9335+ read_lock_bh(&hh->hh_lock);
9336+ memcpy(skb->data - 16, hh->hh_data, 16);
9337+ read_unlock_bh(&hh->hh_lock);
9338+ skb_push(skb, hh->hh_len);
9339+ return hh->hh_output(skb);
9340+ } else if (dst->neighbour)
9341+ return dst->neighbour->output(skb);
9342+
9343+ if (net_ratelimit())
9344+ printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
9345+ kfree_skb(skb);
9346+ return -EINVAL;
9347+}
9348+
9349+
9350+/* Send reply */
9351+static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
9352+{
9353+ struct sk_buff *nskb;
9354+ struct rtable *nrt;
9355+ struct tcphdr *otcph, *ntcph;
9356+ unsigned int otcplen;
9357+ u_int16_t tmp;
9358+ struct flowi fl = {};
9359+
9360+ /* A truncated TCP header isn't going to be useful */
9361+ if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
9362+ return;
9363+
9364+ otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
9365+ + oskb->nh.iph->ihl);
9366+ otcplen = oskb->len - oskb->nh.iph->ihl*4;
9367+
9368+ /* No replies for RST or FIN */
9369+ if (otcph->rst || otcph->fin)
9370+ return;
9371+
9372+ /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
9373+ if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
9374+ return;
9375+
9376+ /* Check checksum. */
9377+ if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
9378+ oskb->nh.iph->daddr,
9379+ csum_partial((char *)otcph, otcplen, 0)) != 0)
9380+ return;
9381+
9382+ /* Copy skb (even if skb is about to be dropped, we can't just
9383+ clone it because there may be other things, such as tcpdump,
9384+ interested in it) */
9385+ nskb = skb_copy(oskb, GFP_ATOMIC);
9386+ if (!nskb)
9387+ return;
9388+
9389+ /* This packet will not be the same as the other: clear nf fields */
9390+ nf_conntrack_put(nskb->nfct);
9391+ nskb->nfct = NULL;
9392+ nskb->nfcache = 0;
9393+#ifdef CONFIG_NETFILTER_DEBUG
9394+ nskb->nf_debug = 0;
9395+#endif
9396+
9397+ ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
9398+
9399+ /* Truncate to length (no data) */
9400+ ntcph->doff = sizeof(struct tcphdr)/4;
9401+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
9402+ nskb->nh.iph->tot_len = htons(nskb->len);
9403+
9404+ /* Swap source and dest */
9405+ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
9406+ tmp = ntcph->source;
9407+ ntcph->source = ntcph->dest;
9408+ ntcph->dest = tmp;
9409+
9410+ /* Use supplied sequence number or make a new one */
9411+ ntcph->seq = otcph->ack ? otcph->ack_seq
9412+ : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
9413+ nskb->nh.iph->daddr,
9414+ ntcph->source,
9415+ ntcph->dest));
9416+
9417+ /* Our SYN-ACKs must have a >0 window */
9418+ ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
9419+
9420+ ntcph->urg_ptr = 0;
9421+
9422+ /* Reset flags */
9423+ ((u_int8_t *)ntcph)[13] = 0;
9424+
9425+ if (otcph->syn && otcph->ack) {
9426+ ntcph->rst = 1;
9427+ ntcph->ack_seq = 0;
9428+ } else {
9429+ ntcph->syn = otcph->syn;
9430+ ntcph->ack = 1;
9431+ ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
9432+ }
9433+
9434+ /* Adjust TCP checksum */
9435+ ntcph->check = 0;
9436+ ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
9437+ nskb->nh.iph->saddr,
9438+ nskb->nh.iph->daddr,
9439+ csum_partial((char *)ntcph,
9440+ sizeof(struct tcphdr), 0));
9441+
9442+ /* Adjust IP TTL */
9443+ nskb->nh.iph->ttl = sysctl_ip_default_ttl;
9444+
9445+ /* Set DF, id = 0 */
9446+ nskb->nh.iph->frag_off = htons(IP_DF);
9447+ nskb->nh.iph->id = 0;
9448+
9449+ /* Adjust IP checksum */
9450+ nskb->nh.iph->check = 0;
9451+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
9452+ nskb->nh.iph->ihl);
9453+
9454+ fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
9455+ fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
9456+ fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
9457+ fl.oif = 0;
9458+ if (ip_route_output_key(&nrt, &fl) != 0)
9459+ goto free_nskb;
9460+
9461+ dst_release(nskb->dst);
9462+ nskb->dst = &nrt->u.dst;
9463+
9464+ /* "Never happens" */
9465+ if (nskb->len > dst_pmtu(nskb->dst))
9466+ goto free_nskb;
9467+
9468+ ip_direct_send (nskb);
9469+
9470+ return;
9471+
9472+ free_nskb:
9473+ kfree_skb(nskb);
9474+}
9475+
9476+
9477+static unsigned int tarpit(struct sk_buff **pskb,
9478+ const struct net_device *in,
9479+ const struct net_device *out,
9480+ unsigned int hooknum,
9481+ const void *targinfo,
9482+ void *userinfo)
9483+{
9484+ struct sk_buff *skb = *pskb;
9485+ struct rtable *rt = (struct rtable*)skb->dst;
9486+
9487+ /* Do we have an input route cache entry? */
9488+ if (!rt)
9489+ return NF_DROP;
9490+
9491+ /* No replies to physical multicast/broadcast */
9492+ if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
9493+ return NF_DROP;
9494+
9495+ /* Now check at the protocol level */
9496+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
9497+ return NF_DROP;
9498+
9499+ /* Our naive response construction doesn't deal with IP
9500+ options, and probably shouldn't try. */
9501+ if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
9502+ return NF_DROP;
9503+
9504+ /* We aren't interested in fragments */
9505+ if (skb->nh.iph->frag_off & htons(IP_OFFSET))
9506+ return NF_DROP;
9507+
9508+ tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
9509+
9510+ return NF_DROP;
9511+}
9512+
9513+
9514+static int check(const char *tablename,
9515+ const struct ipt_entry *e,
9516+ void *targinfo,
9517+ unsigned int targinfosize,
9518+ unsigned int hook_mask)
9519+{
9520+ /* Only allow these for input/forward packet filtering. */
9521+ if (strcmp(tablename, "filter") != 0) {
9522+ DEBUGP("TARPIT: bad table %s'.\n", tablename);
9523+ return 0;
9524+ }
9525+ if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
9526+ | (1 << NF_IP_FORWARD))) != 0) {
9527+ DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
9528+ return 0;
9529+ }
9530+
9531+ /* Must specify that it's a TCP packet */
9532+ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
9533+ DEBUGP("TARPIT: not valid for non-tcp\n");
9534+ return 0;
9535+ }
9536+
9537+ return 1;
9538+}
9539+
9540+static struct ipt_target ipt_tarpit_reg = {
9541+ .name = "TARPIT",
9542+ .target = tarpit,
9543+ .checkentry = check,
9544+ .me = THIS_MODULE
9545+};
9546+
9547+static int __init init(void)
9548+{
9549+ return ipt_register_target(&ipt_tarpit_reg);
9550+}
9551+
9552+static void __exit fini(void)
9553+{
9554+ ipt_unregister_target(&ipt_tarpit_reg);
9555+}
9556+
9557+module_init(init);
9558+module_exit(fini);
9559diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c
9560--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
9561+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c 2004-04-30 09:11:53.000000000 +0200
9562@@ -0,0 +1,64 @@
9563+/* This is a module which is used for setting
9564+ * the NFC_TRACE flag in the nfcache field of an skb.
9565+ */
9566+#include <linux/module.h>
9567+#include <linux/skbuff.h>
9568+
9569+#include <linux/netfilter_ipv4/ip_tables.h>
9570+
9571+static unsigned int
9572+target(struct sk_buff **pskb,
9573+ const struct net_device *in,
9574+ const struct net_device *out,
9575+ unsigned int hooknum,
9576+ const void *targinfo,
9577+ void *userinfo)
9578+{
9579+ (*pskb)->nfcache |= NFC_TRACE;
9580+ return IPT_CONTINUE;
9581+}
9582+
9583+static int
9584+checkentry(const char *tablename,
9585+ const struct ipt_entry *e,
9586+ void *targinfo,
9587+ unsigned int targinfosize,
9588+ unsigned int hook_mask)
9589+{
9590+ if (targinfosize != 0) {
9591+ printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
9592+ targinfosize);
9593+ return 0;
9594+ }
9595+
9596+ if (strcmp(tablename, "raw") != 0) {
9597+ printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
9598+ return 0;
9599+ }
9600+
9601+ return 1;
9602+}
9603+
9604+static struct ipt_target ipt_trace_reg = {
9605+ .name = "TRACE",
9606+ .target = target,
9607+ .checkentry = checkentry,
9608+ .me = THIS_MODULE
9609+};
9610+
9611+static int __init init(void)
9612+{
9613+ if (ipt_register_target(&ipt_trace_reg))
9614+ return -EINVAL;
9615+
9616+ return 0;
9617+}
9618+
9619+static void __exit fini(void)
9620+{
9621+ ipt_unregister_target(&ipt_trace_reg);
9622+}
9623+
9624+module_init(init);
9625+module_exit(fini);
9626+MODULE_LICENSE("GPL");
9627diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c
9628--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
9629+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c 2004-04-30 09:10:15.000000000 +0200
9630@@ -0,0 +1,120 @@
9631+/* TTL modification target for IP tables
9632+ * (C) 2000 by Harald Welte <laforge@gnumonks.org>
9633+ *
9634+ * Version: $Revision$
9635+ *
9636+ * This software is distributed under the terms of GNU GPL
9637+ */
9638+
9639+#include <linux/module.h>
9640+#include <linux/skbuff.h>
9641+#include <linux/ip.h>
9642+#include <net/checksum.h>
9643+
9644+#include <linux/netfilter_ipv4/ip_tables.h>
9645+#include <linux/netfilter_ipv4/ipt_TTL.h>
9646+
9647+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
9648+MODULE_DESCRIPTION("IP tables TTL modification module");
9649+MODULE_LICENSE("GPL");
9650+
9651+static unsigned int
9652+ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
9653+ const struct net_device *out, unsigned int hooknum,
9654+ const void *targinfo, void *userinfo)
9655+{
9656+ struct iphdr *iph;
9657+ const struct ipt_TTL_info *info = targinfo;
9658+ u_int16_t diffs[2];
9659+ int new_ttl;
9660+
9661+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
9662+ return NF_DROP;
9663+
9664+ iph = (*pskb)->nh.iph;
9665+
9666+ switch (info->mode) {
9667+ case IPT_TTL_SET:
9668+ new_ttl = info->ttl;
9669+ break;
9670+ case IPT_TTL_INC:
9671+ new_ttl = iph->ttl + info->ttl;
9672+ if (new_ttl > 255)
9673+ new_ttl = 255;
9674+ break;
9675+ case IPT_TTL_DEC:
9676+ new_ttl = iph->ttl + info->ttl;
9677+ if (new_ttl < 0)
9678+ new_ttl = 0;
9679+ break;
9680+ default:
9681+ new_ttl = iph->ttl;
9682+ break;
9683+ }
9684+
9685+ if (new_ttl != iph->ttl) {
9686+ diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
9687+ iph->ttl = new_ttl;
9688+ diffs[1] = htons(((unsigned)iph->ttl) << 8);
9689+ iph->check = csum_fold(csum_partial((char *)diffs,
9690+ sizeof(diffs),
9691+ iph->check^0xFFFF));
9692+ (*pskb)->nfcache |= NFC_ALTERED;
9693+ }
9694+
9695+ return IPT_CONTINUE;
9696+}
9697+
9698+static int ipt_ttl_checkentry(const char *tablename,
9699+ const struct ipt_entry *e,
9700+ void *targinfo,
9701+ unsigned int targinfosize,
9702+ unsigned int hook_mask)
9703+{
9704+ struct ipt_TTL_info *info = targinfo;
9705+
9706+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
9707+ printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
9708+ targinfosize,
9709+ IPT_ALIGN(sizeof(struct ipt_TTL_info)));
9710+ return 0;
9711+ }
9712+
9713+ if (strcmp(tablename, "mangle")) {
9714+ printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9715+ return 0;
9716+ }
9717+
9718+ if (info->mode > IPT_TTL_MAXMODE) {
9719+ printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
9720+ info->mode);
9721+ return 0;
9722+ }
9723+
9724+ if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
9725+ printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
9726+ return 0;
9727+ }
9728+
9729+ return 1;
9730+}
9731+
9732+static struct ipt_target ipt_TTL = {
9733+ .name = "TTL",
9734+ .target = ipt_ttl_target,
9735+ .checkentry = ipt_ttl_checkentry,
9736+ .me = THIS_MODULE
9737+};
9738+
9739+static int __init init(void)
9740+{
9741+ return ipt_register_target(&ipt_TTL);
9742+}
9743+
9744+static void __exit fini(void)
9745+{
9746+ ipt_unregister_target(&ipt_TTL);
9747+}
9748+
9749+module_init(init);
9750+module_exit(fini);
9751diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c
9752--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
9753+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c 2004-04-30 09:11:56.000000000 +0200
9754@@ -0,0 +1,117 @@
9755+/* XOR target for IP tables
9756+ * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9757+ * Based on ipt_TTL.c
9758+ *
9759+ * Version 1.0
9760+ *
9761+ * This software is distributed under the terms of GNU GPL
9762+ */
9763+
9764+#include <linux/module.h>
9765+#include <linux/skbuff.h>
9766+#include <linux/ip.h>
9767+#include <linux/tcp.h>
9768+#include <linux/udp.h>
9769+
9770+#include <linux/netfilter_ipv4/ip_tables.h>
9771+#include <linux/netfilter_ipv4/ipt_XOR.h>
9772+
9773+MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9774+MODULE_DESCRIPTION("IP tables XOR module");
9775+MODULE_LICENSE("GPL");
9776+
9777+static unsigned int
9778+ipt_xor_target(struct sk_buff **pskb,
9779+ const struct net_device *in, const struct net_device *out,
9780+ unsigned int hooknum, const void *targinfo, void *userinfo)
9781+{
9782+ struct ipt_XOR_info *info = (void *) targinfo;
9783+ struct iphdr *iph;
9784+ struct tcphdr *tcph;
9785+ struct udphdr *udph;
9786+ int i, j, k;
9787+
9788+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
9789+ return NF_DROP;
9790+
9791+ iph = (*pskb)->nh.iph;
9792+
9793+ if (iph->protocol == IPPROTO_TCP) {
9794+ tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9795+ for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9796+ for (k=0; k<=info->block_size; k++) {
9797+ (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
9798+ info->key[j];
9799+ i++;
9800+ }
9801+ j++;
9802+ if (info->key[j] == 0x00)
9803+ j = 0;
9804+ }
9805+ } else if (iph->protocol == IPPROTO_UDP) {
9806+ udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9807+ for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9808+ for (k=0; k<=info->block_size; k++) {
9809+ (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
9810+ info->key[j];
9811+ i++;
9812+ }
9813+ j++;
9814+ if (info->key[j] == 0x00)
9815+ j = 0;
9816+ }
9817+ }
9818+
9819+ return IPT_CONTINUE;
9820+}
9821+
9822+static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9823+ void *targinfo, unsigned int targinfosize,
9824+ unsigned int hook_mask)
9825+{
9826+ struct ipt_XOR_info *info = targinfo;
9827+
9828+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9829+ printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
9830+ targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9831+ return 0;
9832+ }
9833+
9834+ if (strcmp(tablename, "mangle")) {
9835+ printk(KERN_WARNING "XOR: can only be called from"
9836+ "\"mangle\" table, not \"%s\"\n", tablename);
9837+ return 0;
9838+ }
9839+
9840+ if (!strcmp(info->key, "")) {
9841+ printk(KERN_WARNING "XOR: You must specify a key");
9842+ return 0;
9843+ }
9844+
9845+ if (info->block_size == 0) {
9846+ printk(KERN_WARNING "XOR: You must specify a block-size");
9847+ return 0;
9848+ }
9849+
9850+ return 1;
9851+}
9852+
9853+static struct ipt_target ipt_XOR = {
9854+ .name = "XOR",
9855+ .target = ipt_xor_target,
9856+ .checkentry = ipt_xor_checkentry,
9857+ .me = THIS_MODULE,
9858+};
9859+
9860+static int __init init(void)
9861+{
9862+ return ipt_register_target(&ipt_XOR);
9863+}
9864+
9865+static void __exit fini(void)
9866+{
9867+ ipt_unregister_target(&ipt_XOR);
9868+}
9869+
9870+module_init(init);
9871+module_exit(fini);
9872diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c
9873--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
9874+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c 2004-04-30 09:11:57.000000000 +0200
9875@@ -0,0 +1,68 @@
9876+/*
9877+ * iptables module to match inet_addr_type() of an ip.
9878+ */
9879+
9880+#include <linux/module.h>
9881+#include <linux/skbuff.h>
9882+#include <linux/netdevice.h>
9883+#include <net/route.h>
9884+
9885+#include <linux/netfilter_ipv4/ipt_addrtype.h>
9886+#include <linux/netfilter_ipv4/ip_tables.h>
9887+
9888+MODULE_LICENSE("GPL");
9889+
9890+static inline int match_type(u_int32_t addr, u_int16_t mask)
9891+{
9892+ return !!(mask & (1 << inet_addr_type(addr)));
9893+}
9894+
9895+static int match(const struct sk_buff *skb, const struct net_device *in,
9896+ const struct net_device *out, const void *matchinfo,
9897+ int offset, int *hotdrop)
9898+{
9899+ const struct ipt_addrtype_info *info = matchinfo;
9900+ const struct iphdr *iph = skb->nh.iph;
9901+ int ret = 1;
9902+
9903+ if (info->source)
9904+ ret &= match_type(iph->saddr, info->source)^info->invert_source;
9905+ if (info->dest)
9906+ ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9907+
9908+ return ret;
9909+}
9910+
9911+static int checkentry(const char *tablename, const struct ipt_ip *ip,
9912+ void *matchinfo, unsigned int matchsize,
9913+ unsigned int hook_mask)
9914+{
9915+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9916+ printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9917+ matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9918+ return 0;
9919+ }
9920+
9921+ return 1;
9922+}
9923+
9924+static struct ipt_match addrtype_match = {
9925+ .name = "addrtype",
9926+ .match = match,
9927+ .checkentry = checkentry,
9928+ .me = THIS_MODULE
9929+};
9930+
9931+static int __init init(void)
9932+{
9933+ return ipt_register_match(&addrtype_match);
9934+}
9935+
9936+static void __exit fini(void)
9937+{
9938+ ipt_unregister_match(&addrtype_match);
9939+
9940+}
9941+
9942+module_init(init);
9943+module_exit(fini);
9944diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c
9945--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
9946+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c 2004-04-30 09:10:17.000000000 +0200
9947@@ -0,0 +1,230 @@
9948+/*
9949+ * netfilter module to limit the number of parallel tcp
9950+ * connections per IP address.
9951+ * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
9952+ * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
9953+ * only ignore TIME_WAIT or gone connections
9954+ *
9955+ * based on ...
9956+ *
9957+ * Kernel module to match connection tracking information.
9958+ * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
9959+ */
9960+#include <linux/module.h>
9961+#include <linux/skbuff.h>
9962+#include <linux/list.h>
9963+#include <linux/netfilter_ipv4/ip_conntrack.h>
9964+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
9965+#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
9966+#include <linux/netfilter_ipv4/ip_tables.h>
9967+#include <linux/netfilter_ipv4/ipt_connlimit.h>
9968+
9969+#define DEBUG 0
9970+
9971+MODULE_LICENSE("GPL");
9972+
9973+/* we'll save the tuples of all connections we care about */
9974+struct ipt_connlimit_conn
9975+{
9976+ struct list_head list;
9977+ struct ip_conntrack_tuple tuple;
9978+};
9979+
9980+struct ipt_connlimit_data {
9981+ spinlock_t lock;
9982+ struct list_head iphash[256];
9983+};
9984+
9985+static int ipt_iphash(u_int32_t addr)
9986+{
9987+ int hash;
9988+
9989+ hash = addr & 0xff;
9990+ hash ^= (addr >> 8) & 0xff;
9991+ hash ^= (addr >> 16) & 0xff;
9992+ hash ^= (addr >> 24) & 0xff;
9993+ return hash;
9994+}
9995+
9996+static int count_them(struct ipt_connlimit_data *data,
9997+ u_int32_t addr, u_int32_t mask,
9998+ struct ip_conntrack *ct)
9999+{
10000+#if DEBUG
10001+ const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
10002+ "fin_wait", "time_wait", "close", "close_wait",
10003+ "last_ack", "listen" };
10004+#endif
10005+ int addit = 1, matches = 0;
10006+ struct ip_conntrack_tuple tuple;
10007+ struct ip_conntrack_tuple_hash *found;
10008+ struct ipt_connlimit_conn *conn;
10009+ struct list_head *hash,*lh;
10010+
10011+ spin_lock(&data->lock);
10012+ tuple = ct->tuplehash[0].tuple;
10013+ hash = &data->iphash[ipt_iphash(addr & mask)];
10014+
10015+ /* check the saved connections */
10016+ for (lh = hash->next; lh != hash; lh = lh->next) {
10017+ conn = list_entry(lh,struct ipt_connlimit_conn,list);
10018+ found = ip_conntrack_find_get(&conn->tuple,ct);
10019+ if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
10020+ found != NULL &&
10021+ found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
10022+ /* Just to be sure we have it only once in the list.
10023+ We should'nt see tuples twice unless someone hooks this
10024+ into a table without "-p tcp --syn" */
10025+ addit = 0;
10026+ }
10027+#if DEBUG
10028+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
10029+ ipt_iphash(addr & mask),
10030+ NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
10031+ NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
10032+ (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
10033+#endif
10034+ if (NULL == found) {
10035+ /* this one is gone */
10036+ lh = lh->prev;
10037+ list_del(lh->next);
10038+ kfree(conn);
10039+ continue;
10040+ }
10041+ if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
10042+ /* we don't care about connections which are
10043+ closed already -> ditch it */
10044+ lh = lh->prev;
10045+ list_del(lh->next);
10046+ kfree(conn);
10047+ nf_conntrack_put(&found->ctrack->infos[0]);
10048+ continue;
10049+ }
10050+ if ((addr & mask) == (conn->tuple.src.ip & mask)) {
10051+ /* same source IP address -> be counted! */
10052+ matches++;
10053+ }
10054+ nf_conntrack_put(&found->ctrack->infos[0]);
10055+ }
10056+ if (addit) {
10057+ /* save the new connection in our list */
10058+#if DEBUG
10059+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
10060+ ipt_iphash(addr & mask),
10061+ NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
10062+ NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
10063+#endif
10064+ conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
10065+ if (NULL == conn)
10066+ return -1;
10067+ memset(conn,0,sizeof(*conn));
10068+ INIT_LIST_HEAD(&conn->list);
10069+ conn->tuple = tuple;
10070+ list_add(&conn->list,hash);
10071+ matches++;
10072+ }
10073+ spin_unlock(&data->lock);
10074+ return matches;
10075+}
10076+
10077+static int
10078+match(const struct sk_buff *skb,
10079+ const struct net_device *in,
10080+ const struct net_device *out,
10081+ const void *matchinfo,
10082+ int offset,
10083+ int *hotdrop)
10084+{
10085+ const struct ipt_connlimit_info *info = matchinfo;
10086+ int connections, match;
10087+ struct ip_conntrack *ct;
10088+ enum ip_conntrack_info ctinfo;
10089+
10090+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10091+ if (NULL == ct) {
10092+ printk("ipt_connlimit: Oops: invalid ct state ?\n");
10093+ *hotdrop = 1;
10094+ return 0;
10095+ }
10096+ connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
10097+ if (-1 == connections) {
10098+ printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
10099+ *hotdrop = 1; /* let's free some memory :-) */
10100+ return 0;
10101+ }
10102+ match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
10103+#if DEBUG
10104+ printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
10105+ "connections=%d limit=%d match=%s\n",
10106+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
10107+ connections, info->limit, match ? "yes" : "no");
10108+#endif
10109+
10110+ return match;
10111+}
10112+
10113+static int check(const char *tablename,
10114+ const struct ipt_ip *ip,
10115+ void *matchinfo,
10116+ unsigned int matchsize,
10117+ unsigned int hook_mask)
10118+{
10119+ struct ipt_connlimit_info *info = matchinfo;
10120+ int i;
10121+
10122+ /* verify size */
10123+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
10124+ return 0;
10125+
10126+ /* refuse anything but tcp */
10127+ if (ip->proto != IPPROTO_TCP)
10128+ return 0;
10129+
10130+ /* init private data */
10131+ info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
10132+ spin_lock_init(&(info->data->lock));
10133+ for (i = 0; i < 256; i++)
10134+ INIT_LIST_HEAD(&(info->data->iphash[i]));
10135+
10136+ return 1;
10137+}
10138+
10139+static void destroy(void *matchinfo, unsigned int matchinfosize)
10140+{
10141+ struct ipt_connlimit_info *info = matchinfo;
10142+ struct ipt_connlimit_conn *conn;
10143+ struct list_head *hash;
10144+ int i;
10145+
10146+ /* cleanup */
10147+ for (i = 0; i < 256; i++) {
10148+ hash = &(info->data->iphash[i]);
10149+ while (hash != hash->next) {
10150+ conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
10151+ list_del(hash->next);
10152+ kfree(conn);
10153+ }
10154+ }
10155+ kfree(info->data);
10156+}
10157+
10158+static struct ipt_match connlimit_match = {
10159+ .name = "connlimit",
10160+ .match = &match,
10161+ .checkentry = &check,
10162+ .destroy = &destroy,
10163+ .me = THIS_MODULE
10164+};
10165+
10166+static int __init init(void)
10167+{
10168+ return ipt_register_match(&connlimit_match);
10169+}
10170+
10171+static void __exit fini(void)
10172+{
10173+ ipt_unregister_match(&connlimit_match);
10174+}
10175+
10176+module_init(init);
10177+module_exit(fini);
10178diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c
10179--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
10180+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c 2004-04-30 09:11:35.000000000 +0200
10181@@ -0,0 +1,81 @@
10182+/* This kernel module matches connection mark values set by the
10183+ * CONNMARK target
10184+ *
10185+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
10186+ * by Henrik Nordstrom <hno@marasystems.com>
10187+ *
10188+ * This program is free software; you can redistribute it and/or modify
10189+ * it under the terms of the GNU General Public License as published by
10190+ * the Free Software Foundation; either version 2 of the License, or
10191+ * (at your option) any later version.
10192+ *
10193+ * This program is distributed in the hope that it will be useful,
10194+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10195+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10196+ * GNU General Public License for more details.
10197+ *
10198+ * You should have received a copy of the GNU General Public License
10199+ * along with this program; if not, write to the Free Software
10200+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10201+ */
10202+
10203+#include <linux/module.h>
10204+#include <linux/skbuff.h>
10205+
10206+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
10207+MODULE_DESCRIPTION("IP tables connmark match module");
10208+MODULE_LICENSE("GPL");
10209+
10210+#include <linux/netfilter_ipv4/ip_tables.h>
10211+#include <linux/netfilter_ipv4/ipt_connmark.h>
10212+#include <linux/netfilter_ipv4/ip_conntrack.h>
10213+
10214+static int
10215+match(const struct sk_buff *skb,
10216+ const struct net_device *in,
10217+ const struct net_device *out,
10218+ const void *matchinfo,
10219+ int offset,
10220+ int *hotdrop)
10221+{
10222+ const struct ipt_connmark_info *info = matchinfo;
10223+ enum ip_conntrack_info ctinfo;
10224+ struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10225+ if (!ct)
10226+ return 0;
10227+
10228+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
10229+}
10230+
10231+static int
10232+checkentry(const char *tablename,
10233+ const struct ipt_ip *ip,
10234+ void *matchinfo,
10235+ unsigned int matchsize,
10236+ unsigned int hook_mask)
10237+{
10238+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
10239+ return 0;
10240+
10241+ return 1;
10242+}
10243+
10244+static struct ipt_match connmark_match = {
10245+ .name = "connmark",
10246+ .match = &match,
10247+ .checkentry = &checkentry,
10248+ .me = THIS_MODULE
10249+};
10250+
10251+static int __init init(void)
10252+{
10253+ return ipt_register_match(&connmark_match);
10254+}
10255+
10256+static void __exit fini(void)
10257+{
10258+ ipt_unregister_match(&connmark_match);
10259+}
10260+
10261+module_init(init);
10262+module_exit(fini);
10263diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c
10264--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
10265+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c 2004-04-30 09:10:21.000000000 +0200
10266@@ -0,0 +1,690 @@
10267+/* iptables match extension to limit the number of packets per second
10268+ * seperately for each destination.
10269+ *
10270+ * (C) 2003 by Harald Welte <laforge@netfilter.org>
10271+ *
10272+ * $Id$
10273+ *
10274+ * Development of this code was funded by Astaro AG, http://www.astaro.com/
10275+ *
10276+ * based on ipt_limit.c by:
10277