]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.6-rc3-patch-o-matic-ng-extra-20040429.patch
- [sparc32] grsec disabled.
[packages/kernel.git] / 2.6.6-rc3-patch-o-matic-ng-extra-20040429.patch
CommitLineData
384c1045 1diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter.h linux-2.6.6-rc3/include/linux/netfilter.h
2--- linux-2.6.6-rc3.org/include/linux/netfilter.h 2004-04-28 03:35:48.000000000 +0200
3+++ linux-2.6.6-rc3/include/linux/netfilter.h 2004-04-29 11:18:06.000000000 +0200
4@@ -23,6 +23,7 @@
5 <= 0x2000 is used for protocol-flags. */
6 #define NFC_UNKNOWN 0x4000
7 #define NFC_ALTERED 0x8000
8+#define NFC_TRACE 0x10000
9
10 #ifdef __KERNEL__
11 #include <linux/config.h>
12@@ -137,12 +138,14 @@
13 /* This is gross, but inline doesn't cut it for avoiding the function
14 call in fast path: gcc doesn't inline (needs value tracking?). --RR */
15 #ifdef CONFIG_NETFILTER_DEBUG
16-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
17- nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
18+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
19+(!(cond) \
20+ ? (okfn)(skb) \
21+ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
22 #define NF_HOOK_THRESH nf_hook_slow
23 #else
24-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
25-(list_empty(&nf_hooks[(pf)][(hook)]) \
26+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
27+(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
28 ? (okfn)(skb) \
29 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
30 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
31@@ -150,6 +153,8 @@
32 ? (okfn)(skb) \
33 : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
34 #endif
35+#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
36+ NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
37
38 int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
39 struct net_device *indev, struct net_device *outdev,
40@@ -182,7 +187,24 @@
41
42 #else /* !CONFIG_NETFILTER */
43 #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
44+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
45 #endif /*CONFIG_NETFILTER*/
46
47+#ifdef CONFIG_XFRM
48+#ifdef CONFIG_IP_NF_NAT_NEEDED
49+struct flowi;
50+extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
51+
52+static inline void
53+nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
54+{
55+ if (family == AF_INET)
56+ nf_nat_decode_session4(skb, fl);
57+}
58+#else /* CONFIG_IP_NF_NAT_NEEDED */
59+#define nf_nat_decode_session(skb,fl,family)
60+#endif /* CONFIG_IP_NF_NAT_NEEDED */
61+#endif /* CONFIG_XFRM */
62+
63 #endif /*__KERNEL__*/
64 #endif /*__LINUX_NETFILTER_H*/
65diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h linux-2.6.6-rc3/include/linux/netfilter_helpers.h
66--- linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h 1970-01-01 01:00:00.000000000 +0100
67+++ linux-2.6.6-rc3/include/linux/netfilter_helpers.h 2004-04-29 11:20:13.000000000 +0200
68@@ -0,0 +1,133 @@
69+/*
70+ * Helpers for netfiler modules. This file provides implementations for basic
71+ * functions such as strncasecmp(), etc.
72+ *
73+ * gcc will warn for defined but unused functions, so we only include the
74+ * functions requested. The following macros are used:
75+ * NF_NEED_STRNCASECMP nf_strncasecmp()
76+ * NF_NEED_STRTOU16 nf_strtou16()
77+ * NF_NEED_STRTOU32 nf_strtou32()
78+ */
79+#ifndef _NETFILTER_HELPERS_H
80+#define _NETFILTER_HELPERS_H
81+
82+/* Only include these functions for kernel code. */
83+#ifdef __KERNEL__
84+
85+#include <linux/ctype.h>
86+#define iseol(c) ( (c) == '\r' || (c) == '\n' )
87+
88+/*
89+ * The standard strncasecmp()
90+ */
91+#ifdef NF_NEED_STRNCASECMP
92+static int
93+nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
94+{
95+ if (s1 == NULL || s2 == NULL)
96+ {
97+ if (s1 == NULL && s2 == NULL)
98+ {
99+ return 0;
100+ }
101+ return (s1 == NULL) ? -1 : 1;
102+ }
103+ while (len > 0 && tolower(*s1) == tolower(*s2))
104+ {
105+ len--;
106+ s1++;
107+ s2++;
108+ }
109+ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
110+}
111+#endif /* NF_NEED_STRNCASECMP */
112+
113+/*
114+ * Parse a string containing a 16-bit unsigned integer.
115+ * Returns the number of chars used, or zero if no number is found.
116+ */
117+#ifdef NF_NEED_STRTOU16
118+static int
119+nf_strtou16(const char* pbuf, u_int16_t* pval)
120+{
121+ int n = 0;
122+
123+ *pval = 0;
124+ while (isdigit(pbuf[n]))
125+ {
126+ *pval = (*pval * 10) + (pbuf[n] - '0');
127+ n++;
128+ }
129+
130+ return n;
131+}
132+#endif /* NF_NEED_STRTOU16 */
133+
134+/*
135+ * Parse a string containing a 32-bit unsigned integer.
136+ * Returns the number of chars used, or zero if no number is found.
137+ */
138+#ifdef NF_NEED_STRTOU32
139+static int
140+nf_strtou32(const char* pbuf, u_int32_t* pval)
141+{
142+ int n = 0;
143+
144+ *pval = 0;
145+ while (pbuf[n] >= '0' && pbuf[n] <= '9')
146+ {
147+ *pval = (*pval * 10) + (pbuf[n] - '0');
148+ n++;
149+ }
150+
151+ return n;
152+}
153+#endif /* NF_NEED_STRTOU32 */
154+
155+/*
156+ * Given a buffer and length, advance to the next line and mark the current
157+ * line.
158+ */
159+#ifdef NF_NEED_NEXTLINE
160+static int
161+nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
162+{
163+ uint off = *poff;
164+ uint physlen = 0;
165+
166+ if (off >= len)
167+ {
168+ return 0;
169+ }
170+
171+ while (p[off] != '\n')
172+ {
173+ if (len-off <= 1)
174+ {
175+ return 0;
176+ }
177+
178+ physlen++;
179+ off++;
180+ }
181+
182+ /* if we saw a crlf, physlen needs adjusted */
183+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
184+ {
185+ physlen--;
186+ }
187+
188+ /* advance past the newline */
189+ off++;
190+
191+ *plineoff = *poff;
192+ *plinelen = physlen;
193+ *poff = off;
194+
195+ return 1;
196+}
197+#endif /* NF_NEED_NEXTLINE */
198+
199+#endif /* __KERNEL__ */
200+
201+#endif /* _NETFILTER_HELPERS_H */
202diff -Nur --exclude '*.orig' 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
203--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-28 03:36:37.000000000 +0200
204+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-29 11:21:43.000000000 +0200
205@@ -51,10 +51,12 @@
206
207 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
208 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
209+#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
210
211 /* per conntrack: protocol private data */
212 union ip_conntrack_proto {
213 /* insert conntrack proto private data here */
214+ struct ip_ct_sctp sctp;
215 struct ip_ct_tcp tcp;
216 struct ip_ct_icmp icmp;
217 };
218@@ -64,6 +66,11 @@
219 };
220
221 /* Add protocol helper include file here */
222+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
223+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
224+#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
225+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
226+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
227 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
228 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
229 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
230@@ -71,6 +78,11 @@
231 /* per expectation: application helper private data */
232 union ip_conntrack_expect_help {
233 /* insert conntrack helper private data (expect) here */
234+ struct ip_ct_talk_expect exp_talk_info;
235+ struct ip_ct_rtsp_expect exp_rtsp_info;
236+ struct ip_ct_rsh_expect exp_rsh_info;
237+ struct ip_ct_mms_expect exp_mms_info;
238+ struct ip_ct_h225_expect exp_h225_info;
239 struct ip_ct_amanda_expect exp_amanda_info;
240 struct ip_ct_ftp_expect exp_ftp_info;
241 struct ip_ct_irc_expect exp_irc_info;
242@@ -85,6 +97,11 @@
243 /* per conntrack: application helper private data */
244 union ip_conntrack_help {
245 /* insert conntrack helper private data (master) here */
246+ struct ip_ct_talk_master ct_talk_info;
247+ struct ip_ct_rtsp_master ct_rtsp_info;
248+ struct ip_ct_rsh_master ct_rsh_info;
249+ struct ip_ct_mms_master ct_mms_info;
250+ struct ip_ct_h225_master ct_h225_info;
251 struct ip_ct_ftp_master ct_ftp_info;
252 struct ip_ct_irc_master ct_irc_info;
253 };
254@@ -207,6 +224,10 @@
255 } nat;
256 #endif /* CONFIG_IP_NF_NAT_NEEDED */
257
258+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
259+ unsigned long mark;
260+#endif
261+
262 };
263
264 /* get master conntrack via master expectation */
384c1045 265diff -Nur --exclude '*.orig' 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
266--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
267+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-04-29 11:18:00.000000000 +0200
268@@ -0,0 +1,31 @@
269+#ifndef _IP_CONNTRACK_H323_H
270+#define _IP_CONNTRACK_H323_H
271+/* H.323 connection tracking. */
272+
273+#ifdef __KERNEL__
274+/* Protects H.323 related data */
275+#include <linux/netfilter_ipv4/lockhelp.h>
276+DECLARE_LOCK_EXTERN(ip_h323_lock);
277+#endif
278+
279+/* Default H.225 port */
280+#define H225_PORT 1720
281+
282+/* This structure is per expected connection */
283+struct ip_ct_h225_expect {
284+ u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
285+ enum ip_conntrack_dir dir; /* Direction of the original connection */
286+ unsigned int offset; /* offset of the address in the payload */
287+};
288+
289+/* This structure exists only once per master */
290+struct ip_ct_h225_master {
291+ int is_h225; /* H.225 or H.245 connection */
292+#ifdef CONFIG_IP_NF_NAT_NEEDED
293+ enum ip_conntrack_dir dir; /* Direction of the original connection */
294+ u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
295+ unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
296+#endif
297+};
298+
299+#endif /* _IP_CONNTRACK_H323_H */
300diff -Nur --exclude '*.orig' 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
301--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
302+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-04-29 11:19:01.000000000 +0200
303@@ -0,0 +1,31 @@
304+#ifndef _IP_CONNTRACK_MMS_H
305+#define _IP_CONNTRACK_MMS_H
306+/* MMS tracking. */
307+
308+#ifdef __KERNEL__
309+#include <linux/netfilter_ipv4/lockhelp.h>
310+
311+DECLARE_LOCK_EXTERN(ip_mms_lock);
312+
313+#define MMS_PORT 1755
314+#define MMS_SRV_MSG_ID 196610
315+
316+#define MMS_SRV_MSG_OFFSET 36
317+#define MMS_SRV_UNICODE_STRING_OFFSET 60
318+#define MMS_SRV_CHUNKLENLV_OFFSET 16
319+#define MMS_SRV_CHUNKLENLM_OFFSET 32
320+#define MMS_SRV_MESSAGELENGTH_OFFSET 8
321+#endif
322+
323+/* This structure is per expected connection */
324+struct ip_ct_mms_expect {
325+ u_int32_t len;
326+ u_int32_t padding;
327+ u_int16_t port;
328+};
329+
330+/* This structure exists only once per master */
331+struct ip_ct_mms_master {
332+};
333+
334+#endif /* _IP_CONNTRACK_MMS_H */
335diff -Nur --exclude '*.orig' 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
336--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
337+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-04-29 11:19:53.000000000 +0200
338@@ -0,0 +1,21 @@
339+#ifndef _IP_CT_QUAKE3
340+#define _IP_CT_QUAKE3
341+
342+/* Don't confuse with 27960, often used as the Server Port */
343+#define QUAKE3_MASTER_PORT 27950
344+
345+struct quake3_search {
346+ const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
347+ const char *pattern;
348+ size_t plen;
349+};
350+
351+/* This structure is per expected connection */
352+struct ip_ct_quake3_expect {
353+};
354+
355+/* This structure exists only once per master */
356+struct ip_ct_quake3_master {
357+};
358+
359+#endif /* _IP_CT_QUAKE3 */
360diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
361--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
362+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2004-04-29 11:20:02.000000000 +0200
363@@ -0,0 +1,68 @@
364+/* RPC extension for IP connection tracking, Version 2.2
365+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
366+ * - original rpc tracking module
367+ * - "recent" connection handling for kernel 2.3+ netfilter
368+ *
369+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
370+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
371+ *
372+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
373+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
374+ * - extended matching to support filtering on procedures
375+ *
376+ * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
377+ *
378+ * This program is free software; you can redistribute it and/or
379+ * modify it under the terms of the GNU General Public License
380+ * as published by the Free Software Foundation; either version
381+ * 2 of the License, or (at your option) any later version.
382+ **
383+ */
384+
385+#include <asm/param.h>
386+#include <linux/sched.h>
387+#include <linux/timer.h>
388+#include <linux/stddef.h>
389+#include <linux/list.h>
390+
391+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
392+
393+#ifndef _IP_CONNTRACK_RPC_H
394+#define _IP_CONNTRACK_RPC_H
395+
396+#define RPC_PORT 111
397+
398+
399+/* Datum in RPC packets are encoded in XDR */
400+#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
401+
402+/* Fast timeout, to deny DoS atacks */
403+#define EXP (60 * HZ)
404+
405+/* Normal timeouts */
406+#define EXPIRES (180 * HZ)
407+
408+/* For future conections RPC, using client's cache bindings
409+ * I'll use ip_conntrack_lock to lock these lists */
410+
411+/* This identifies each request and stores protocol */
412+struct request_p {
413+ struct list_head list;
414+
415+ u_int32_t xid;
416+ u_int32_t ip;
417+ u_int16_t port;
418+
419+ /* Protocol */
420+ u_int16_t proto;
421+
422+ struct timer_list timeout;
423+};
424+
425+static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
426+ u_int32_t ip, u_int32_t port) {
427+ return (p->xid == xid && p->ip == ip && p->port);
428+
429+}
430+
431+#endif /* _IP_CONNTRACK_RPC_H */
432diff -Nur --exclude '*.orig' 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
433--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
434+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-04-29 11:20:06.000000000 +0200
435@@ -0,0 +1,35 @@
436+/* RSH extension for IP connection tracking, Version 1.0
437+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
438+ * based on HW's ip_conntrack_irc.c
439+ *
440+ * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
441+ *
442+ * This program is free software; you can redistribute it and/or
443+ * modify it under the terms of the GNU General Public License
444+ * as published by the Free Software Foundation; either version
445+ * 2 of the License, or (at your option) any later version.
446+ */
447+#ifndef _IP_CONNTRACK_RSH_H
448+#define _IP_CONNTRACK_RSH_H
449+
450+#ifdef __KERNEL__
451+#include <linux/netfilter_ipv4/lockhelp.h>
452+
453+DECLARE_LOCK_EXTERN(ip_rsh_lock);
454+#endif
455+
456+
457+#define RSH_PORT 514
458+
459+/* This structure is per expected connection */
460+struct ip_ct_rsh_expect
461+{
462+ u_int16_t port;
463+};
464+
465+/* This structure exists only once per master */
466+struct ip_ct_rsh_master {
467+};
468+
469+#endif /* _IP_CONNTRACK_RSH_H */
470+
471diff -Nur --exclude '*.orig' 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
472--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
473+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-04-29 11:20:13.000000000 +0200
474@@ -0,0 +1,68 @@
475+/*
476+ * RTSP extension for IP connection tracking.
477+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
478+ * based on ip_conntrack_irc.h
479+ *
480+ * This program is free software; you can redistribute it and/or
481+ * modify it under the terms of the GNU General Public License
482+ * as published by the Free Software Foundation; either version
483+ * 2 of the License, or (at your option) any later version.
484+ */
485+#ifndef _IP_CONNTRACK_RTSP_H
486+#define _IP_CONNTRACK_RTSP_H
487+
488+/* #define IP_NF_RTSP_DEBUG */
489+#define IP_NF_RTSP_VERSION "0.01"
490+
491+/* port block types */
492+typedef enum {
493+ pb_single, /* client_port=x */
494+ pb_range, /* client_port=x-y */
495+ pb_discon /* client_port=x/y (rtspbis) */
496+} portblock_t;
497+
498+/* We record seq number and length of rtsp headers here, all in host order. */
499+
500+/*
501+ * This structure is per expected connection. It is a member of struct
502+ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
503+ * there and we are expected to only store the length of the data which
504+ * needs replaced. If a packet contains multiple RTSP messages, we create
505+ * one expected connection per message.
506+ *
507+ * We use these variables to mark the entire header block. This may seem
508+ * like overkill, but the nature of RTSP requires it. A header may appear
509+ * multiple times in a message. We must treat two Transport headers the
510+ * same as one Transport header with two entries.
511+ */
512+struct ip_ct_rtsp_expect
513+{
514+ u_int32_t len; /* length of header block */
515+ portblock_t pbtype; /* Type of port block that was requested */
516+ u_int16_t loport; /* Port that was requested, low or first */
517+ u_int16_t hiport; /* Port that was requested, high or second */
518+#if 0
519+ uint method; /* RTSP method */
520+ uint cseq; /* CSeq from request */
521+#endif
522+};
523+
524+/* This structure exists only once per master */
525+struct ip_ct_rtsp_master
526+{
527+ /* Empty (?) */
528+};
529+
530+
531+#ifdef __KERNEL__
532+
533+#include <linux/netfilter_ipv4/lockhelp.h>
534+
535+#define RTSP_PORT 554
536+
537+/* Protects rtsp part of conntracks */
538+DECLARE_LOCK_EXTERN(ip_rtsp_lock);
539+
540+#endif /* __KERNEL__ */
541+
542+#endif /* _IP_CONNTRACK_RTSP_H */
543diff -Nur --exclude '*.orig' 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
544--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
545+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-04-29 11:20:17.000000000 +0200
546@@ -0,0 +1,25 @@
547+#ifndef _IP_CONNTRACK_SCTP_H
548+#define _IP_CONNTRACK_SCTP_H
549+/* SCTP tracking. */
550+
551+enum sctp_conntrack {
552+ SCTP_CONNTRACK_NONE,
553+ SCTP_CONNTRACK_CLOSED,
554+ SCTP_CONNTRACK_COOKIE_WAIT,
555+ SCTP_CONNTRACK_COOKIE_ECHOED,
556+ SCTP_CONNTRACK_ESTABLISHED,
557+ SCTP_CONNTRACK_SHUTDOWN_SENT,
558+ SCTP_CONNTRACK_SHUTDOWN_RECD,
559+ SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
560+ SCTP_CONNTRACK_MAX
561+};
562+
563+struct ip_ct_sctp
564+{
565+ enum sctp_conntrack state;
566+
567+ u_int32_t vtag[IP_CT_DIR_MAX];
568+ u_int32_t ttag[IP_CT_DIR_MAX];
569+};
570+
571+#endif /* _IP_CONNTRACK_SCTP_H */
572diff -Nur --exclude '*.orig' 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
573--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
574+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-04-29 11:21:43.000000000 +0200
575@@ -0,0 +1,152 @@
576+#ifndef _IP_CONNTRACK_TALK_H
577+#define _IP_CONNTRACK_TALK_H
578+/* TALK tracking. */
579+
580+#ifdef __KERNEL__
581+#include <linux/in.h>
582+#include <linux/netfilter_ipv4/lockhelp.h>
583+
584+/* Protects talk part of conntracks */
585+DECLARE_LOCK_EXTERN(ip_talk_lock);
586+#endif
587+
588+
589+#define TALK_PORT 517
590+#define NTALK_PORT 518
591+
592+/* talk structures and constants from <protocols/talkd.h> */
593+
594+/*
595+ * 4.3BSD struct sockaddr
596+ */
597+struct talk_addr {
598+ u_int16_t ta_family;
599+ u_int16_t ta_port;
600+ u_int32_t ta_addr;
601+ u_int32_t ta_junk1;
602+ u_int32_t ta_junk2;
603+};
604+
605+#define TALK_OLD_NSIZE 9
606+#define TALK_NSIZE 12
607+#define TALK_TTY_NSIZE 16
608+
609+/*
610+ * Client->server request message formats.
611+ */
612+struct talk_msg {
613+ u_char type; /* request type, see below */
614+ char l_name[TALK_OLD_NSIZE];/* caller's name */
615+ char r_name[TALK_OLD_NSIZE];/* callee's name */
616+ u_char pad;
617+ u_int32_t id_num; /* message id */
618+ int32_t pid; /* caller's process id */
619+ char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
620+ struct talk_addr addr; /* old (4.3) style */
621+ struct talk_addr ctl_addr; /* old (4.3) style */
622+};
623+
624+struct ntalk_msg {
625+ u_char vers; /* protocol version */
626+ u_char type; /* request type, see below */
627+ u_char answer; /* not used */
628+ u_char pad;
629+ u_int32_t id_num; /* message id */
630+ struct talk_addr addr; /* old (4.3) style */
631+ struct talk_addr ctl_addr; /* old (4.3) style */
632+ int32_t pid; /* caller's process id */
633+ char l_name[TALK_NSIZE];/* caller's name */
634+ char r_name[TALK_NSIZE];/* callee's name */
635+ char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
636+};
637+
638+struct ntalk2_msg {
639+ u_char vers; /* talk protocol version */
640+ u_char type; /* request type */
641+ u_char answer; /* */
642+ u_char extended; /* !0 if additional parts */
643+ u_int32_t id_num; /* message id number (dels) */
644+ struct talk_addr addr; /* target address */
645+ struct talk_addr ctl_addr; /* reply to address */
646+ int32_t pid; /* caller's process id */
647+ char l_name[TALK_NSIZE]; /* caller's name */
648+ char r_name[TALK_NSIZE]; /* callee's name */
649+ char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
650+};
651+
652+/*
653+ * Server->client response message formats.
654+ */
655+struct talk_response {
656+ u_char type; /* type of request message, see below */
657+ u_char answer; /* response to request message, see below */
658+ u_char pad[2];
659+ u_int32_t id_num; /* message id */
660+ struct talk_addr addr; /* address for establishing conversation */
661+};
662+
663+struct ntalk_response {
664+ u_char vers; /* protocol version */
665+ u_char type; /* type of request message, see below */
666+ u_char answer; /* response to request message, see below */
667+ u_char pad;
668+ u_int32_t id_num; /* message id */
669+ struct talk_addr addr; /* address for establishing conversation */
670+};
671+
672+struct ntalk2_response {
673+ u_char vers; /* protocol version */
674+ u_char type; /* type of request message */
675+ u_char answer; /* response to request */
676+ u_char rvers; /* Version of answering vers*/
677+ u_int32_t id_num; /* message id number */
678+ struct talk_addr addr; /* address for connection */
679+ /* This is at the end to compatiblize this with NTALK version. */
680+ char r_name[TALK_NSIZE]; /* callee's name */
681+};
682+
683+#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
684+#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
685+#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
686+
687+#define TALK_VERSION 0 /* protocol versions */
688+#define NTALK_VERSION 1
689+#define NTALK2_VERSION 2
690+
691+/* message type values */
692+#define LEAVE_INVITE 0 /* leave invitation with server */
693+#define LOOK_UP 1 /* check for invitation by callee */
694+#define DELETE 2 /* delete invitation by caller */
695+#define ANNOUNCE 3 /* announce invitation by caller */
696+/* NTALK2 */
697+#define REPLY_QUERY 4 /* request reply data from local daemon */
698+
699+/* answer values */
700+#define SUCCESS 0 /* operation completed properly */
701+#define NOT_HERE 1 /* callee not logged in */
702+#define FAILED 2 /* operation failed for unexplained reason */
703+#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
704+#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
705+#define UNKNOWN_REQUEST 5 /* request has invalid type value */
706+#define BADVERSION 6 /* request has invalid protocol version */
707+#define BADADDR 7 /* request has invalid addr value */
708+#define BADCTLADDR 8 /* request has invalid ctl_addr value */
709+/* NTALK2 */
710+#define NO_CALLER 9 /* no-one calling answer from REPLY */
711+#define TRY_HERE 10 /* Not on this machine, try this */
712+#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
713+#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
714+
715+/* We don't really need much for talk */
716+struct ip_ct_talk_expect
717+{
718+ /* Port that was to be used */
719+ u_int16_t port;
720+};
721+
722+/* This structure exists only once per master */
723+struct ip_ct_talk_master
724+{
725+};
726+
727+#endif /* _IP_CONNTRACK_TALK_H */
728diff -Nur --exclude '*.orig' 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
729--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-28 03:36:22.000000000 +0200
730+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-29 11:20:17.000000000 +0200
731@@ -25,6 +25,9 @@
732 struct {
733 u_int16_t id;
734 } icmp;
735+ struct {
736+ u_int16_t port;
737+ } sctp;
738 };
739
740 /* The manipulable part of the tuple. */
741@@ -55,6 +58,9 @@
742 struct {
743 u_int8_t type, code;
744 } icmp;
745+ struct {
746+ u_int16_t port;
747+ } sctp;
748 } u;
749
750 /* The protocol. */
751diff -Nur --exclude '*.orig' 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
752--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h 2004-04-28 03:35:48.000000000 +0200
753+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h 2004-04-29 11:17:15.000000000 +0200
754@@ -134,6 +134,12 @@
755 /* Back pointer */
756 unsigned int comefrom;
757
758+ /* Name of the chain */
759+ char *chainname;
760+
761+ /* Rule number in the chain. */
762+ u_int32_t rulenum;
763+
764 /* Packet and byte counters. */
765 struct ipt_counters counters;
766
767diff -Nur --exclude '*.orig' 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
768--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
769+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-29 11:10:59.000000000 +0200
770@@ -0,0 +1,25 @@
771+#ifndef _IPT_CONNMARK_H_target
772+#define _IPT_CONNMARK_H_target
773+
774+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
775+ * by Henrik Nordstrom <hno@marasystems.com>
776+ *
777+ * This program is free software; you can redistribute it and/or modify
778+ * it under the terms of the GNU General Public License as published by
779+ * the Free Software Foundation; either version 2 of the License, or
780+ * (at your option) any later version.
781+ */
782+
783+enum {
784+ IPT_CONNMARK_SET = 0,
785+ IPT_CONNMARK_SAVE,
786+ IPT_CONNMARK_RESTORE
787+};
788+
789+struct ipt_connmark_target_info {
790+ unsigned long mark;
791+ unsigned long mask;
792+ u_int8_t mode;
793+};
794+
795+#endif /*_IPT_CONNMARK_H_target*/
796diff -Nur --exclude '*.orig' 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
797--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
798+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-04-29 11:17:03.000000000 +0200
799@@ -0,0 +1,13 @@
800+#ifndef _IPT_IPMARK_H_target
801+#define _IPT_IPMARK_H_target
802+
803+struct ipt_ipmark_target_info {
804+ unsigned long andmask;
805+ unsigned long ormask;
806+ unsigned int addr;
807+};
808+
809+#define IPT_IPMARK_SRC 0
810+#define IPT_IPMARK_DST 1
811+
812+#endif /*_IPT_IPMARK_H_target*/
813diff -Nur --exclude '*.orig' 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
814--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
815+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h 2004-04-29 11:17:18.000000000 +0200
816@@ -0,0 +1,9 @@
817+#ifndef _IPT_XOR_H
818+#define _IPT_XOR_H
819+
820+struct ipt_XOR_info {
821+ char key[30];
822+ u_int8_t block_size;
823+};
824+
825+#endif /* _IPT_XOR_H */
826diff -Nur --exclude '*.orig' 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
827--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
828+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-29 11:17:23.000000000 +0200
829@@ -0,0 +1,11 @@
830+#ifndef _IPT_ADDRTYPE_H
831+#define _IPT_ADDRTYPE_H
832+
833+struct ipt_addrtype_info {
834+ u_int16_t source; /* source-type mask */
835+ u_int16_t dest; /* dest-type mask */
836+ int invert_source;
837+ int invert_dest;
838+};
839+
840+#endif
841diff -Nur --exclude '*.orig' 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
842--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
843+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-29 11:10:59.000000000 +0200
844@@ -0,0 +1,18 @@
845+#ifndef _IPT_CONNMARK_H
846+#define _IPT_CONNMARK_H
847+
848+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
849+ * by Henrik Nordstrom <hno@marasystems.com>
850+ *
851+ * This program is free software; you can redistribute it and/or modify
852+ * it under the terms of the GNU General Public License as published by
853+ * the Free Software Foundation; either version 2 of the License, or
854+ * (at your option) any later version.
855+ */
856+
857+struct ipt_connmark_info {
858+ unsigned long mark, mask;
859+ u_int8_t invert;
860+};
861+
862+#endif /*_IPT_CONNMARK_H*/
863diff -Nur --exclude '*.orig' 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
864--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
865+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h 2004-04-29 11:19:41.000000000 +0200
866@@ -0,0 +1,52 @@
867+#ifndef _IPT_POLICY_H
868+#define _IPT_POLICY_H
869+
870+#define POLICY_MAX_ELEM 4
871+
872+enum ipt_policy_flags
873+{
874+ POLICY_MATCH_IN = 0x1,
875+ POLICY_MATCH_OUT = 0x2,
876+ POLICY_MATCH_NONE = 0x4,
877+ POLICY_MATCH_STRICT = 0x8,
878+};
879+
880+enum ipt_policy_modes
881+{
882+ POLICY_MODE_TRANSPORT,
883+ POLICY_MODE_TUNNEL
884+};
885+
886+struct ipt_policy_spec
887+{
888+ u_int8_t saddr:1,
889+ daddr:1,
890+ proto:1,
891+ mode:1,
892+ spi:1,
893+ reqid:1;
894+};
895+
896+struct ipt_policy_elem
897+{
898+ u_int32_t saddr;
899+ u_int32_t smask;
900+ u_int32_t daddr;
901+ u_int32_t dmask;
902+ u_int32_t spi;
903+ u_int32_t reqid;
904+ u_int8_t proto;
905+ u_int8_t mode;
906+
907+ struct ipt_policy_spec match;
908+ struct ipt_policy_spec invert;
909+};
910+
911+struct ipt_policy_info
912+{
913+ struct ipt_policy_elem pol[POLICY_MAX_ELEM];
914+ u_int16_t flags;
915+ u_int16_t len;
916+};
917+
918+#endif /* _IPT_POLICY_H */
919diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_rpc.h
920--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
921+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_rpc.h 2004-04-29 11:20:02.000000000 +0200
922@@ -0,0 +1,35 @@
923+/* RPC extension for IP netfilter matching, Version 2.2
924+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
925+ * - original rpc tracking module
926+ * - "recent" connection handling for kernel 2.3+ netfilter
927+ *
928+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
929+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
930+ *
931+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
932+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
933+ * - extended matching to support filtering on procedures
934+ *
935+ * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
936+ *
937+ * This program is free software; you can redistribute it and/or
938+ * modify it under the terms of the GNU General Public License
939+ * as published by the Free Software Foundation; either version
940+ * 2 of the License, or (at your option) any later version.
941+ **
942+ */
943+
944+#ifndef _IPT_RPC_H
945+#define _IPT_RPC_H
946+
947+struct ipt_rpc_data;
948+
949+struct ipt_rpc_info {
950+ int inverse;
951+ int strict;
952+ const char c_procs[1408];
953+ int i_procs;
954+ struct ipt_rpc_data *data;
955+};
956+
957+#endif /* _IPT_RPC_H */
958diff -Nur --exclude '*.orig' 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
959--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
960+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h 2004-04-29 11:21:38.000000000 +0200
961@@ -0,0 +1,21 @@
962+#ifndef _IPT_STRING_H
963+#define _IPT_STRING_H
964+
965+/* *** PERFORMANCE TWEAK ***
966+ * Packet size and search string threshold,
967+ * above which sublinear searches is used. */
968+#define IPT_STRING_HAYSTACK_THRESH 100
969+#define IPT_STRING_NEEDLE_THRESH 20
970+
971+#define BM_MAX_NLEN 256
972+#define BM_MAX_HLEN 1024
973+
974+typedef char *(*proc_ipt_search) (char *, char *, int, int);
975+
976+struct ipt_string_info {
977+ char string[BM_MAX_NLEN];
978+ u_int16_t invert;
979+ u_int16_t len;
980+};
981+
982+#endif /* _IPT_STRING_H */
983diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc3/include/linux/netfilter_ipv4.h
984--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h 2004-04-28 03:36:31.000000000 +0200
985+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4.h 2004-04-29 11:18:03.000000000 +0200
986@@ -7,6 +7,8 @@
987
988 #include <linux/config.h>
989 #include <linux/netfilter.h>
990+#include <linux/netdevice.h>
991+#include <net/protocol.h>
992
993 /* IP Cache bits. */
994 /* Src IP address. */
995@@ -85,6 +87,58 @@
996 Returns true or false. */
997 extern int skb_ip_make_writable(struct sk_buff **pskb,
998 unsigned int writable_len);
999+
1000+#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1001+#include <net/route.h>
1002+#include <net/xfrm.h>
1003+
1004+static inline int nf_hook_input_cond(struct sk_buff *skb)
1005+{
1006+ return !skb->sp || skb->sp->decap_done;
1007+}
1008+
1009+static inline int
1010+nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1011+{
1012+ return skb->sp && !skb->sp->decap_done
1013+ && (!ipprot || !ipprot->xfrm_prot);
1014+}
1015+
1016+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1017+{
1018+ return skb->sp && !skb->sp->decap_done
1019+ && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1020+}
1021+
1022+extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1023+extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1024+#else /* CONFIG_XFRM */
1025+static inline int nf_hook_input_cond(struct sk_buff *skb)
1026+{
1027+ return 1;
1028+}
1029+
1030+static inline int
1031+nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1032+{
1033+ return 0;
1034+}
1035+
1036+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1037+{
1038+ return 0;
1039+}
1040+
1041+static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1042+{
1043+ return 0;
1044+}
1045+
1046+static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1047+{
1048+ return 0;
1049+}
1050+#endif /* CONFIG_XFRM */
1051 #endif /*__KERNEL__*/
1052
1053 #endif /*__LINUX_IP_NETFILTER_H*/
1054diff -Nur --exclude '*.orig' 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
1055--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-28 03:36:37.000000000 +0200
1056+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-29 11:17:15.000000000 +0200
1057@@ -140,6 +140,12 @@
1058 /* Back pointer */
1059 unsigned int comefrom;
1060
1061+ /* Name of the chain */
1062+ char *chainname;
1063+
1064+ /* Rule number in the chain. */
1065+ u_int32_t rulenum;
1066+
1067 /* Packet and byte counters. */
1068 struct ip6t_counters counters;
1069
1070diff -Nur --exclude '*.orig' 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
1071--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-28 03:36:03.000000000 +0200
1072+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-29 11:19:40.000000000 +0200
1073@@ -6,12 +6,14 @@
1074 #define IP6T_OWNER_GID 0x02
1075 #define IP6T_OWNER_PID 0x04
1076 #define IP6T_OWNER_SID 0x08
1077+#define IP6T_OWNER_COMM 0x10
1078
1079 struct ip6t_owner_info {
1080 uid_t uid;
1081 gid_t gid;
1082 pid_t pid;
1083 pid_t sid;
1084+ char comm[16];
1085 u_int8_t match, invert; /* flags */
1086 };
1087
1088diff -Nur --exclude '*.orig' 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
1089--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1090+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h 2004-04-29 11:19:41.000000000 +0200
1091@@ -0,0 +1,52 @@
1092+#ifndef _IP6T_POLICY_H\r
1093+#define _IP6T_POLICY_H\r
1094+\r
1095+#define POLICY_MAX_ELEM 4\r
1096+\r
1097+enum ip6t_policy_flags\r
1098+{\r
1099+ POLICY_MATCH_IN = 0x1,\r
1100+ POLICY_MATCH_OUT = 0x2,\r
1101+ POLICY_MATCH_NONE = 0x4,\r
1102+ POLICY_MATCH_STRICT = 0x8,\r
1103+};\r
1104+\r
1105+enum ip6t_policy_modes\r
1106+{\r
1107+ POLICY_MODE_TRANSPORT,\r
1108+ POLICY_MODE_TUNNEL\r
1109+};\r
1110+\r
1111+struct ip6t_policy_spec\r
1112+{\r
1113+ u_int8_t saddr:1,\r
1114+ daddr:1,\r
1115+ proto:1,\r
1116+ mode:1,\r
1117+ spi:1,\r
1118+ reqid:1;\r
1119+};\r
1120+\r
1121+struct ip6t_policy_elem\r
1122+{\r
1123+ struct in6_addr saddr;\r
1124+ struct in6_addr smask;\r
1125+ struct in6_addr daddr;\r
1126+ struct in6_addr dmask;\r
1127+ u_int32_t spi;\r
1128+ u_int32_t reqid;\r
1129+ u_int8_t proto;\r
1130+ u_int8_t mode;\r
1131+\r
1132+ struct ip6t_policy_spec match;\r
1133+ struct ip6t_policy_spec invert;\r
1134+};\r
1135+\r
1136+struct ip6t_policy_info\r
1137+{\r
1138+ struct ip6t_policy_elem pol[POLICY_MAX_ELEM];\r
1139+ u_int16_t flags;\r
1140+ u_int16_t len;\r
1141+};\r
1142+\r
1143+#endif /* _IP6T_POLICY_H */\r
1144diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_mime.h linux-2.6.6-rc3/include/linux/netfilter_mime.h
1145--- linux-2.6.6-rc3.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1146+++ linux-2.6.6-rc3/include/linux/netfilter_mime.h 2004-04-29 11:20:13.000000000 +0200
1147@@ -0,0 +1,89 @@
1148+/*
1149+ * MIME functions for netfilter modules. This file provides implementations
1150+ * for basic MIME parsing. MIME headers are used in many protocols, such as
1151+ * HTTP, RTSP, SIP, etc.
1152+ *
1153+ * gcc will warn for defined but unused functions, so we only include the
1154+ * functions requested. The following macros are used:
1155+ * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
1156+ */
1157+#ifndef _NETFILTER_MIME_H
1158+#define _NETFILTER_MIME_H
1159+
1160+/* Only include these functions for kernel code. */
1161+#ifdef __KERNEL__
1162+
1163+#include <linux/ctype.h>
1164+
1165+/*
1166+ * Given a buffer and length, advance to the next line and mark the current
1167+ * line. If the current line is empty, *plinelen will be set to zero. If
1168+ * not, it will be set to the actual line length (including CRLF).
1169+ *
1170+ * 'line' in this context means logical line (includes LWS continuations).
1171+ * Returns 1 on success, 0 on failure.
1172+ */
1173+#ifdef NF_NEED_MIME_NEXTLINE
1174+static int
1175+nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1176+{
1177+ uint off = *poff;
1178+ uint physlen = 0;
1179+ int is_first_line = 1;
1180+
1181+ if (off >= len)
1182+ {
1183+ return 0;
1184+ }
1185+
1186+ do
1187+ {
1188+ while (p[off] != '\n')
1189+ {
1190+ if (len-off <= 1)
1191+ {
1192+ return 0;
1193+ }
1194+
1195+ physlen++;
1196+ off++;
1197+ }
1198+
1199+ /* if we saw a crlf, physlen needs adjusted */
1200+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1201+ {
1202+ physlen--;
1203+ }
1204+
1205+ /* advance past the newline */
1206+ off++;
1207+
1208+ /* check for an empty line */
1209+ if (physlen == 0)
1210+ {
1211+ break;
1212+ }
1213+
1214+ /* check for colon on the first physical line */
1215+ if (is_first_line)
1216+ {
1217+ is_first_line = 0;
1218+ if (memchr(p+(*poff), ':', physlen) == NULL)
1219+ {
1220+ return 0;
1221+ }
1222+ }
1223+ }
1224+ while (p[off] == ' ' || p[off] == '\t');
1225+
1226+ *plineoff = *poff;
1227+ *plinelen = (physlen == 0) ? 0 : (off - *poff);
1228+ *poff = off;
1229+
1230+ return 1;
1231+}
1232+#endif /* NF_NEED_MIME_NEXTLINE */
1233+
1234+#endif /* __KERNEL__ */
1235+
1236+#endif /* _NETFILTER_MIME_H */
1237diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/ip.h linux-2.6.6-rc3/include/net/ip.h
1238--- linux-2.6.6-rc3.org/include/net/ip.h 2004-04-28 03:36:16.000000000 +0200
1239+++ linux-2.6.6-rc3/include/net/ip.h 2004-04-29 11:18:02.000000000 +0200
1240@@ -30,6 +30,8 @@
1241 #include <linux/netdevice.h>
1242 #include <linux/inetdevice.h>
1243 #include <linux/in_route.h>
1244+#include <linux/netfilter.h>
1245+#include <linux/netfilter_ipv4.h>
1246 #include <net/route.h>
1247 #include <net/arp.h>
1248
1249@@ -48,6 +50,7 @@
1250 #define IPSKB_TRANSLATED 2
1251 #define IPSKB_FORWARDED 4
1252 #define IPSKB_XFRM_TUNNEL_SIZE 8
1253+#define IPSKB_XFRM_TRANSFORMED 16
1254 };
1255
1256 struct ipcm_cookie
1257@@ -212,6 +215,12 @@
1258 __ip_select_ident(iph, dst, more);
1259 }
1260
1261+extern inline int ip_dst_output(struct sk_buff *skb)
1262+{
1263+ return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1264+ skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1265+}
1266+
1267 /*
1268 * Map a multicast IP onto multicast MAC for type ethernet.
1269 */
1270diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/protocol.h linux-2.6.6-rc3/include/net/protocol.h
1271--- linux-2.6.6-rc3.org/include/net/protocol.h 2004-04-28 03:35:44.000000000 +0200
1272+++ linux-2.6.6-rc3/include/net/protocol.h 2004-04-29 11:18:03.000000000 +0200
1273@@ -39,6 +39,7 @@
1274 int (*handler)(struct sk_buff *skb);
1275 void (*err_handler)(struct sk_buff *skb, u32 info);
1276 int no_policy;
1277+ int xfrm_prot;
1278 };
1279
1280 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
1281diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/tcp.h linux-2.6.6-rc3/include/net/tcp.h
1282--- linux-2.6.6-rc3.org/include/net/tcp.h 2004-04-29 11:24:38.000000000 +0200
1283+++ linux-2.6.6-rc3/include/net/tcp.h 2004-04-29 11:19:32.000000000 +0200
1284@@ -162,6 +162,7 @@
1285 extern void tcp_bucket_unlock(struct sock *sk);
1286 extern int tcp_port_rover;
1287 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
1288+extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
1289
1290 /* These are AF independent. */
1291 static __inline__ int tcp_bhashfn(__u16 lport)
1292diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/udp.h linux-2.6.6-rc3/include/net/udp.h
1293--- linux-2.6.6-rc3.org/include/net/udp.h 2004-04-28 03:36:29.000000000 +0200
1294+++ linux-2.6.6-rc3/include/net/udp.h 2004-04-29 11:19:32.000000000 +0200
1295@@ -74,6 +74,8 @@
1296 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
1297 extern int udp_disconnect(struct sock *sk, int flags);
1298
1299+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
1300+
1301 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
1302 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
1303 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
1304diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/xfrm.h linux-2.6.6-rc3/include/net/xfrm.h
1305--- linux-2.6.6-rc3.org/include/net/xfrm.h 2004-04-28 03:36:31.000000000 +0200
1306+++ linux-2.6.6-rc3/include/net/xfrm.h 2004-04-29 11:18:03.000000000 +0200
1307@@ -540,6 +540,9 @@
1308 {
1309 atomic_t refcnt;
1310 int len;
1311+#ifdef CONFIG_NETFILTER
1312+ int decap_done;
1313+#endif
1314 struct sec_decap_state x[XFRM_MAX_DEPTH];
1315 };
1316
1317diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/core/netfilter.c linux-2.6.6-rc3/net/core/netfilter.c
1318--- linux-2.6.6-rc3.org/net/core/netfilter.c 2004-04-28 03:35:46.000000000 +0200
1319+++ linux-2.6.6-rc3/net/core/netfilter.c 2004-04-29 11:18:06.000000000 +0200
1320@@ -27,6 +27,8 @@
1321 #include <linux/icmp.h>
1322 #include <net/sock.h>
1323 #include <net/route.h>
1324+#include <net/xfrm.h>
1325+#include <net/ip.h>
1326 #include <linux/ip.h>
1327
1328 /* In this code, we can be waiting indefinitely for userspace to
1329@@ -638,7 +640,6 @@
1330 #ifdef CONFIG_IP_ROUTE_FWMARK
1331 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
1332 #endif
1333- fl.proto = iph->protocol;
1334 if (ip_route_output_key(&rt, &fl) != 0)
1335 return -1;
1336
1337@@ -665,6 +666,20 @@
1338 if ((*pskb)->dst->error)
1339 return -1;
1340
1341+#ifdef CONFIG_XFRM
1342+ if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
1343+ struct xfrm_policy_afinfo *afinfo;
1344+
1345+ afinfo = xfrm_policy_get_afinfo(AF_INET);
1346+ if (afinfo != NULL) {
1347+ afinfo->decode_session(*pskb, &fl);
1348+ xfrm_policy_put_afinfo(afinfo);
1349+ if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
1350+ return -1;
1351+ }
1352+ }
1353+#endif
1354+
1355 /* Change in oif may mean change in hh_len. */
1356 hh_len = (*pskb)->dst->dev->hard_header_len;
1357 if (skb_headroom(*pskb) < hh_len) {
1358@@ -682,6 +697,71 @@
1359 return 0;
1360 }
1361
1362+#ifdef CONFIG_XFRM
1363+inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1364+{
1365+ skb->sp->decap_done = 1;
1366+ dst_release(skb->dst);
1367+ skb->dst = NULL;
1368+ nf_reset(skb);
1369+ return netif_rx(skb);
1370+}
1371+
1372+int nf_rcv_postxfrm_local(struct sk_buff *skb)
1373+{
1374+ __skb_push(skb, skb->data - skb->nh.raw);
1375+ /* Fix header len and checksum if last xfrm was transport mode */
1376+ if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
1377+ skb->nh.iph->tot_len = htons(skb->len);
1378+ ip_send_check(skb->nh.iph);
1379+ }
1380+ return nf_rcv_postxfrm_nonlocal(skb);
1381+}
1382+
1383+#ifdef CONFIG_IP_NF_NAT_NEEDED
1384+#include <linux/netfilter_ipv4/ip_conntrack.h>
1385+#include <linux/netfilter_ipv4/ip_nat.h>
1386+
1387+void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
1388+{
1389+ struct ip_conntrack *ct;
1390+ struct ip_conntrack_tuple *t;
1391+ struct ip_nat_info_manip *m;
1392+ unsigned int i;
1393+
1394+ if (skb->nfct == NULL)
1395+ return;
1396+ ct = (struct ip_conntrack *)skb->nfct->master;
1397+
1398+ for (i = 0; i < ct->nat.info.num_manips; i++) {
1399+ m = &ct->nat.info.manips[i];
1400+ t = &ct->tuplehash[m->direction].tuple;
1401+
1402+ switch (m->hooknum) {
1403+ case NF_IP_PRE_ROUTING:
1404+ if (m->maniptype != IP_NAT_MANIP_DST)
1405+ break;
1406+ fl->fl4_dst = t->dst.ip;
1407+ if (t->dst.protonum == IPPROTO_TCP ||
1408+ t->dst.protonum == IPPROTO_UDP)
1409+ fl->fl_ip_dport = t->dst.u.tcp.port;
1410+ break;
1411+#ifdef CONFIG_IP_NF_NAT_LOCAL
1412+ case NF_IP_LOCAL_IN:
1413+ if (m->maniptype != IP_NAT_MANIP_SRC)
1414+ break;
1415+ fl->fl4_src = t->src.ip;
1416+ if (t->dst.protonum == IPPROTO_TCP ||
1417+ t->dst.protonum == IPPROTO_UDP)
1418+ fl->fl_ip_sport = t->src.u.tcp.port;
1419+ break;
1420+#endif
1421+ }
1422+ }
1423+}
1424+#endif /* CONFIG_IP_NF_NAT_NEEDED */
1425+#endif
1426+
1427 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
1428 {
1429 struct sk_buff *nskb;
1430@@ -839,3 +919,4 @@
1431 EXPORT_SYMBOL(nf_unregister_hook);
1432 EXPORT_SYMBOL(nf_unregister_queue_handler);
1433 EXPORT_SYMBOL(nf_unregister_sockopt);
1434+EXPORT_SYMBOL(nf_rcv_postxfrm_local);
1435diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ah4.c linux-2.6.6-rc3/net/ipv4/ah4.c
1436--- linux-2.6.6-rc3.org/net/ipv4/ah4.c 2004-04-28 03:36:34.000000000 +0200
1437+++ linux-2.6.6-rc3/net/ipv4/ah4.c 2004-04-29 11:18:03.000000000 +0200
1438@@ -145,6 +145,7 @@
1439 err = -EHOSTUNREACH;
1440 goto error_nolock;
1441 }
1442+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1443 return NET_XMIT_BYPASS;
1444
1445 error:
1446@@ -343,6 +344,7 @@
1447 .handler = xfrm4_rcv,
1448 .err_handler = ah4_err,
1449 .no_policy = 1,
1450+ .xfrm_prot = 1,
1451 };
1452
1453 static int __init ah4_init(void)
1454diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/esp4.c linux-2.6.6-rc3/net/ipv4/esp4.c
1455--- linux-2.6.6-rc3.org/net/ipv4/esp4.c 2004-04-28 03:36:01.000000000 +0200
1456+++ linux-2.6.6-rc3/net/ipv4/esp4.c 2004-04-29 11:18:03.000000000 +0200
1457@@ -216,6 +216,7 @@
1458 err = -EHOSTUNREACH;
1459 goto error_nolock;
1460 }
1461+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1462 return NET_XMIT_BYPASS;
1463
1464 error:
1465@@ -598,6 +599,7 @@
1466 .handler = xfrm4_rcv,
1467 .err_handler = esp4_err,
1468 .no_policy = 1,
1469+ .xfrm_prot = 1,
1470 };
1471
1472 static int __init esp4_init(void)
1473diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/igmp.c linux-2.6.6-rc3/net/ipv4/igmp.c
1474--- linux-2.6.6-rc3.org/net/ipv4/igmp.c 2004-04-28 03:36:55.000000000 +0200
1475+++ linux-2.6.6-rc3/net/ipv4/igmp.c 2004-04-29 11:18:02.000000000 +0200
1476@@ -342,7 +342,7 @@
1477 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
1478
1479 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
1480- dst_output);
1481+ ip_dst_output);
1482 }
1483
1484 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
1485@@ -672,7 +672,7 @@
1486 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
1487
1488 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1489- dst_output);
1490+ ip_dst_output);
1491 }
1492
1493 static void igmp_gq_timer_expire(unsigned long data)
1494diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_forward.c linux-2.6.6-rc3/net/ipv4/ip_forward.c
1495--- linux-2.6.6-rc3.org/net/ipv4/ip_forward.c 2004-04-28 03:34:59.000000000 +0200
1496+++ linux-2.6.6-rc3/net/ipv4/ip_forward.c 2004-04-29 11:18:03.000000000 +0200
1497@@ -51,7 +51,7 @@
1498 if (unlikely(opt->optlen))
1499 ip_forward_options(skb);
1500
1501- return dst_output(skb);
1502+ return ip_dst_output(skb);
1503 }
1504
1505 int ip_forward(struct sk_buff *skb)
1506diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
1507--- linux-2.6.6-rc3.org/net/ipv4/ip_input.c 2004-04-29 11:24:39.000000000 +0200
1508+++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-29 11:18:06.000000000 +0200
1509@@ -206,10 +206,6 @@
1510
1511 __skb_pull(skb, ihl);
1512
1513- /* Free reference early: we don't need it any more, and it may
1514- hold ip_conntrack module loaded indefinitely. */
1515- nf_reset(skb);
1516-
1517 /* Point into the IP datagram, just past the header. */
1518 skb->h.raw = skb->data;
1519
1520@@ -224,6 +220,13 @@
1521 resubmit:
1522 hash = protocol & (MAX_INET_PROTOS - 1);
1523 raw_sk = sk_head(&raw_v4_htable[hash]);
1524+ ipprot = inet_protos[hash];
1525+ smp_read_barrier_depends();
1526+
1527+ if (nf_xfrm_local_done(skb, ipprot)) {
1528+ nf_rcv_postxfrm_local(skb);
1529+ goto out;
1530+ }
1531
1532 /* If there maybe a raw socket we must check - if not we
1533 * don't care less
1534@@ -231,14 +234,15 @@
1535 if (raw_sk)
1536 raw_v4_input(skb, skb->nh.iph, hash);
1537
1538- if ((ipprot = inet_protos[hash]) != NULL) {
1539+ if (ipprot != NULL) {
1540 int ret;
1541
1542- smp_read_barrier_depends();
1543- if (!ipprot->no_policy &&
1544- !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1545- kfree_skb(skb);
1546- goto out;
1547+ if (!ipprot->no_policy) {
1548+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1549+ kfree_skb(skb);
1550+ goto out;
1551+ }
1552+ nf_reset(skb);
1553 }
1554 ret = ipprot->handler(skb);
1555 if (ret < 0) {
1556@@ -279,8 +283,8 @@
1557 return 0;
1558 }
1559
1560- return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1561- ip_local_deliver_finish);
1562+ return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1563+ ip_local_deliver_finish, nf_hook_input_cond(skb));
1564 }
1565
1566 static inline int ip_rcv_finish(struct sk_buff *skb)
1567@@ -297,6 +301,9 @@
1568 goto drop;
1569 }
1570
1571+ if (nf_xfrm_nonlocal_done(skb))
1572+ return nf_rcv_postxfrm_nonlocal(skb);
1573+
1574 #ifdef CONFIG_NET_CLS_ROUTE
1575 if (skb->dst->tclassid) {
1576 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
1577@@ -418,8 +425,8 @@
1578 }
1579 }
1580
1581- return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1582- ip_rcv_finish);
1583+ return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1584+ ip_rcv_finish, nf_hook_input_cond(skb));
1585
1586 inhdr_error:
1587 IP_INC_STATS_BH(IpInHdrErrors);
1588diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_output.c linux-2.6.6-rc3/net/ipv4/ip_output.c
1589--- linux-2.6.6-rc3.org/net/ipv4/ip_output.c 2004-04-28 03:36:55.000000000 +0200
1590+++ linux-2.6.6-rc3/net/ipv4/ip_output.c 2004-04-29 11:18:03.000000000 +0200
1591@@ -123,6 +123,15 @@
1592 return ttl;
1593 }
1594
1595+#ifdef CONFIG_NETFILTER
1596+/* out-of-line copy is only required with netfilter */
1597+int ip_dst_output(struct sk_buff *skb)
1598+{
1599+ return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1600+ skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1601+}
1602+#endif
1603+
1604 /*
1605 * Add an ip header to a skbuff and send it out.
1606 *
1607@@ -165,7 +174,7 @@
1608
1609 /* Send it out. */
1610 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1611- dst_output);
1612+ ip_dst_output);
1613 }
1614
1615 static inline int ip_finish_output2(struct sk_buff *skb)
1616@@ -283,7 +292,7 @@
1617 return ip_finish_output(skb);
1618 }
1619
1620-int ip_output(struct sk_buff *skb)
1621+static inline int ip_output2(struct sk_buff *skb)
1622 {
1623 IP_INC_STATS(IpOutRequests);
1624
1625@@ -294,6 +303,16 @@
1626 return ip_finish_output(skb);
1627 }
1628
1629+int ip_output(struct sk_buff *skb)
1630+{
1631+ int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
1632+
1633+ if (transformed)
1634+ nf_reset(skb);
1635+ return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1636+ skb->dst->dev, ip_output2, transformed);
1637+}
1638+
1639 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
1640 {
1641 struct sock *sk = skb->sk;
1642@@ -387,7 +406,7 @@
1643 skb->priority = sk->sk_priority;
1644
1645 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1646- dst_output);
1647+ ip_dst_output);
1648
1649 no_route:
1650 IP_INC_STATS(IpOutNoRoutes);
1651@@ -1177,7 +1196,7 @@
1652
1653 /* Netfilter gets whole the not fragmented skb. */
1654 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1655- skb->dst->dev, dst_output);
1656+ skb->dst->dev, ip_dst_output);
1657 if (err) {
1658 if (err > 0)
1659 err = inet->recverr ? net_xmit_errno(err) : 0;
1660diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipcomp.c linux-2.6.6-rc3/net/ipv4/ipcomp.c
1661--- linux-2.6.6-rc3.org/net/ipv4/ipcomp.c 2004-04-28 03:36:33.000000000 +0200
1662+++ linux-2.6.6-rc3/net/ipv4/ipcomp.c 2004-04-29 11:18:03.000000000 +0200
1663@@ -231,6 +231,7 @@
1664 err = -EHOSTUNREACH;
1665 goto error_nolock;
1666 }
1667+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1668 err = NET_XMIT_BYPASS;
1669
1670 out_exit:
1671@@ -407,6 +408,7 @@
1672 .handler = xfrm4_rcv,
1673 .err_handler = ipcomp4_err,
1674 .no_policy = 1,
1675+ .xfrm_prot = 1,
1676 };
1677
1678 static int __init ipcomp4_init(void)
1679diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
1680--- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-29 11:24:39.000000000 +0200
1681+++ linux-2.6.6-rc3/net/ipv4/ipip.c 2004-04-29 11:18:03.000000000 +0200
1682@@ -478,6 +478,11 @@
1683
1684 read_lock(&ipip_lock);
1685 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
1686+ /* IPIP packets decapsulated by IPsec missed netfilter hooks */
1687+ if (nf_xfrm_local_done(skb, NULL)) {
1688+ nf_rcv_postxfrm_local(skb);
1689+ return 0;
1690+ }
1691 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1692 kfree_skb(skb);
1693 return 0;
1694diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipmr.c linux-2.6.6-rc3/net/ipv4/ipmr.c
1695--- linux-2.6.6-rc3.org/net/ipv4/ipmr.c 2004-04-28 03:35:47.000000000 +0200
1696+++ linux-2.6.6-rc3/net/ipv4/ipmr.c 2004-04-29 11:18:03.000000000 +0200
1697@@ -1120,7 +1120,7 @@
1698 if (unlikely(opt->optlen))
1699 ip_forward_options(skb);
1700
1701- return dst_output(skb);
1702+ return ip_dst_output(skb);
1703 }
1704
1705 /*
1706diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
1707--- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig 2004-04-29 11:24:40.000000000 +0200
1708+++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig 2004-04-29 11:21:43.000000000 +0200
1709@@ -206,6 +206,11 @@
1710
1711 To compile it as a module, choose M here. If unsure, say N.
1712
1713+config IP_NF_MATCH_UNCLEAN
1714+ tristate 'unclean match support (EXPERIMENTAL)'
1715+ depends on EXPERIMENTAL && IP_NF_IPTABLES
1716+ help
1717+
1718 config IP_NF_MATCH_TTL
1719 tristate "TTL match support"
1720 depends on IP_NF_IPTABLES
d8b5a97c 1721@@ -706,5 +711,138 @@
384c1045 1722 depends on IP_NF_IPTABLES
1723 help
1724
1725+config IP_NF_CONNTRACK_MARK
1726+ bool 'Connection mark tracking support'
1727+config IP_NF_TARGET_CONNMARK
1728+ tristate 'CONNMARK target support'
1729+ depends on IP_NF_MANGLE
1730+config IP_NF_MATCH_CONNMARK
1731+ tristate ' Connection mark match support'
1732+ depends on IP_NF_IPTABLES
1733+ help
1734+
1735+config IP_NF_TARGET_IPMARK
1736+ tristate 'IPMARK target support'
1737+ depends on IP_NF_MANGLE
1738+ help
1739+
1740+config IP_NF_TARGET_TARPIT
1741+ tristate 'TARPIT target support'
1742+ depends on IP_NF_FILTER
1743+ help
1744+
1745+config IP_NF_TARGET_TRACE
1746+ tristate 'TRACE target support'
1747+ depends on IP_NF_RAW
1748+ help
1749+ The TRACE target allows packets to be traced as those
1750+ matches any subsequent rule in any table/rule. The matched
1751+ rule and the packet is logged with the prefix
1752+
1753+ TRACE: tablename/chainname/rulenum
1754+
1755+ If you want to compile it as a module, say M here and read
1756+ <file:Documentation/modules.txt>. If unsure, say `N'.
1757+ help
1758+
1759+config IP_NF_TARGET_XOR
1760+ tristate 'XOR target support'
1761+ depends on IP_NF_MANGLE
1762+ help
1763+
1764+config IP_NF_MATCH_ADDRTYPE
1765+ tristate 'address type match support'
1766+ depends on IP_NF_IPTABLES
1767+ help
1768+
384c1045 1769+config IP_NF_EGG
1770+ tristate 'Eggdrop bot support'
1771+ depends on IP_NF_CONNTRACK
1772+ help
1773+
1774+config IP_NF_NAT_H323
1775+ tristate
1776+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1777+ default IP_NF_NAT if IP_NF_H323=y
1778+ default m if IP_NF_H323=m
1779+
1780+config IP_NF_H323
1781+ tristate 'H.323 (netmeeting) support'
1782+ depends on IP_NF_CONNTRACK
1783+ help
1784+
1785+config IP_NF_NAT_MMS
1786+ tristate
1787+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1788+ default IP_NF_NAT if IP_NF_MMS=y
1789+ default m if IP_NF_MMS=m
1790+
1791+config IP_NF_MMS
1792+ tristate 'MMS protocol support'
1793+ depends on IP_NF_CONNTRACK
1794+ help
1795+
1796+config IP_NF_MATCH_POLICY
1797+ tristate "IPsec policy match support"
1798+ depends on IP_NF_IPTABLES && XFRM
1799+ help
1800+ Policy matching allows you to match packets based on the
1801+ IPsec policy that was used during decapsulation/will
1802+ be used during encapsulation.
1803+
1804+ To compile it as a module, choose M here. If unsure, say N.
1805+ help
1806+
1807+config IP_NF_NAT_QUAKE3
1808+ tristate
1809+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1810+ default IP_NF_NAT if IP_NF_QUAKE3=y
1811+ default m if IP_NF_QUAKE3=m
1812+
1813+config IP_NF_QUAKE3
1814+ tristate "Quake3 protocol support"
1815+ depends on IP_NF_CONNTRACK
1816+ help
1817+
1818+config IP_NF_MATCH_RPC
1819+ tristate 'RPC match support'
1820+ depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1821+ help
1822+
1823+config IP_NF_RSH
1824+ tristate 'RSH protocol support'
1825+ depends on IP_NF_CONNTRACK
1826+ help
1827+
1828+config IP_NF_NAT_RTSP
1829+ tristate
1830+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1831+ default IP_NF_NAT if IP_NF_RTSP=y
1832+ default m if IP_NF_RTSP=m
1833+config IP_NF_RTSP
1834+ tristate ' RTSP protocol support'
1835+ depends on IP_NF_CONNTRACK
1836+ help
1837+
1838+config IP_NF_CT_PROTO_SCTP
1839+ tristate 'SCTP protocol connection tracking support'
1840+ depends on IP_NF_CONNTRACK
1841+ help
1842+
1843+config IP_NF_MATCH_STRING
1844+ tristate 'String match support'
1845+ depends on IP_NF_IPTABLES
1846+ help
1847+
1848+config IP_NF_NAT_TALK
1849+ tristate
1850+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1851+ default IP_NF_NAT if IP_NF_TALK=y
1852+ default m if IP_NF_TALK=m
1853+config IP_NF_TALK
1854+ tristate 'talk protocol support'
1855+ depends on IP_NF_CONNTRACK
1856+ help
1857+
1858 endmenu
1859
1860diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
1861--- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile 2004-04-29 11:24:40.000000000 +0200
1862+++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-29 11:21:43.000000000 +0200
d8b5a97c 1863@@ -19,17 +19,43 @@
384c1045 1864 # connection tracking
1865 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1866
1867+# talk protocol support
1868+obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1869+obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1870+
1871+
1872+# SCTP protocol connection tracking
1873+obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
1874+
1875+# H.323 support
1876+obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1877+obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1878+
1879+
1880 # connection tracking helpers
1881+
1882+# rtsp protocol support
1883+obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
1884+obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
1885+
1886+obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1887+obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1888 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1889 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1890 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1891+obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1892+
1893+obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
1894+
1895 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1896
1897 # NAT helpers
384c1045 1898 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
1899 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1900 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1901 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1902+obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1903+obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1904
1905 # generic IP tables
1906 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1907@@ -41,6 +83,8 @@
1908 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1909
1910 # matches
1911+obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1912+
1913 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1914 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1915 obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1916@@ -87,14 +132,19 @@
1917 obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1918
1919
1920+obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
1921+obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
1922 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1923 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1924+obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
1925 obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1926 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1927 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1928+obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
1929 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1930
1931 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1932+obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
1933
1934 # targets
1935 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
1936@@ -102,6 +152,8 @@
1937 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
1938 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
1939 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
1940+obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
1941+obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
1942 obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
1943 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
1944 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
1945@@ -110,11 +162,14 @@
1946 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1947 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1948 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1949+obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
1950+obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
1951 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1952 obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1953 obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1954 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1955 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1956+obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
1957 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
1958
1959 # generic ARP tables
1960diff -Nur --exclude '*.orig' 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
1961--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-29 11:24:39.000000000 +0200
1962+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-29 11:11:00.000000000 +0200
1963@@ -718,6 +718,9 @@
1964 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1965 conntrack->master = expected;
1966 expected->sibling = conntrack;
1967+#if CONFIG_IP_NF_CONNTRACK_MARK
1968+ conntrack->mark = expected->expectant->mark;
1969+#endif
1970 LIST_DELETE(&ip_conntrack_expect_list, expected);
1971 expected->expectant->expecting--;
1972 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1973diff -Nur --exclude '*.orig' 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
1974--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
1975+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c 2004-04-29 11:17:59.000000000 +0200
1976@@ -0,0 +1,237 @@
1977+/* Eggdrop extension for IP connection tracking, Version 0.0.5
1978+ * based on ip_conntrack_irc.c
1979+ *
1980+ * This module only supports the share userfile-send command,
1981+ * used by eggdrops to share it's userfile.
1982+ *
1983+ * There are no support for NAT at the moment.
1984+ *
1985+ * This program is free software; you can redistribute it and/or
1986+ * modify it under the terms of the GNU General Public License
1987+ * as published by the Free Software Foundation; either version
1988+ * 2 of the License, or (at your option) any later version.
1989+ *
1990+ * Module load syntax:
1991+ *
1992+ * please give the ports of all Eggdrops You have running
1993+ * on your system, the default port is 3333.
1994+ *
1995+ * 2001-04-19: Security update. IP addresses are now compared
1996+ * to prevent unauthorized "related" access.
1997+ *
1998+ * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
1999+ * Port to netfilter 'newnat' API.
2000+ */
2001+
2002+#include <linux/module.h>
2003+#include <linux/netfilter.h>
2004+#include <linux/ip.h>
2005+#include <net/checksum.h>
2006+#include <net/tcp.h>
2007+
2008+#include <linux/netfilter_ipv4/lockhelp.h>
2009+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2010+
2011+#define MAX_PORTS 8
2012+static int ports[MAX_PORTS];
2013+static int ports_c = 0;
2014+static unsigned int egg_timeout = 300;
2015+
2016+MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
2017+MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
2018+MODULE_LICENSE("GPL");
2019+#ifdef MODULE_PARM
2020+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2021+MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
2022+#endif
2023+
2024+DECLARE_LOCK(ip_egg_lock);
2025+struct module *ip_conntrack_egg = THIS_MODULE;
2026+
2027+#if 0
2028+#define DEBUGP printk
2029+#else
2030+#define DEBUGP(format, args...)
2031+#endif
2032+
2033+int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
2034+/* tries to get the ip_addr and port out of a eggdrop command
2035+ return value: -1 on failure, 0 on success
2036+ data pointer to first byte of DCC command data
2037+ data_end pointer to last byte of dcc command data
2038+ ip returns parsed ip of dcc command
2039+ port returns parsed port of dcc command */
2040+{
2041+ if (data > data_end)
2042+ return -1;
2043+
2044+ *ip = simple_strtoul(data, &data, 10);
2045+
2046+ /* skip blanks between ip and port */
2047+ while (*data == ' ' && data < data_end)
2048+ data++;
2049+
2050+ *port = simple_strtoul(data, &data, 10);
2051+ return 0;
2052+}
2053+
2054+
2055+static int help(const struct iphdr *iph, size_t len,
2056+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
2057+{
2058+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
2059+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
2060+ char *data = (char *) tcph + tcph->doff * 4;
2061+ char *data_limit;
2062+ u_int32_t tcplen = len - iph->ihl * 4;
2063+ u_int32_t datalen = tcplen - tcph->doff * 4;
2064+ int dir = CTINFO2DIR(ctinfo);
2065+ int bytes_scanned = 0;
2066+ struct ip_conntrack_expect exp;
2067+
2068+ u_int32_t egg_ip;
2069+ u_int16_t egg_port;
2070+
2071+ DEBUGP("entered\n");
2072+
2073+ /* If packet is coming from IRC server */
2074+ if (dir != IP_CT_DIR_REPLY)
2075+ return NF_ACCEPT;
2076+
2077+ /* Until there's been traffic both ways, don't look in packets. */
2078+ if (ctinfo != IP_CT_ESTABLISHED
2079+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2080+ DEBUGP("Conntrackinfo = %u\n", ctinfo);
2081+ return NF_ACCEPT;
2082+ }
2083+
2084+ /* Not whole TCP header? */
2085+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
2086+ DEBUGP("tcplen = %u\n", (unsigned) tcplen);
2087+ return NF_ACCEPT;
2088+ }
2089+
2090+ /* Checksum invalid? Ignore. */
2091+ /* FIXME: Source route IP option packets --RR */
2092+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2093+ csum_partial((char *) tcph, tcplen, 0))) {
2094+ DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
2095+ tcph, tcplen, NIPQUAD(iph->saddr),
2096+ NIPQUAD(iph->daddr));
2097+ return NF_ACCEPT;
2098+ }
2099+
2100+ data_limit = (char *) data + datalen;
2101+ while (datalen > 5 && bytes_scanned < 128) {
2102+ if (memcmp(data, "s us ", 5)) {
2103+ data++;
2104+ datalen--;
2105+ bytes_scanned++;
2106+ continue;
2107+ }
2108+
2109+ data += 5;
2110+
2111+ DEBUGP("Userfile-share found in connection "
2112+ "%u.%u.%u.%u -> %u.%u.%u.%u\n",
2113+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
2114+
2115+ if (parse_command((char *) data, data_limit, &egg_ip,
2116+ &egg_port)) {
2117+ DEBUGP("no data in userfile-share pkt\n");
2118+ return NF_ACCEPT;
2119+ }
2120+
2121+ memset(&exp, 0, sizeof(exp));
2122+
2123+ if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
2124+ if (net_ratelimit())
2125+ printk("Forged Eggdrop command from "
2126+ "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
2127+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
2128+ HIPQUAD(egg_ip), egg_port);
2129+ return NF_ACCEPT;
2130+ }
2131+
2132+ exp.tuple.src.ip = iph->daddr;
2133+ exp.tuple.src.u.tcp.port = 0;
2134+ exp.tuple.dst.ip = htonl(egg_ip);
2135+ exp.tuple.dst.u.tcp.port = htons(egg_port);
2136+ exp.tuple.dst.protonum = IPPROTO_TCP;
2137+
2138+ exp.mask.dst.u.tcp.port = 0xffff;
2139+ exp.mask.dst.protonum = 0xffff;
2140+
2141+ DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
2142+ NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
2143+ NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
2144+
2145+ ip_conntrack_expect_related(ct, &exp);
2146+ break;
2147+ }
2148+ return NF_ACCEPT;
2149+}
2150+
2151+static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
2152+static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
2153+
2154+static void deregister_helpers(void) {
2155+ int i;
2156+
2157+ for (i = 0; i < ports_c; i++) {
2158+ DEBUGP("unregistering helper for port %d\n", ports[i]);
2159+ ip_conntrack_helper_unregister(&egg_helpers[i]);
2160+ }
2161+}
2162+
2163+static int __init init(void)
2164+{
2165+ int i, ret;
2166+ char *tmpname;
2167+
2168+ /* If no port given, default to standard eggdrop port */
2169+ if (ports[0] == 0)
2170+ ports[0] = 3333;
2171+
2172+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2173+ memset(&egg_helpers[i], 0,
2174+ sizeof(struct ip_conntrack_helper));
2175+ egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
2176+ egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
2177+ egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
2178+ egg_helpers[i].mask.dst.protonum = 0xFFFF;
2179+ egg_helpers[i].max_expected = 1;
2180+ egg_helpers[i].timeout = egg_timeout;
2181+ egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2182+ egg_helpers[i].me = THIS_MODULE;
2183+ egg_helpers[i].help = help;
2184+
2185+ tmpname = &egg_names[i][0];
2186+ if (ports[i] == 3333)
2187+ sprintf(tmpname, "eggdrop");
2188+ else
2189+ sprintf(tmpname, "eggdrop-%d", ports[i]);
2190+ egg_helpers[i].name = tmpname;
2191+
2192+ DEBUGP("port #%d: %d\n", i, ports[i]);
2193+
2194+ ret = ip_conntrack_helper_register(&egg_helpers[i]);
2195+
2196+ if (ret) {
2197+ printk("ip_conntrack_egg: ERROR registering helper "
2198+ "for port %d\n", ports[i]);
2199+ deregister_helpers();
2200+ return 1;
2201+ }
2202+ ports_c++;
2203+ }
2204+ return 0;
2205+}
2206+
2207+static void __exit fini(void)
2208+{
2209+ deregister_helpers();
2210+}
2211+
2212+module_init(init);
2213+module_exit(fini);
2214diff -Nur --exclude '*.orig' 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
2215--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
2216+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c 2004-04-29 11:18:00.000000000 +0200
2217@@ -0,0 +1,308 @@
2218+/*
2219+ * H.323 'brute force' extension for H.323 connection tracking.
2220+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2221+ *
2222+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
2223+ * (http://www.coritel.it/projects/sofia/nat/)
2224+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
2225+ * the unregistered helpers to the conntrack entries.
2226+ */
2227+
2228+
2229+#include <linux/module.h>
2230+#include <linux/netfilter.h>
2231+#include <linux/ip.h>
2232+#include <net/checksum.h>
2233+#include <net/tcp.h>
2234+
2235+#include <linux/netfilter_ipv4/lockhelp.h>
2236+#include <linux/netfilter_ipv4/ip_conntrack.h>
2237+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2238+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2239+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
2240+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
2241+
2242+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
2243+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
2244+MODULE_LICENSE("GPL");
2245+
2246+DECLARE_LOCK(ip_h323_lock);
2247+struct module *ip_conntrack_h323 = THIS_MODULE;
2248+
2249+#if 0
2250+#define DEBUGP printk
2251+#else
2252+#define DEBUGP(format, args...)
2253+#endif
2254+
2255+/* FIXME: This should be in userspace. Later. */
2256+static int h245_help(const struct iphdr *iph, size_t len,
2257+ struct ip_conntrack *ct,
2258+ enum ip_conntrack_info ctinfo)
2259+{
2260+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2261+ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2262+ unsigned char *data_limit;
2263+ u_int32_t tcplen = len - iph->ihl * 4;
2264+ u_int32_t datalen = tcplen - tcph->doff * 4;
2265+ int dir = CTINFO2DIR(ctinfo);
2266+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2267+ struct ip_conntrack_expect expect, *exp = &expect;
2268+ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2269+ u_int16_t data_port;
2270+ u_int32_t data_ip;
2271+ unsigned int i;
2272+
2273+ DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2274+ NIPQUAD(iph->saddr), ntohs(tcph->source),
2275+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
2276+
2277+ /* Can't track connections formed before we registered */
2278+ if (!info)
2279+ return NF_ACCEPT;
2280+
2281+ /* Until there's been traffic both ways, don't look in packets. */
2282+ if (ctinfo != IP_CT_ESTABLISHED
2283+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2284+ DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
2285+ return NF_ACCEPT;
2286+ }
2287+
2288+ /* Not whole TCP header or too short packet? */
2289+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2290+ DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
2291+ return NF_ACCEPT;
2292+ }
2293+
2294+ /* Checksum invalid? Ignore. */
2295+ /* FIXME: Source route IP option packets --RR */
2296+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2297+ csum_partial((char *)tcph, tcplen, 0))) {
2298+ DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2299+ tcph, tcplen, NIPQUAD(iph->saddr),
2300+ NIPQUAD(iph->daddr));
2301+ return NF_ACCEPT;
2302+ }
2303+
2304+ data_limit = (unsigned char *) data + datalen;
2305+ /* bytes: 0123 45
2306+ ipadrr port */
2307+ for (i = 0; data < (data_limit - 5); data++, i++) {
2308+ data_ip = *((u_int32_t *)data);
2309+ if (data_ip == iph->saddr) {
2310+ data_port = *((u_int16_t *)(data + 4));
2311+ memset(&expect, 0, sizeof(expect));
2312+ /* update the H.225 info */
2313+ DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
2314+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2315+ NIPQUAD(iph->saddr), ntohs(data_port));
2316+ LOCK_BH(&ip_h323_lock);
2317+ info->is_h225 = H225_PORT + 1;
2318+ exp_info->port = data_port;
2319+ exp_info->dir = dir;
2320+ exp_info->offset = i;
2321+
2322+ exp->seq = ntohl(tcph->seq) + i;
2323+
2324+ exp->tuple = ((struct ip_conntrack_tuple)
2325+ { { ct->tuplehash[!dir].tuple.src.ip,
2326+ { 0 } },
2327+ { data_ip,
2328+ { .tcp = { data_port } },
2329+ IPPROTO_UDP }});
2330+ exp->mask = ((struct ip_conntrack_tuple)
2331+ { { 0xFFFFFFFF, { 0 } },
2332+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2333+
2334+ exp->expectfn = NULL;
2335+
2336+ /* Ignore failure; should only happen with NAT */
2337+ ip_conntrack_expect_related(ct, exp);
2338+
2339+ UNLOCK_BH(&ip_h323_lock);
2340+ }
2341+ }
2342+
2343+ return NF_ACCEPT;
2344+
2345+}
2346+
2347+/* H.245 helper is not registered! */
2348+static struct ip_conntrack_helper h245 =
2349+ { { NULL, NULL },
2350+ "H.245", /* name */
2351+ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2352+ NULL, /* module */
2353+ 8, /* max_ expected */
2354+ 240, /* timeout */
2355+ { { 0, { 0 } }, /* tuple */
2356+ { 0, { 0 }, IPPROTO_TCP } },
2357+ { { 0, { 0xFFFF } }, /* mask */
2358+ { 0, { 0 }, 0xFFFF } },
2359+ h245_help /* helper */
2360+ };
2361+
2362+static int h225_expect(struct ip_conntrack *ct)
2363+{
2364+ WRITE_LOCK(&ip_conntrack_lock);
2365+ ct->helper = &h245;
2366+ DEBUGP("h225_expect: helper for %p added\n", ct);
2367+ WRITE_UNLOCK(&ip_conntrack_lock);
2368+
2369+ return NF_ACCEPT; /* unused */
2370+}
2371+
2372+/* FIXME: This should be in userspace. Later. */
2373+static int h225_help(const struct iphdr *iph, size_t len,
2374+ struct ip_conntrack *ct,
2375+ enum ip_conntrack_info ctinfo)
2376+{
2377+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2378+ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2379+ unsigned char *data_limit;
2380+ u_int32_t tcplen = len - iph->ihl * 4;
2381+ u_int32_t datalen = tcplen - tcph->doff * 4;
2382+ int dir = CTINFO2DIR(ctinfo);
2383+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2384+ struct ip_conntrack_expect expect, *exp = &expect;
2385+ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2386+ u_int16_t data_port;
2387+ u_int32_t data_ip;
2388+ unsigned int i;
2389+
2390+ DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2391+ NIPQUAD(iph->saddr), ntohs(tcph->source),
2392+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
2393+
2394+ /* Can't track connections formed before we registered */
2395+ if (!info)
2396+ return NF_ACCEPT;
2397+
2398+ /* Until there's been traffic both ways, don't look in packets. */
2399+ if (ctinfo != IP_CT_ESTABLISHED
2400+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2401+ DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
2402+ return NF_ACCEPT;
2403+ }
2404+
2405+ /* Not whole TCP header or too short packet? */
2406+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2407+ DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
2408+ return NF_ACCEPT;
2409+ }
2410+
2411+ /* Checksum invalid? Ignore. */
2412+ /* FIXME: Source route IP option packets --RR */
2413+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2414+ csum_partial((char *)tcph, tcplen, 0))) {
2415+ DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2416+ tcph, tcplen, NIPQUAD(iph->saddr),
2417+ NIPQUAD(iph->daddr));
2418+ return NF_ACCEPT;
2419+ }
2420+
2421+ data_limit = (unsigned char *) data + datalen;
2422+ /* bytes: 0123 45
2423+ ipadrr port */
2424+ for (i = 0; data < (data_limit - 5); data++, i++) {
2425+ data_ip = *((u_int32_t *)data);
2426+ if (data_ip == iph->saddr) {
2427+ data_port = *((u_int16_t *)(data + 4));
2428+ if (data_port == tcph->source) {
2429+ /* Signal address */
2430+ DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
2431+ NIPQUAD(iph->saddr));
2432+ /* Update the H.225 info so that NAT can mangle the address/port
2433+ even when we have no expected connection! */
2434+#ifdef CONFIG_IP_NF_NAT_NEEDED
2435+ LOCK_BH(&ip_h323_lock);
2436+ info->dir = dir;
2437+ info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
2438+ info->offset[IP_CT_DIR_ORIGINAL] = i;
2439+ UNLOCK_BH(&ip_h323_lock);
2440+#endif
2441+ } else {
2442+ memset(&expect, 0, sizeof(expect));
2443+
2444+ /* update the H.225 info */
2445+ LOCK_BH(&ip_h323_lock);
2446+ info->is_h225 = H225_PORT;
2447+ exp_info->port = data_port;
2448+ exp_info->dir = dir;
2449+ exp_info->offset = i;
2450+
2451+ exp->seq = ntohl(tcph->seq) + i;
2452+
2453+ exp->tuple = ((struct ip_conntrack_tuple)
2454+ { { ct->tuplehash[!dir].tuple.src.ip,
2455+ { 0 } },
2456+ { data_ip,
2457+ { .tcp = { data_port } },
2458+ IPPROTO_TCP }});
2459+ exp->mask = ((struct ip_conntrack_tuple)
2460+ { { 0xFFFFFFFF, { 0 } },
2461+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2462+
2463+ exp->expectfn = h225_expect;
2464+
2465+ /* Ignore failure */
2466+ ip_conntrack_expect_related(ct, exp);
2467+
2468+ DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
2469+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2470+ NIPQUAD(iph->saddr), ntohs(data_port));
2471+
2472+ UNLOCK_BH(&ip_h323_lock);
2473+ }
2474+#ifdef CONFIG_IP_NF_NAT_NEEDED
2475+ } else if (data_ip == iph->daddr) {
2476+ data_port = *((u_int16_t *)(data + 4));
2477+ if (data_port == tcph->dest) {
2478+ /* Signal address */
2479+ DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
2480+ NIPQUAD(iph->daddr));
2481+ /* Update the H.225 info so that NAT can mangle the address/port
2482+ even when we have no expected connection! */
2483+ LOCK_BH(&ip_h323_lock);
2484+ info->dir = dir;
2485+ info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
2486+ info->offset[IP_CT_DIR_REPLY] = i;
2487+ UNLOCK_BH(&ip_h323_lock);
2488+ }
2489+#endif
2490+ }
2491+ }
2492+
2493+ return NF_ACCEPT;
2494+
2495+}
2496+
2497+static struct ip_conntrack_helper h225 =
2498+ { { NULL, NULL },
2499+ "H.225", /* name */
2500+ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2501+ THIS_MODULE, /* module */
2502+ 2, /* max_expected */
2503+ 240, /* timeout */
2504+ { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
2505+ { 0, { 0 }, IPPROTO_TCP } },
2506+ { { 0, { 0xFFFF } }, /* mask */
2507+ { 0, { 0 }, 0xFFFF } },
2508+ h225_help /* helper */
2509+ };
2510+
2511+static int __init init(void)
2512+{
2513+ return ip_conntrack_helper_register(&h225);
2514+}
2515+
2516+static void __exit fini(void)
2517+{
2518+ /* Unregister H.225 helper */
2519+ ip_conntrack_helper_unregister(&h225);
2520+}
2521+
2522+EXPORT_SYMBOL(ip_h323_lock);
2523+
2524+module_init(init);
2525+module_exit(fini);
2526diff -Nur --exclude '*.orig' 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
2527--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
2528+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c 2004-04-29 11:19:01.000000000 +0200
2529@@ -0,0 +1,308 @@
2530+/* MMS extension for IP connection tracking
2531+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2532+ * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
2533+ *
2534+ * ip_conntrack_mms.c v0.3 2002-09-22
2535+ *
2536+ * This program is free software; you can redistribute it and/or
2537+ * modify it under the terms of the GNU General Public License
2538+ * as published by the Free Software Foundation; either version
2539+ * 2 of the License, or (at your option) any later version.
2540+ *
2541+ * Module load syntax:
2542+ * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
2543+ *
2544+ * Please give the ports of all MMS servers You wish to connect to.
2545+ * If you don't specify ports, the default will be TCP port 1755.
2546+ *
2547+ * More info on MMS protocol, firewalls and NAT:
2548+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
2549+ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
2550+ *
2551+ * The SDP project people are reverse-engineering MMS:
2552+ * http://get.to/sdp
2553+ */
2554+
2555+#include <linux/config.h>
2556+#include <linux/module.h>
2557+#include <linux/netfilter.h>
2558+#include <linux/ip.h>
2559+#include <linux/ctype.h>
2560+#include <net/checksum.h>
2561+#include <net/tcp.h>
2562+
2563+#include <linux/netfilter_ipv4/lockhelp.h>
2564+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2565+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
2566+
2567+DECLARE_LOCK(ip_mms_lock);
2568+struct module *ip_conntrack_mms = THIS_MODULE;
2569+
2570+#define MAX_PORTS 8
2571+static int ports[MAX_PORTS];
2572+static int ports_c;
2573+#ifdef MODULE_PARM
2574+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2575+#endif
2576+
2577+#if 0
2578+#define DEBUGP printk
2579+#else
2580+#define DEBUGP(format, args...)
2581+#endif
2582+
2583+EXPORT_SYMBOL(ip_mms_lock);
2584+
2585+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2586+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
2587+MODULE_LICENSE("GPL");
2588+
2589+/* #define isdigit(c) (c >= '0' && c <= '9') */
2590+
2591+/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
2592+static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
2593+{
2594+ int i;
2595+ for (i = 0; i < unicode_size; ++i) {
2596+ string[i] = (char)(unicode[i]);
2597+ }
2598+ string[unicode_size] = 0x00;
2599+}
2600+
2601+__inline static int atoi(char *s)
2602+{
2603+ int i=0;
2604+ while (isdigit(*s)) {
2605+ i = i*10 + *(s++) - '0';
2606+ }
2607+ return i;
2608+}
2609+
2610+/* convert ip address string like "192.168.0.10" to unsigned int */
2611+__inline static u_int32_t asciiiptoi(char *s)
2612+{
2613+ unsigned int i, j, k;
2614+
2615+ for(i=k=0; k<3; ++k, ++s, i<<=8) {
2616+ i+=atoi(s);
2617+ for(j=0; (*(++s) != '.') && (j<3); ++j)
2618+ ;
2619+ }
2620+ i+=atoi(s);
2621+ return ntohl(i);
2622+}
2623+
2624+int parse_mms(const char *data,
2625+ const unsigned int datalen,
2626+ u_int32_t *mms_ip,
2627+ u_int16_t *mms_proto,
2628+ u_int16_t *mms_port,
2629+ char **mms_string_b,
2630+ char **mms_string_e,
2631+ char **mms_padding_e)
2632+{
2633+ int unicode_size, i;
2634+ char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
2635+ char getlengthstring[28];
2636+
2637+ for(unicode_size=0;
2638+ (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2639+ unicode_size++)
2640+ if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
2641+ return -1; /* out of bounds - incomplete packet */
2642+
2643+ unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2644+ DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2645+
2646+ /* IP address ? */
2647+ *mms_ip = asciiiptoi(tempstring+2);
2648+
2649+ i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2650+
2651+ /* protocol ? */
2652+ if(strncmp(tempstring+3+i, "TCP", 3)==0)
2653+ *mms_proto = IPPROTO_TCP;
2654+ else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2655+ *mms_proto = IPPROTO_UDP;
2656+
2657+ /* port ? */
2658+ *mms_port = atoi(tempstring+7+i);
2659+
2660+ /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
2661+ unicode string, one to the end of the string, and one to the end
2662+ of the packet, since we must keep track of the number of bytes
2663+ between end of the unicode string and the end of packet (padding) */
2664+ *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2665+ *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2666+ *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2667+ return 0;
2668+}
2669+
2670+
2671+/* FIXME: This should be in userspace. Later. */
2672+static int help(const struct iphdr *iph, size_t len,
2673+ struct ip_conntrack *ct,
2674+ enum ip_conntrack_info ctinfo)
2675+{
2676+ /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2677+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2678+ const char *data = (const char *)tcph + tcph->doff * 4;
2679+ unsigned int tcplen = len - iph->ihl * 4;
2680+ unsigned int datalen = tcplen - tcph->doff * 4;
2681+ int dir = CTINFO2DIR(ctinfo);
2682+ struct ip_conntrack_expect expect, *exp = &expect;
2683+ struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2684+
2685+ u_int32_t mms_ip;
2686+ u_int16_t mms_proto;
2687+ char mms_proto_string[8];
2688+ u_int16_t mms_port;
2689+ char *mms_string_b, *mms_string_e, *mms_padding_e;
2690+
2691+ /* Until there's been traffic both ways, don't look in packets. */
2692+ if (ctinfo != IP_CT_ESTABLISHED
2693+ && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2694+ DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2695+ return NF_ACCEPT;
2696+ }
2697+
2698+ /* Not whole TCP header? */
2699+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2700+ DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2701+ return NF_ACCEPT;
2702+ }
2703+
2704+ /* Checksum invalid? Ignore. */
2705+ /* FIXME: Source route IP option packets --RR */
2706+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2707+ csum_partial((char *)tcph, tcplen, 0))) {
2708+ DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2709+ tcph, tcplen, NIPQUAD(iph->saddr),
2710+ NIPQUAD(iph->daddr));
2711+ return NF_ACCEPT;
2712+ }
2713+
2714+ /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2715+ /* FIXME: There is an issue with only looking at this packet: before this packet,
2716+ the client has already sent a packet to the server with the server's hostname
2717+ according to the client (think of it as the "Host: " header in HTTP/1.1). The
2718+ server will break the connection if this doesn't correspond to its own host
2719+ header. The client can also connect to an IP address; if it's the server's IP
2720+ address, it will not break the connection. When doing DNAT on a connection
2721+ where the client uses a server's IP address, the nat module should detect
2722+ this and change this string accordingly to the DNATed address. This should
2723+ probably be done by checking for an IP address, then storing it as a member
2724+ of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2725+ */
2726+ if( (MMS_SRV_MSG_OFFSET < datalen) &&
2727+ ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2728+ DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
2729+ (u8)*(data+36), (u8)*(data+37),
2730+ (u8)*(data+38), (u8)*(data+39),
2731+ datalen);
2732+ if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2733+ &mms_string_b, &mms_string_e, &mms_padding_e))
2734+ if(net_ratelimit())
2735+ /* FIXME: more verbose debugging ? */
2736+ printk(KERN_WARNING
2737+ "ip_conntrack_mms: Unable to parse data payload\n");
2738+
2739+ memset(&expect, 0, sizeof(expect));
2740+
2741+ sprintf(mms_proto_string, "(%u)", mms_proto);
2742+ DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2743+ mms_proto == IPPROTO_TCP ? "TCP"
2744+ : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2745+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2746+ NIPQUAD(mms_ip),
2747+ mms_port);
2748+
2749+ /* it's possible that the client will just ask the server to tunnel
2750+ the stream over the same TCP session (from port 1755): there's
2751+ shouldn't be a need to add an expectation in that case, but it
2752+ makes NAT packet mangling so much easier */
2753+ LOCK_BH(&ip_mms_lock);
2754+
2755+ DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2756+
2757+ exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2758+ exp_mms_info->len = (mms_string_e - mms_string_b);
2759+ exp_mms_info->padding = (mms_padding_e - mms_string_e);
2760+ exp_mms_info->port = mms_port;
2761+
2762+ DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2763+ exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2764+
2765+ exp->tuple = ((struct ip_conntrack_tuple)
2766+ { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2767+ { mms_ip,
2768+ { .tcp = { (__u16) ntohs(mms_port) } },
2769+ mms_proto } }
2770+ );
2771+ exp->mask = ((struct ip_conntrack_tuple)
2772+ { { 0xFFFFFFFF, { 0 } },
2773+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2774+ exp->expectfn = NULL;
2775+ ip_conntrack_expect_related(ct, &expect);
2776+ UNLOCK_BH(&ip_mms_lock);
2777+ }
2778+
2779+ return NF_ACCEPT;
2780+}
2781+
2782+static struct ip_conntrack_helper mms[MAX_PORTS];
2783+static char mms_names[MAX_PORTS][10];
2784+
2785+/* Not __exit: called from init() */
2786+static void fini(void)
2787+{
2788+ int i;
2789+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2790+ DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2791+ ports[i]);
2792+ ip_conntrack_helper_unregister(&mms[i]);
2793+ }
2794+}
2795+
2796+static int __init init(void)
2797+{
2798+ int i, ret;
2799+ char *tmpname;
2800+
2801+ if (ports[0] == 0)
2802+ ports[0] = MMS_PORT;
2803+
2804+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2805+ memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2806+ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2807+ mms[i].tuple.dst.protonum = IPPROTO_TCP;
2808+ mms[i].mask.src.u.tcp.port = 0xFFFF;
2809+ mms[i].mask.dst.protonum = 0xFFFF;
2810+ mms[i].max_expected = 1;
2811+ mms[i].timeout = 0;
2812+ mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2813+ mms[i].me = THIS_MODULE;
2814+ mms[i].help = help;
2815+
2816+ tmpname = &mms_names[i][0];
2817+ if (ports[i] == MMS_PORT)
2818+ sprintf(tmpname, "mms");
2819+ else
2820+ sprintf(tmpname, "mms-%d", ports[i]);
2821+ mms[i].name = tmpname;
2822+
2823+ DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
2824+ ports[i]);
2825+ ret = ip_conntrack_helper_register(&mms[i]);
2826+
2827+ if (ret) {
2828+ fini();
2829+ return ret;
2830+ }
2831+ ports_c++;
2832+ }
2833+ return 0;
2834+}
2835+
2836+module_init(init);
2837+module_exit(fini);
2838diff -Nur --exclude '*.orig' 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
2839--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
2840+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-04-29 11:20:17.000000000 +0200
2841@@ -0,0 +1,529 @@
2842+/*
2843+ * Connection tracking protocol helper module for SCTP.
2844+ *
2845+ * SCTP is defined in RFC 2960. References to various sections in this code
2846+ * are to this RFC.
2847+ *
2848+ * This program is free software; you can redistribute it and/or modify
2849+ * it under the terms of the GNU General Public License version 2 as
2850+ * published by the Free Software Foundation.
2851+ */
2852+
2853+#include <linux/types.h>
2854+#include <linux/sched.h>
2855+#include <linux/timer.h>
2856+#include <linux/netfilter.h>
2857+#include <linux/module.h>
2858+#include <linux/in.h>
2859+#include <linux/ip.h>
2860+#include <linux/sctp.h>
2861+#include <linux/string.h>
2862+
2863+#include <linux/netfilter_ipv4/ip_conntrack.h>
2864+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2865+#include <linux/netfilter_ipv4/lockhelp.h>
2866+
2867+#if 0
2868+#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
2869+#else
2870+#define DEBUGP(format, args...)
2871+#endif
2872+
2873+/* Protects conntrack->proto.sctp */
2874+static DECLARE_RWLOCK(sctp_lock);
2875+
2876+/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
2877+ closely. They're more complex. --RR
2878+
2879+ And so for me for SCTP :D -Kiran */
2880+
2881+static const char *sctp_conntrack_names[] = {
2882+ "NONE",
2883+ "CLOSED",
2884+ "COOKIE_WAIT",
2885+ "COOKIE_ECHOED",
2886+ "ESTABLISHED",
2887+ "SHUTDOWN_SENT",
2888+ "SHUTDOWN_RECD",
2889+ "SHUTDOWN_ACK_SENT",
2890+};
2891+
2892+#define SECS * HZ
2893+#define MINS * 60 SECS
2894+#define HOURS * 60 MINS
2895+#define DAYS * 24 HOURS
2896+
2897+unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
2898+unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
2899+unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
2900+unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
2901+unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
2902+unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
2903+unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
2904+
2905+static unsigned long * sctp_timeouts[]
2906+= { 0, /* SCTP_CONNTRACK_NONE */
2907+ &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
2908+ &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
2909+ &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
2910+ &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
2911+ &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
2912+ &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
2913+ &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
2914+ };
2915+
2916+#define sNO SCTP_CONNTRACK_NONE
2917+#define sCL SCTP_CONNTRACK_CLOSED
2918+#define sCW SCTP_CONNTRACK_COOKIE_WAIT
2919+#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
2920+#define sES SCTP_CONNTRACK_ESTABLISHED
2921+#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
2922+#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
2923+#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
2924+#define sIV SCTP_CONNTRACK_MAX
2925+
2926+/*
2927+ These are the descriptions of the states:
2928+
2929+NOTE: These state names are tantalizingly similar to the states of an
2930+SCTP endpoint. But the interpretation of the states is a little different,
2931+considering that these are the states of the connection and not of an end
2932+point. Please note the subtleties. -Kiran
2933+
2934+NONE - Nothing so far.
2935+COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
2936+ an INIT_ACK chunk in the reply direction.
2937+COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
2938+ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
2939+SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
2940+SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
2941+SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
2942+ to that of the SHUTDOWN chunk.
2943+CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
2944+ the SHUTDOWN chunk. Connection is closed.
2945+*/
2946+
2947+/* TODO
2948+ - I have assumed that the first INIT is in the original direction.
2949+ This messes things when an INIT comes in the reply direction in CLOSED
2950+ state.
2951+ - Check the error type in the reply dir before transitioning from
2952+cookie echoed to closed.
2953+ - Sec 5.2.4 of RFC 2960
2954+ - Multi Homing support.
2955+*/
2956+
2957+/* SCTP conntrack state transitions */
2958+static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
2959+ {
2960+/* ORIGINAL */
2961+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
2962+/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
2963+/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
2964+/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
2965+/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
2966+/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
2967+/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
2968+/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
2969+/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
2970+/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
2971+ },
2972+ {
2973+/* REPLY */
2974+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
2975+/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
2976+/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
2977+/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
2978+/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
2979+/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
2980+/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
2981+/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
2982+/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
2983+/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
2984+ }
2985+};
2986+
2987+static int sctp_pkt_to_tuple(const struct sk_buff *skb,
2988+ unsigned int dataoff,
2989+ struct ip_conntrack_tuple *tuple)
2990+{
2991+ sctp_sctphdr_t hdr;
2992+
2993+ DEBUGP(__FUNCTION__);
2994+ DEBUGP("\n");
2995+
2996+ /* Actually only need first 8 bytes. */
2997+ if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
2998+ return 0;
2999+
3000+ tuple->src.u.sctp.port = hdr.source;
3001+ tuple->dst.u.sctp.port = hdr.dest;
3002+
3003+ return 1;
3004+}
3005+
3006+static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
3007+ const struct ip_conntrack_tuple *orig)
3008+{
3009+ DEBUGP(__FUNCTION__);
3010+ DEBUGP("\n");
3011+
3012+ tuple->src.u.sctp.port = orig->dst.u.sctp.port;
3013+ tuple->dst.u.sctp.port = orig->src.u.sctp.port;
3014+ return 1;
3015+}
3016+
3017+/* Print out the per-protocol part of the tuple. */
3018+static unsigned int sctp_print_tuple(char *buffer,
3019+ const struct ip_conntrack_tuple *tuple)
3020+{
3021+ DEBUGP(__FUNCTION__);
3022+ DEBUGP("\n");
3023+
3024+ return sprintf(buffer, "sport=%hu dport=%hu ",
3025+ ntohs(tuple->src.u.sctp.port),
3026+ ntohs(tuple->dst.u.sctp.port));
3027+}
3028+
3029+/* Print out the private part of the conntrack. */
3030+static unsigned int sctp_print_conntrack(char *buffer,
3031+ const struct ip_conntrack *conntrack)
3032+{
3033+ enum sctp_conntrack state;
3034+
3035+ DEBUGP(__FUNCTION__);
3036+ DEBUGP("\n");
3037+
3038+ READ_LOCK(&sctp_lock);
3039+ state = conntrack->proto.sctp.state;
3040+ READ_UNLOCK(&sctp_lock);
3041+
3042+ return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
3043+}
3044+
3045+#define for_each_sctp_chunk(skb, sch, offset, count) \
3046+for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
3047+ offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
3048+ offset += (htons(sch.length) + 3) & ~3, count++)
3049+
3050+/* Some validity checks to make sure the chunks are fine */
3051+static int do_basic_checks(struct ip_conntrack *conntrack,
3052+ const struct sk_buff *skb,
3053+ char *map)
3054+{
3055+ u_int32_t offset, count;
3056+ sctp_chunkhdr_t sch;
3057+ int flag;
3058+
3059+ DEBUGP(__FUNCTION__);
3060+ DEBUGP("\n");
3061+
3062+ flag = 0;
3063+
3064+ for_each_sctp_chunk (skb, sch, offset, count) {
3065+ DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
3066+
3067+ if (sch.type == SCTP_CID_INIT
3068+ || sch.type == SCTP_CID_INIT_ACK
3069+ || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3070+ flag = 1;
3071+ }
3072+
3073+ /* Cookie Ack/Echo chunks not the first OR
3074+ Init / Init Ack / Shutdown compl chunks not the only chunks */
3075+ if ((sch.type == SCTP_CID_COOKIE_ACK
3076+ || sch.type == SCTP_CID_COOKIE_ECHO
3077+ || flag)
3078+ && count !=0 ) {
3079+ DEBUGP("Basic checks failed\n");
3080+ return 1;
3081+ }
3082+
3083+ if (map) {
3084+ set_bit (sch.type, (void *)map);
3085+ }
3086+ }
3087+
3088+ DEBUGP("Basic checks passed\n");
3089+ return 0;
3090+}
3091+
3092+static int new_state(enum ip_conntrack_dir dir,
3093+ enum sctp_conntrack cur_state,
3094+ int chunk_type)
3095+{
3096+ int i;
3097+
3098+ DEBUGP(__FUNCTION__);
3099+ DEBUGP("\n");
3100+
3101+ DEBUGP("Chunk type: %d\n", chunk_type);
3102+
3103+ switch (chunk_type) {
3104+ case SCTP_CID_INIT:
3105+ DEBUGP("SCTP_CID_INIT\n");
3106+ i = 0; break;
3107+ case SCTP_CID_INIT_ACK:
3108+ DEBUGP("SCTP_CID_INIT_ACK\n");
3109+ i = 1; break;
3110+ case SCTP_CID_ABORT:
3111+ DEBUGP("SCTP_CID_ABORT\n");
3112+ i = 2; break;
3113+ case SCTP_CID_SHUTDOWN:
3114+ DEBUGP("SCTP_CID_SHUTDOWN\n");
3115+ i = 3; break;
3116+ case SCTP_CID_SHUTDOWN_ACK:
3117+ DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
3118+ i = 4; break;
3119+ case SCTP_CID_ERROR:
3120+ DEBUGP("SCTP_CID_ERROR\n");
3121+ i = 5; break;
3122+ case SCTP_CID_COOKIE_ECHO:
3123+ DEBUGP("SCTP_CID_COOKIE_ECHO\n");
3124+ i = 6; break;
3125+ case SCTP_CID_COOKIE_ACK:
3126+ DEBUGP("SCTP_CID_COOKIE_ACK\n");
3127+ i = 7; break;
3128+ case SCTP_CID_SHUTDOWN_COMPLETE:
3129+ DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
3130+ i = 8; break;
3131+ default:
3132+ /* Other chunks like DATA, SACK, HEARTBEAT and
3133+ its ACK do not cause a change in state */
3134+ DEBUGP("Unknown chunk type, Will stay in %s\n",
3135+ sctp_conntrack_names[cur_state]);
3136+ return cur_state;
3137+ }
3138+
3139+ DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
3140+ dir, sctp_conntrack_names[cur_state], chunk_type,
3141+ sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
3142+
3143+ return sctp_conntracks[dir][i][cur_state];
3144+}
3145+
3146+/* Returns verdict for packet, or -1 for invalid. */
3147+static int sctp_packet(struct ip_conntrack *conntrack,
3148+ const struct sk_buff *skb,
3149+ enum ip_conntrack_info ctinfo)
3150+{
3151+ enum sctp_conntrack newconntrack, oldsctpstate;
3152+ sctp_sctphdr_t sctph;
3153+ sctp_chunkhdr_t sch;
3154+ u_int32_t offset, count;
3155+ char map[256 / sizeof (char)] = {0};
3156+
3157+ DEBUGP(__FUNCTION__);
3158+ DEBUGP("\n");
3159+
3160+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3161+ return -1;
3162+
3163+ if (do_basic_checks(conntrack, skb, map) != 0)
3164+ return -1;
3165+
3166+ /* Check the verification tag (Sec 8.5) */
3167+ if (!test_bit(SCTP_CID_INIT, (void *)map)
3168+ && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
3169+ && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
3170+ && !test_bit(SCTP_CID_ABORT, (void *)map)
3171+ && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
3172+ && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3173+ DEBUGP("Verification tag check failed\n");
3174+ return -1;
3175+ }
3176+
3177+ oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
3178+ for_each_sctp_chunk (skb, sch, offset, count) {
3179+ WRITE_LOCK(&sctp_lock);
3180+
3181+ /* Special cases of Verification tag check (Sec 8.5.1) */
3182+ if (sch.type == SCTP_CID_INIT) {
3183+ /* Sec 8.5.1 (A) */
3184+ if (sctph.vtag != 0) {
3185+ WRITE_UNLOCK(&sctp_lock);
3186+ return -1;
3187+ }
3188+ } else if (sch.type == SCTP_CID_ABORT) {
3189+ /* Sec 8.5.1 (B) */
3190+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3191+ && !(sctph.vtag == conntrack->proto.sctp.vtag
3192+ [1 - CTINFO2DIR(ctinfo)])) {
3193+ WRITE_UNLOCK(&sctp_lock);
3194+ return -1;
3195+ }
3196+ } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3197+ /* Sec 8.5.1 (C) */
3198+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3199+ && !(sctph.vtag == conntrack->proto.sctp.vtag
3200+ [1 - CTINFO2DIR(ctinfo)]
3201+ && (sch.flags & 1))) {
3202+ WRITE_UNLOCK(&sctp_lock);
3203+ return -1;
3204+ }
3205+ } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
3206+ /* Sec 8.5.1 (D) */
3207+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3208+ WRITE_UNLOCK(&sctp_lock);
3209+ return -1;
3210+ }
3211+ }
3212+
3213+ oldsctpstate = conntrack->proto.sctp.state;
3214+ newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
3215+
3216+ /* Invalid */
3217+ if (newconntrack == SCTP_CONNTRACK_MAX) {
3218+ DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
3219+ CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
3220+ WRITE_UNLOCK(&sctp_lock);
3221+ return -1;
3222+ }
3223+
3224+ /* If it is an INIT or an INIT ACK note down the vtag */
3225+ if (sch.type == SCTP_CID_INIT
3226+ || sch.type == SCTP_CID_INIT_ACK) {
3227+ sctp_inithdr_t inithdr;
3228+
3229+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
3230+ &inithdr, sizeof(inithdr)) != 0) {
3231+ WRITE_UNLOCK(&sctp_lock);
3232+ return -1;
3233+ }
3234+ DEBUGP("Setting vtag %x for dir %d\n",
3235+ inithdr.init_tag, CTINFO2DIR(ctinfo));
3236+ conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
3237+ }
3238+
3239+ conntrack->proto.sctp.state = newconntrack;
3240+ WRITE_UNLOCK(&sctp_lock);
3241+ }
3242+
3243+ ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
3244+
3245+ if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
3246+ && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
3247+ && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
3248+ DEBUGP("Setting assured bit\n");
3249+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
3250+ }
3251+
3252+ return NF_ACCEPT;
3253+}
3254+
3255+/* Called when a new connection for this protocol found. */
3256+static int sctp_new(struct ip_conntrack *conntrack,
3257+ const struct sk_buff *skb)
3258+{
3259+ enum sctp_conntrack newconntrack;
3260+ sctp_sctphdr_t sctph;
3261+ sctp_chunkhdr_t sch;
3262+ u_int32_t offset, count;
3263+ char map[256 / sizeof (char)] = {0};
3264+
3265+ DEBUGP(__FUNCTION__);
3266+ DEBUGP("\n");
3267+
3268+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3269+ return -1;
3270+
3271+ if (do_basic_checks(conntrack, skb, map) != 0)
3272+ return -1;
3273+
3274+ /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
3275+ if ((test_bit (SCTP_CID_ABORT, (void *)map))
3276+ || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
3277+ || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
3278+ return -1;
3279+ }
3280+
3281+ newconntrack = SCTP_CONNTRACK_MAX;
3282+ for_each_sctp_chunk (skb, sch, offset, count) {
3283+ /* Don't need lock here: this conntrack not in circulation yet */
3284+ newconntrack = new_state (IP_CT_DIR_ORIGINAL,
3285+ SCTP_CONNTRACK_NONE, sch.type);
3286+
3287+ /* Invalid: delete conntrack */
3288+ if (newconntrack == SCTP_CONNTRACK_MAX) {
3289+ DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
3290+ return 0;
3291+ }
3292+
3293+ /* Copy the vtag into the state info */
3294+ if (sch.type == SCTP_CID_INIT) {
3295+ if (sctph.vtag == 0) {
3296+ sctp_inithdr_t inithdr;
3297+
3298+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
3299+ &inithdr, sizeof(inithdr)) != 0) {
3300+ return -1;
3301+ }
3302+
3303+ DEBUGP("Setting vtag %x for new conn\n",
3304+ inithdr.init_tag);
3305+
3306+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
3307+ inithdr.init_tag;
3308+ } else {
3309+ /* Sec 8.5.1 (A) */
3310+ return -1;
3311+ }
3312+ }
3313+ /* If it is a shutdown ack OOTB packet, we expect a return
3314+ shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
3315+ else {
3316+ DEBUGP("Setting vtag %x for new conn OOTB\n",
3317+ sctph.vtag);
3318+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
3319+ }
3320+
3321+ conntrack->proto.sctp.state = newconntrack;
3322+ }
3323+
3324+ return 1;
3325+}
3326+
3327+static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
3328+ const struct sk_buff *skb)
3329+{
3330+ /* To be implemented */
3331+ return 0;
3332+}
3333+
3334+struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
3335+ .list = { NULL, NULL },
3336+ .proto = IPPROTO_SCTP,
3337+ .name = "sctp",
3338+ .pkt_to_tuple = sctp_pkt_to_tuple,
3339+ .invert_tuple = sctp_invert_tuple,
3340+ .print_tuple = sctp_print_tuple,
3341+ .print_conntrack = sctp_print_conntrack,
3342+ .packet = sctp_packet,
3343+ .new = sctp_new,
3344+ .destroy = NULL,
3345+ .exp_matches_pkt = sctp_exp_matches_pkt,
3346+ .me = THIS_MODULE
3347+};
3348+
3349+int __init init(void)
3350+{
3351+ int ret;
3352+
3353+ ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
3354+ DEBUGP("SCTP conntrack module loading %s\n",
3355+ ret ? "failed": "succeeded");
3356+ return ret;
3357+}
3358+
3359+void __exit fini(void)
3360+{
3361+ ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
3362+ DEBUGP("SCTP conntrack module unloaded\n");
3363+}
3364+
3365+module_init(init);
3366+module_exit(fini);
3367+
3368+MODULE_LICENSE("GPL");
3369+MODULE_AUTHOR("Kiran Kumar Immidi");
3370+MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
3371diff -Nur --exclude '*.orig' 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
3372--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
3373+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-04-29 11:19:53.000000000 +0200
3374@@ -0,0 +1,156 @@
3375+/* Quake3 extension for IP connection tracking
3376+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3377+ * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
3378+ *
3379+ * ip_conntrack_quake3.c v0.04 2002-08-31
3380+ *
3381+ * This program is free software; you can redistribute it and/or
3382+ * modify it under the terms of the GNU General Public License
3383+ * as published by the Free Software Foundation; either version
3384+ * 2 of the License, or (at your option) any later version.
3385+ *
3386+ * Module load syntax:
3387+ * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
3388+ *
3389+ * please give the ports of all Quake3 master servers You wish to
3390+ * connect to. If you don't specify ports, the default will be UDP
3391+ * port 27950.
3392+ *
3393+ * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
3394+ */
3395+
3396+#include <linux/module.h>
3397+#include <linux/ip.h>
3398+#include <linux/udp.h>
3399+
3400+#include <linux/netfilter.h>
3401+#include <linux/netfilter_ipv4/ip_tables.h>
3402+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3403+#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
3404+
3405+struct module *ip_conntrack_quake3 = THIS_MODULE;
3406+
3407+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3408+MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
3409+MODULE_LICENSE("GPL");
3410+
3411+#define MAX_PORTS 8
3412+static int ports[MAX_PORTS];
3413+static int ports_c = 0;
3414+#ifdef MODULE_PARM
3415+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3416+MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
3417+#endif
3418+
3419+/* Quake3 master server reply will add > 100 expectations per reply packet; when
3420+ doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
3421+#if 0
3422+#define DEBUGP printk
3423+#else
3424+#define DEBUGP(format, args...)
3425+#endif
3426+
3427+struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
3428+
3429+static int quake3_help(const struct iphdr *iph, size_t len,
3430+ struct ip_conntrack *ct,
3431+ enum ip_conntrack_info ctinfo)
3432+{
3433+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
3434+ int dir = CTINFO2DIR(ctinfo);
3435+ struct ip_conntrack_expect exp;
3436+ int i;
3437+
3438+ /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
3439+ if (ctinfo != IP_CT_ESTABLISHED
3440+ && ctinfo != IP_CT_IS_REPLY) {
3441+ DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
3442+ return NF_ACCEPT;
3443+ } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
3444+
3445+ if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
3446+ for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
3447+ i+6 < ntohs(udph->len);
3448+ i+=7) {
3449+ DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
3450+ i, ntohs(udph->len),
3451+ NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
3452+ ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
3453+
3454+ memset(&exp, 0, sizeof(exp));
3455+
3456+ exp.tuple = ((struct ip_conntrack_tuple)
3457+ { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3458+ { (u_int32_t) *((u_int32_t *)((int)udph + i)),
3459+ { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
3460+ IPPROTO_UDP } }
3461+ );
3462+ exp.mask = ((struct ip_conntrack_tuple)
3463+ { { 0xFFFFFFFF, { 0 } },
3464+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
3465+ exp.expectfn = NULL;
3466+
3467+ ip_conntrack_expect_related(ct, &exp);
3468+ }
3469+
3470+ }
3471+
3472+ return(NF_ACCEPT);
3473+}
3474+
3475+static struct ip_conntrack_helper quake3[MAX_PORTS];
3476+static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
3477+
3478+static void fini(void)
3479+{
3480+ int i;
3481+
3482+ for(i = 0 ; (i < ports_c); i++) {
3483+ DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
3484+ ports[i]);
3485+ ip_conntrack_helper_unregister(&quake3[i]);
3486+ }
3487+}
3488+
3489+static int __init init(void)
3490+{
3491+ int i, ret;
3492+ char *tmpname;
3493+
3494+ if(!ports[0])
3495+ ports[0]=QUAKE3_MASTER_PORT;
3496+
3497+ for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
3498+ /* Create helper structure */
3499+ memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
3500+
3501+ quake3[i].tuple.dst.protonum = IPPROTO_UDP;
3502+ quake3[i].tuple.src.u.udp.port = htons(ports[i]);
3503+ quake3[i].mask.dst.protonum = 0xFFFF;
3504+ quake3[i].mask.src.u.udp.port = 0xFFFF;
3505+ quake3[i].help = quake3_help;
3506+ quake3[i].me = THIS_MODULE;
3507+
3508+ tmpname = &quake3_names[i][0];
3509+ if (ports[i] == QUAKE3_MASTER_PORT)
3510+ sprintf(tmpname, "quake3");
3511+ else
3512+ sprintf(tmpname, "quake3-%d", i);
3513+ quake3[i].name = tmpname;
3514+
3515+ DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
3516+ ports[i]);
3517+
3518+ ret=ip_conntrack_helper_register(&quake3[i]);
3519+ if(ret) {
3520+ fini();
3521+ return(ret);
3522+ }
3523+ ports_c++;
3524+ }
3525+
3526+ return(0);
3527+}
3528+
3529+module_init(init);
3530+module_exit(fini);
3531diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
3532--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
3533+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2004-04-29 11:20:02.000000000 +0200
3534@@ -0,0 +1,508 @@
3535+/* RPC extension for IP (TCP) connection tracking, Version 2.2
3536+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3537+ * - original rpc tracking module
3538+ * - "recent" connection handling for kernel 2.3+ netfilter
3539+ *
3540+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3541+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3542+ *
3543+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3544+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
3545+ * - extended matching to support filtering on procedures
3546+ *
3547+ * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
3548+ *
3549+ * This program is free software; you can redistribute it and/or
3550+ * modify it under the terms of the GNU General Public License
3551+ * as published by the Free Software Foundation; either version
3552+ * 2 of the License, or (at your option) any later version.
3553+ **
3554+ * Module load syntax:
3555+ * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
3556+ *
3557+ * Please give the ports of all RPC servers you wish to connect to.
3558+ * If you don't specify ports, the default will be port 111.
3559+ **
3560+ * Note to all:
3561+ *
3562+ * RPCs should not be exposed to the internet - ask the Pentagon;
3563+ *
3564+ * "The unidentified crackers pleaded guilty in July to charges
3565+ * of juvenile delinquency stemming from a string of Pentagon
3566+ * network intrusions in February.
3567+ *
3568+ * The youths, going by the names TooShort and Makaveli, used
3569+ * a common server security hole to break in, according to
3570+ * Dane Jasper, owner of the California Internet service
3571+ * provider, Sonic. They used the hole, known as the 'statd'
3572+ * exploit, to attempt more than 800 break-ins, Jasper said."
3573+ *
3574+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3575+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
3576+ **
3577+ */
3578+
3579+#include <linux/module.h>
3580+#include <linux/netfilter.h>
3581+#include <linux/ip.h>
3582+#include <net/checksum.h>
3583+#include <net/tcp.h>
3584+
3585+#include <asm/param.h>
3586+#include <linux/sched.h>
3587+#include <linux/timer.h>
3588+#include <linux/stddef.h>
3589+#include <linux/list.h>
3590+
3591+#include <linux/netfilter_ipv4/lockhelp.h>
3592+#include <linux/netfilter_ipv4/ip_tables.h>
3593+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3594+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3595+
3596+#define MAX_PORTS 8
3597+static int ports[MAX_PORTS];
3598+static int ports_n_c = 0;
3599+
3600+#ifdef MODULE_PARM
3601+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3602+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3603+#endif
3604+
3605+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3606+MODULE_DESCRIPTION("RPC TCP connection tracking module");
3607+MODULE_LICENSE("GPL");
3608+
3609+#if 0
3610+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
3611+ format, ## args)
3612+#else
3613+#define DEBUGP(format, args...)
3614+#endif
3615+
3616+DECLARE_RWLOCK(ipct_rpc_tcp_lock);
3617+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
3618+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
3619+#include <linux/netfilter_ipv4/listhelp.h>
3620+
3621+/* For future conections RPC, using client's cache bindings
3622+ * I'll use ip_conntrack_lock to lock these lists */
3623+
3624+LIST_HEAD(request_p_list_tcp);
3625+
3626+
3627+static void delete_request_p(unsigned long request_p_ul)
3628+{
3629+ struct request_p *p = (void *)request_p_ul;
3630+
3631+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3632+ LIST_DELETE(&request_p_list_tcp, p);
3633+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3634+ kfree(p);
3635+ return;
3636+}
3637+
3638+
3639+static void req_cl(struct request_p * r)
3640+{
3641+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3642+ del_timer(&r->timeout);
3643+ LIST_DELETE(&request_p_list_tcp, r);
3644+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3645+ kfree(r);
3646+ return;
3647+}
3648+
3649+
3650+static void clean_request(struct list_head *list)
3651+{
3652+ struct list_head *first = list->prev;
3653+ struct list_head *temp = list->next;
3654+ struct list_head *aux;
3655+
3656+ if (list_empty(list))
3657+ return;
3658+
3659+ while (first != temp) {
3660+ aux = temp->next;
3661+ req_cl((struct request_p *)temp);
3662+ temp = aux;
3663+ }
3664+ req_cl((struct request_p *)temp);
3665+ return;
3666+}
3667+
3668+
3669+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3670+ u_int16_t port)
3671+{
3672+ struct request_p *req_p;
3673+
3674+ /* Verifies if entry already exists */
3675+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3676+ req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3677+ struct request_p *, xid, ip, port);
3678+
3679+ if (req_p) {
3680+ /* Refresh timeout */
3681+ if (del_timer(&req_p->timeout)) {
3682+ req_p->timeout.expires = jiffies + EXP;
3683+ add_timer(&req_p->timeout);
3684+ }
3685+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3686+ return;
3687+
3688+ }
3689+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3690+
3691+ /* Allocate new request_p */
3692+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3693+ if (!req_p) {
3694+ DEBUGP("can't allocate request_p\n");
3695+ return;
3696+ }
3697+ *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
3698+ { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3699+ NULL }});
3700+
3701+ /* Initialize timer */
3702+ init_timer(&req_p->timeout);
3703+ req_p->timeout.function = delete_request_p;
3704+ add_timer(&req_p->timeout);
3705+
3706+ /* Put in list */
3707+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3708+ list_prepend(&request_p_list_tcp, req_p);
3709+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3710+ return;
3711+
3712+}
3713+
3714+
3715+static int check_rpc_packet(const u_int32_t *data,
3716+ int dir, struct ip_conntrack *ct,
3717+ struct list_head request_p_list)
3718+{
3719+ struct request_p *req_p;
3720+ u_int32_t xid;
3721+ struct ip_conntrack_expect expect, *exp = &expect;
3722+
3723+ /* Translstion's buffer for XDR */
3724+ u_int16_t port_buf;
3725+
3726+
3727+ /* Get XID */
3728+ xid = *data;
3729+
3730+ /* This does sanity checking on RPC payloads,
3731+ * and permits only the RPC "get port" (3)
3732+ * in authorised procedures in client
3733+ * communications with the portmapper.
3734+ */
3735+
3736+ /* perform direction dependant RPC work */
3737+ if (dir == IP_CT_DIR_ORIGINAL) {
3738+
3739+ data += 5;
3740+
3741+ /* Get RPC requestor */
3742+ if (IXDR_GET_INT32(data) != 3) {
3743+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3744+ return NF_ACCEPT;
3745+ }
3746+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3747+
3748+ data++;
3749+
3750+ /* Jump Credentials and Verfifier */
3751+ data += IXDR_GET_INT32(data) + 2;
3752+ data += IXDR_GET_INT32(data) + 2;
3753+
3754+ /* Get RPC procedure */
3755+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3756+ (unsigned int)IXDR_GET_INT32(data));
3757+
3758+ /* Get RPC protocol and store against client parameters */
3759+ data = data + 2;
3760+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3761+ ct->tuplehash[dir].tuple.src.u.all);
3762+
3763+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3764+ xid, IXDR_GET_INT32(data),
3765+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3766+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
3767+
3768+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
3769+ (unsigned int)IXDR_GET_INT32(data));
3770+
3771+ } else {
3772+
3773+ /* Check for returning packet's stored counterpart */
3774+ req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3775+ struct request_p *, xid,
3776+ ct->tuplehash[!dir].tuple.src.ip,
3777+ ct->tuplehash[!dir].tuple.src.u.all);
3778+
3779+ /* Drop unexpected packets */
3780+ if (!req_p) {
3781+ DEBUGP("packet is not expected. [skip]\n");
3782+ return NF_ACCEPT;
3783+ }
3784+
3785+ /* Verifies if packet is really an RPC reply packet */
3786+ data = data++;
3787+ if (IXDR_GET_INT32(data) != 1) {
3788+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
3789+ return NF_ACCEPT;
3790+ }
3791+
3792+ /* Is status accept? */
3793+ data++;
3794+ if (IXDR_GET_INT32(data)) {
3795+ DEBUGP("packet is not an RPC accept. [skip]\n");
3796+ return NF_ACCEPT;
3797+ }
3798+
3799+ /* Get Verifier length. Jump verifier */
3800+ data++;
3801+ data = data + IXDR_GET_INT32(data) + 2;
3802+
3803+ /* Is accpet status "success"? */
3804+ if (IXDR_GET_INT32(data)) {
3805+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3806+ return NF_ACCEPT;
3807+ }
3808+
3809+ /* Get server port number */
3810+ data++;
3811+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
3812+
3813+ /* If a packet has made it this far then it deserves an
3814+ * expectation ... if port == 0, then this service is
3815+ * not going to be registered.
3816+ */
3817+ if (port_buf) {
3818+ DEBUGP("port found: %u\n", port_buf);
3819+
3820+ memset(&expect, 0, sizeof(expect));
3821+
3822+ /* Watch out, Radioactive-Man! */
3823+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3824+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3825+ exp->mask.src.ip = 0xffffffff;
3826+ exp->mask.dst.ip = 0xffffffff;
3827+
3828+ switch (req_p->proto) {
3829+ case IPPROTO_UDP:
3830+ exp->tuple.src.u.udp.port = 0;
3831+ exp->tuple.dst.u.udp.port = htons(port_buf);
3832+ exp->tuple.dst.protonum = IPPROTO_UDP;
3833+ exp->mask.src.u.udp.port = 0;
3834+ exp->mask.dst.u.udp.port = htons(0xffff);
3835+ exp->mask.dst.protonum = 0xffff;
3836+ break;
3837+
3838+ case IPPROTO_TCP:
3839+ exp->tuple.src.u.tcp.port = 0;
3840+ exp->tuple.dst.u.tcp.port = htons(port_buf);
3841+ exp->tuple.dst.protonum = IPPROTO_TCP;
3842+ exp->mask.src.u.tcp.port = 0;
3843+ exp->mask.dst.u.tcp.port = htons(0xffff);
3844+ exp->mask.dst.protonum = 0xffff;
3845+ break;
3846+ }
3847+ exp->expectfn = NULL;
3848+
3849+ ip_conntrack_expect_related(ct, &expect);
3850+
3851+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3852+ NIPQUAD(exp->tuple.src.ip),
3853+ NIPQUAD(exp->tuple.dst.ip),
3854+ port_buf, req_p->proto);
3855+
3856+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3857+ NIPQUAD(exp->mask.src.ip),
3858+ NIPQUAD(exp->mask.dst.ip),
3859+ exp->mask.dst.protonum);
3860+
3861+ }
3862+
3863+ req_cl(req_p);
3864+
3865+ DEBUGP("packet evaluated. [expect]\n");
3866+ return NF_ACCEPT;
3867+ }
3868+
3869+ return NF_ACCEPT;
3870+
3871+}
3872+
3873+
3874+/* RPC TCP helper */
3875+static int help(const struct iphdr *iph, size_t len,
3876+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3877+{
3878+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3879+ const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3880+ size_t tcplen = len - iph->ihl * 4;
3881+
3882+ int dir = CTINFO2DIR(ctinfo);
3883+ int crp_ret;
3884+
3885+
3886+ DEBUGP("new packet to evaluate ..\n");
3887+
3888+ /* This works for packets like handshake packets, ignore */
3889+ if (len == ((tcph->doff + iph->ihl) * 4)) {
3890+ DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3891+ return NF_ACCEPT;
3892+ }
3893+
3894+ /* Until there's been traffic both ways, don't look in packets. */
3895+ if (ctinfo != IP_CT_ESTABLISHED
3896+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3897+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3898+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3899+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3900+ return NF_ACCEPT;
3901+ }
3902+
3903+ /* Not whole TCP header? */
3904+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3905+ DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3906+ DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3907+ return NF_ACCEPT;
3908+ }
3909+
3910+ /* FIXME: Source route IP option packets --RR */
3911+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3912+ csum_partial((char *) tcph, tcplen, 0))) {
3913+ DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3914+ tcph, tcplen, NIPQUAD(iph->saddr),
3915+ NIPQUAD(iph->daddr));
3916+ DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3917+ DEBUGP("packet contains a bad checksum. [skip]\n");
3918+ return NF_ACCEPT;
3919+ }
3920+
3921+ /* perform direction dependant protocol work */
3922+ if (dir == IP_CT_DIR_ORIGINAL) {
3923+
3924+ DEBUGP("packet is from the initiator. [cont]\n");
3925+
3926+ /* Tests if packet len is ok */
3927+ if ((tcplen - (tcph->doff * 4)) != 60) {
3928+ DEBUGP("packet length is not correct. [skip]\n");
3929+ return NF_ACCEPT;
3930+ }
3931+
3932+ } else {
3933+
3934+ DEBUGP("packet is from the receiver. [cont]\n");
3935+
3936+ /* Tests if packet len is ok */
3937+ if ((tcplen - (tcph->doff * 4)) != 32) {
3938+ DEBUGP("packet length is not correct. [skip]\n");
3939+ return NF_ACCEPT;
3940+ }
3941+ }
3942+
3943+ /* Get to the data */
3944+ data++;
3945+
3946+ /* Check the RPC data */
3947+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
3948+
3949+ return crp_ret;
3950+
3951+}
3952+
3953+
3954+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3955+
3956+static void fini(void);
3957+
3958+
3959+static int __init init(void)
3960+{
3961+ int port, ret;
3962+ static char name[10];
3963+
3964+
3965+ /* If no port given, default to standard RPC port */
3966+ if (ports[0] == 0)
3967+ ports[0] = RPC_PORT;
3968+
3969+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3970+ memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3971+
3972+ if (ports[port] == RPC_PORT)
3973+ sprintf(name, "rpc");
3974+ else
3975+ sprintf(name, "rpc-%d", port);
3976+
3977+ rpc_helpers[port].name = name;
3978+ rpc_helpers[port].me = THIS_MODULE;
3979+ rpc_helpers[port].max_expected = 1;
3980+ rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3981+ rpc_helpers[port].timeout = 0;
3982+
3983+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
3984+ rpc_helpers[port].mask.dst.protonum = 0xffff;
3985+
3986+ /* RPC can come from ports 0:65535 to ports[port] (111) */
3987+ rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3988+ rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3989+ rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3990+
3991+ rpc_helpers[port].help = help;
3992+
3993+ DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
3994+ DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3995+ NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3996+ ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
3997+ NIPQUAD(rpc_helpers[port].tuple.src.ip),
3998+ ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
3999+ DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4000+ NIPQUAD(rpc_helpers[port].mask.dst.ip),
4001+ ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
4002+ NIPQUAD(rpc_helpers[port].mask.src.ip),
4003+ ntohs(rpc_helpers[port].mask.src.u.tcp.port));
4004+
4005+ ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4006+
4007+ if (ret) {
4008+ printk("ERROR registering port %d\n",
4009+ ports[port]);
4010+ fini();
4011+ return -EBUSY;
4012+ }
4013+ ports_n_c++;
4014+ }
4015+ return 0;
4016+}
4017+
4018+
4019+/* This function is intentionally _NOT_ defined as __exit, because
4020+ * it is needed by the init function */
4021+static void fini(void)
4022+{
4023+ int port;
4024+
4025+ DEBUGP("cleaning request list\n");
4026+ clean_request(&request_p_list_tcp);
4027+
4028+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4029+ DEBUGP("unregistering port %d\n", ports[port]);
4030+ ip_conntrack_helper_unregister(&rpc_helpers[port]);
4031+ }
4032+}
4033+
4034+
4035+module_init(init);
4036+module_exit(fini);
4037+
4038+struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
4039+EXPORT_SYMBOL(request_p_list_tcp);
4040+EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
4041+EXPORT_SYMBOL(ipct_rpc_tcp_lock);
4042+
4043diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
4044--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
4045+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2004-04-29 11:20:02.000000000 +0200
4046@@ -0,0 +1,503 @@
4047+/* RPC extension for IP (UDP) connection tracking, Version 2.2
4048+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
4049+ * - original rpc tracking module
4050+ * - "recent" connection handling for kernel 2.3+ netfilter
4051+ *
4052+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
4053+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
4054+ *
4055+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4056+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
4057+ * - extended matching to support filtering on procedures
4058+ *
4059+ * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
4060+ *
4061+ * This program is free software; you can redistribute it and/or
4062+ * modify it under the terms of the GNU General Public License
4063+ * as published by the Free Software Foundation; either version
4064+ * 2 of the License, or (at your option) any later version.
4065+ **
4066+ * Module load syntax:
4067+ * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
4068+ *
4069+ * Please give the ports of all RPC servers you wish to connect to.
4070+ * If you don't specify ports, the default will be port 111.
4071+ **
4072+ * Note to all:
4073+ *
4074+ * RPCs should not be exposed to the internet - ask the Pentagon;
4075+ *
4076+ * "The unidentified crackers pleaded guilty in July to charges
4077+ * of juvenile delinquency stemming from a string of Pentagon
4078+ * network intrusions in February.
4079+ *
4080+ * The youths, going by the names TooShort and Makaveli, used
4081+ * a common server security hole to break in, according to
4082+ * Dane Jasper, owner of the California Internet service
4083+ * provider, Sonic. They used the hole, known as the 'statd'
4084+ * exploit, to attempt more than 800 break-ins, Jasper said."
4085+ *
4086+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
4087+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
4088+ **
4089+ */
4090+
4091+#include <linux/module.h>
4092+#include <linux/netfilter.h>
4093+#include <linux/ip.h>
4094+#include <net/checksum.h>
4095+#include <net/udp.h>
4096+
4097+#include <asm/param.h>
4098+#include <linux/sched.h>
4099+#include <linux/timer.h>
4100+#include <linux/stddef.h>
4101+#include <linux/list.h>
4102+
4103+#include <linux/netfilter_ipv4/lockhelp.h>
4104+#include <linux/netfilter_ipv4/ip_tables.h>
4105+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4106+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
4107+
4108+#define MAX_PORTS 8
4109+static int ports[MAX_PORTS];
4110+static int ports_n_c = 0;
4111+
4112+#ifdef MODULE_PARM
4113+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4114+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
4115+#endif
4116+
4117+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
4118+MODULE_DESCRIPTION("RPC UDP connection tracking module");
4119+MODULE_LICENSE("GPL");
4120+
4121+#if 0
4122+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
4123+ format, ## args)
4124+#else
4125+#define DEBUGP(format, args...)
4126+#endif
4127+
4128+DECLARE_RWLOCK(ipct_rpc_udp_lock);
4129+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
4130+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
4131+#include <linux/netfilter_ipv4/listhelp.h>
4132+
4133+/* For future conections RPC, using client's cache bindings
4134+ * I'll use ip_conntrack_lock to lock these lists */
4135+
4136+LIST_HEAD(request_p_list_udp);
4137+
4138+
4139+static void delete_request_p(unsigned long request_p_ul)
4140+{
4141+ struct request_p *p = (void *)request_p_ul;
4142+
4143+ WRITE_LOCK(&ipct_rpc_udp_lock);
4144+ LIST_DELETE(&request_p_list_udp, p);
4145+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4146+ kfree(p);
4147+ return;
4148+}
4149+
4150+
4151+static void req_cl(struct request_p * r)
4152+{
4153+ WRITE_LOCK(&ipct_rpc_udp_lock);
4154+ del_timer(&r->timeout);
4155+ LIST_DELETE(&request_p_list_udp, r);
4156+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4157+ kfree(r);
4158+ return;
4159+}
4160+
4161+
4162+static void clean_request(struct list_head *list)
4163+{
4164+ struct list_head *first = list->prev;
4165+ struct list_head *temp = list->next;
4166+ struct list_head *aux;
4167+
4168+ if (list_empty(list))
4169+ return;
4170+
4171+ while (first != temp) {
4172+ aux = temp->next;
4173+ req_cl((struct request_p *)temp);
4174+ temp = aux;
4175+ }
4176+ req_cl((struct request_p *)temp);
4177+ return;
4178+}
4179+
4180+
4181+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
4182+ u_int16_t port)
4183+{
4184+ struct request_p *req_p;
4185+
4186+ /* Verifies if entry already exists */
4187+ WRITE_LOCK(&ipct_rpc_udp_lock);
4188+ req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4189+ struct request_p *, xid, ip, port);
4190+
4191+ if (req_p) {
4192+ /* Refresh timeout */
4193+ if (del_timer(&req_p->timeout)) {
4194+ req_p->timeout.expires = jiffies + EXP;
4195+ add_timer(&req_p->timeout);
4196+ }
4197+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4198+ return;
4199+
4200+ }
4201+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4202+
4203+ /* Allocate new request_p */
4204+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
4205+ if (!req_p) {
4206+ DEBUGP("can't allocate request_p\n");
4207+ return;
4208+ }
4209+ *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
4210+ { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
4211+ NULL }});
4212+
4213+ /* Initialize timer */
4214+ init_timer(&req_p->timeout);
4215+ req_p->timeout.function = delete_request_p;
4216+ add_timer(&req_p->timeout);
4217+
4218+ /* Put in list */
4219+ WRITE_LOCK(&ipct_rpc_udp_lock);
4220+ list_prepend(&request_p_list_udp, req_p);
4221+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4222+ return;
4223+
4224+}
4225+
4226+
4227+static int check_rpc_packet(const u_int32_t *data,
4228+ int dir, struct ip_conntrack *ct,
4229+ struct list_head request_p_list)
4230+{
4231+ struct request_p *req_p;
4232+ u_int32_t xid;
4233+ struct ip_conntrack_expect expect, *exp = &expect;
4234+
4235+ /* Translstion's buffer for XDR */
4236+ u_int16_t port_buf;
4237+
4238+
4239+ /* Get XID */
4240+ xid = *data;
4241+
4242+ /* This does sanity checking on RPC payloads,
4243+ * and permits only the RPC "get port" (3)
4244+ * in authorised procedures in client
4245+ * communications with the portmapper.
4246+ */
4247+
4248+ /* perform direction dependant RPC work */
4249+ if (dir == IP_CT_DIR_ORIGINAL) {
4250+
4251+ data += 5;
4252+
4253+ /* Get RPC requestor */
4254+ if (IXDR_GET_INT32(data) != 3) {
4255+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
4256+ return NF_ACCEPT;
4257+ }
4258+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
4259+
4260+ data++;
4261+
4262+ /* Jump Credentials and Verfifier */
4263+ data = data + IXDR_GET_INT32(data) + 2;
4264+ data = data + IXDR_GET_INT32(data) + 2;
4265+
4266+ /* Get RPC procedure */
4267+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
4268+ (unsigned int)IXDR_GET_INT32(data));
4269+
4270+ /* Get RPC protocol and store against client parameters */
4271+ data = data + 2;
4272+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
4273+ ct->tuplehash[dir].tuple.src.u.all);
4274+
4275+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
4276+ xid, IXDR_GET_INT32(data),
4277+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
4278+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
4279+
4280+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
4281+ (unsigned int)IXDR_GET_INT32(data));
4282+
4283+ } else {
4284+
4285+ /* Check for returning packet's stored counterpart */
4286+ req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4287+ struct request_p *, xid,
4288+ ct->tuplehash[!dir].tuple.src.ip,
4289+ ct->tuplehash[!dir].tuple.src.u.all);
4290+
4291+ /* Drop unexpected packets */
4292+ if (!req_p) {
4293+ DEBUGP("packet is not expected. [skip]\n");
4294+ return NF_ACCEPT;
4295+ }
4296+
4297+ /* Verifies if packet is really an RPC reply packet */
4298+ data = data++;
4299+ if (IXDR_GET_INT32(data) != 1) {
4300+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
4301+ return NF_ACCEPT;
4302+ }
4303+
4304+ /* Is status accept? */
4305+ data++;
4306+ if (IXDR_GET_INT32(data)) {
4307+ DEBUGP("packet is not an RPC accept. [skip]\n");
4308+ return NF_ACCEPT;
4309+ }
4310+
4311+ /* Get Verifier length. Jump verifier */
4312+ data++;
4313+ data = data + IXDR_GET_INT32(data) + 2;
4314+
4315+ /* Is accpet status "success"? */
4316+ if (IXDR_GET_INT32(data)) {
4317+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
4318+ return NF_ACCEPT;
4319+ }
4320+
4321+ /* Get server port number */
4322+ data++;
4323+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
4324+
4325+ /* If a packet has made it this far then it deserves an
4326+ * expectation ... if port == 0, then this service is
4327+ * not going to be registered.
4328+ */
4329+ if (port_buf) {
4330+ DEBUGP("port found: %u\n", port_buf);
4331+
4332+ memset(&expect, 0, sizeof(expect));
4333+
4334+ /* Watch out, Radioactive-Man! */
4335+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4336+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4337+ exp->mask.src.ip = 0xffffffff;
4338+ exp->mask.dst.ip = 0xffffffff;
4339+
4340+ switch (req_p->proto) {
4341+ case IPPROTO_UDP:
4342+ exp->tuple.src.u.udp.port = 0;
4343+ exp->tuple.dst.u.udp.port = htons(port_buf);
4344+ exp->tuple.dst.protonum = IPPROTO_UDP;
4345+ exp->mask.src.u.udp.port = 0;
4346+ exp->mask.dst.u.udp.port = htons(0xffff);
4347+ exp->mask.dst.protonum = 0xffff;
4348+ break;
4349+
4350+ case IPPROTO_TCP:
4351+ exp->tuple.src.u.tcp.port = 0;
4352+ exp->tuple.dst.u.tcp.port = htons(port_buf);
4353+ exp->tuple.dst.protonum = IPPROTO_TCP;
4354+ exp->mask.src.u.tcp.port = 0;
4355+ exp->mask.dst.u.tcp.port = htons(0xffff);
4356+ exp->mask.dst.protonum = 0xffff;
4357+ break;
4358+ }
4359+ exp->expectfn = NULL;
4360+
4361+ ip_conntrack_expect_related(ct, &expect);
4362+
4363+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
4364+ NIPQUAD(exp->tuple.src.ip),
4365+ NIPQUAD(exp->tuple.dst.ip),
4366+ port_buf, req_p->proto);
4367+
4368+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
4369+ NIPQUAD(exp->mask.src.ip),
4370+ NIPQUAD(exp->mask.dst.ip),
4371+ exp->mask.dst.protonum);
4372+
4373+ }
4374+
4375+ req_cl(req_p);
4376+
4377+ DEBUGP("packet evaluated. [expect]\n");
4378+ return NF_ACCEPT;
4379+ }
4380+
4381+ return NF_ACCEPT;
4382+
4383+}
4384+
4385+
4386+/* RPC UDP helper */
4387+static int help(const struct iphdr *iph, size_t len,
4388+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4389+{
4390+ struct udphdr *udph = (void *) iph + iph->ihl * 4;
4391+ const u_int32_t *data = (const u_int32_t *)udph + 2;
4392+ size_t udplen = len - iph->ihl * 4;
4393+ int dir = CTINFO2DIR(ctinfo);
4394+ int crp_ret;
4395+
4396+ /* Checksum */
4397+ const u_int16_t *chsm = (const u_int16_t *)udph + 3;
4398+
4399+
4400+ DEBUGP("new packet to evaluate ..\n");
4401+
4402+ /* Not whole UDP header? */
4403+ if (udplen < sizeof(struct udphdr)) {
4404+ DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
4405+ DEBUGP("packet does not contain a complete UDP header. [skip]\n");
4406+ return NF_ACCEPT;
4407+ }
4408+
4409+ /* FIXME: Source route IP option packets --RR */
4410+ if (*chsm) {
4411+ if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4412+ csum_partial((char *)udph, udplen, 0))) {
4413+ DEBUGP("[note: failure to get past this error may indicate source routing]\n");
4414+ DEBUGP("packet contains a bad checksum. [skip]\n");
4415+ return NF_ACCEPT;
4416+ }
4417+ }
4418+
4419+ /* perform direction dependant protocol work */
4420+ if (dir == IP_CT_DIR_ORIGINAL) {
4421+
4422+ DEBUGP("packet is from the initiator. [cont]\n");
4423+
4424+ /* Tests if packet len is ok */
4425+ if ((udplen - sizeof(struct udphdr)) != 56) {
4426+ DEBUGP("packet length is not correct. [skip]\n");
4427+ return NF_ACCEPT;
4428+ }
4429+
4430+ } else {
4431+
4432+ DEBUGP("packet is from the receiver. [cont]\n");
4433+
4434+ /* Until there's been traffic both ways, don't look in packets. */
4435+ if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4436+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
4437+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
4438+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
4439+ return NF_ACCEPT;
4440+ }
4441+
4442+ /* Tests if packet len is ok */
4443+ if ((udplen - sizeof(struct udphdr)) != 28) {
4444+ DEBUGP("packet length is not correct. [skip]\n");
4445+ return NF_ACCEPT;
4446+ }
4447+
4448+ }
4449+
4450+ /* Get to the data */
4451+ /* udp *data == *correct */
4452+
4453+ /* Check the RPC data */
4454+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
4455+
4456+ return crp_ret;
4457+
4458+}
4459+
4460+
4461+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
4462+
4463+static void fini(void);
4464+
4465+
4466+static int __init init(void)
4467+{
4468+ int port, ret;
4469+ static char name[10];
4470+
4471+
4472+ /* If no port given, default to standard RPC port */
4473+ if (ports[0] == 0)
4474+ ports[0] = RPC_PORT;
4475+
4476+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4477+ memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4478+
4479+ if (ports[port] == RPC_PORT)
4480+ sprintf(name, "rpc");
4481+ else
4482+ sprintf(name, "rpc-%d", port);
4483+
4484+ rpc_helpers[port].name = name;
4485+ rpc_helpers[port].me = THIS_MODULE;
4486+ rpc_helpers[port].max_expected = 1;
4487+ rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4488+ rpc_helpers[port].timeout = 0;
4489+
4490+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
4491+ rpc_helpers[port].mask.dst.protonum = 0xffff;
4492+
4493+ /* RPC can come from ports 0:65535 to ports[port] (111) */
4494+ rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
4495+ rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
4496+ rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
4497+
4498+ rpc_helpers[port].help = help;
4499+
4500+ DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
4501+ DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4502+ NIPQUAD(rpc_helpers[port].tuple.dst.ip),
4503+ ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
4504+ NIPQUAD(rpc_helpers[port].tuple.src.ip),
4505+ ntohs(rpc_helpers[port].tuple.src.u.udp.port));
4506+ DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4507+ NIPQUAD(rpc_helpers[port].mask.dst.ip),
4508+ ntohs(rpc_helpers[port].mask.dst.u.udp.port),
4509+ NIPQUAD(rpc_helpers[port].mask.src.ip),
4510+ ntohs(rpc_helpers[port].mask.src.u.udp.port));
4511+
4512+ ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4513+
4514+ if (ret) {
4515+ printk("ERROR registering port %d\n",
4516+ ports[port]);
4517+ fini();
4518+ return -EBUSY;
4519+ }
4520+ ports_n_c++;
4521+ }
4522+ return 0;
4523+}
4524+
4525+
4526+/* This function is intentionally _NOT_ defined as __exit, because
4527+ * it is needed by the init function */
4528+static void fini(void)
4529+{
4530+ int port;
4531+
4532+ DEBUGP("cleaning request list\n");
4533+ clean_request(&request_p_list_udp);
4534+
4535+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4536+ DEBUGP("unregistering port %d\n", ports[port]);
4537+ ip_conntrack_helper_unregister(&rpc_helpers[port]);
4538+ }
4539+}
4540+
4541+
4542+module_init(init);
4543+module_exit(fini);
4544+
4545+struct module *ip_conntrack_rpc_udp = THIS_MODULE;
4546+EXPORT_SYMBOL(request_p_list_udp);
4547+EXPORT_SYMBOL(ip_conntrack_rpc_udp);
4548+EXPORT_SYMBOL(ipct_rpc_udp_lock);
4549+
4550diff -Nur --exclude '*.orig' 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
4551--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
4552+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-04-29 11:20:06.000000000 +0200
4553@@ -0,0 +1,331 @@
4554+/* RSH extension for IP connection tracking, Version 1.0
4555+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4556+ * based on HW's ip_conntrack_irc.c
4557+ *
4558+ * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
4559+ *
4560+ * This program is free software; you can redistribute it and/or
4561+ * modify it under the terms of the GNU General Public License
4562+ * as published by the Free Software Foundation; either version
4563+ * 2 of the License, or (at your option) any later version.
4564+ **
4565+ * Module load syntax:
4566+ * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
4567+ *
4568+ * please give the ports of all RSH servers You wish to connect to.
4569+ * If You don't specify ports, the default will be port 514
4570+ **
4571+ * Note to all:
4572+ * RSH blows ... you should use SSH (openssh.org) to replace it,
4573+ * unfortunately I babysit some sysadmins that won't migrate
4574+ * their legacy crap, in our second tier.
4575+ */
4576+
4577+
4578+/*
4579+ * Some docco ripped from the net to teach me all there is to know about
4580+ * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
4581+ * this module).
4582+ *
4583+ * I have no idea what "unix rshd man pages" these guys have .. but that
4584+ * is some pretty detailed docco!
4585+ **
4586+ *
4587+ * 4. Of the rsh protocol.
4588+ * -----------------------
4589+ *
4590+ * The rshd listens on TCP port #514. The following info is from the unix
4591+ * rshd man pages :
4592+ *
4593+ * "Service Request Protocol
4594+ *
4595+ * When the rshd daemon receives a service request, it initiates the
4596+ * following protocol:
4597+ *
4598+ * 1. The rshd daemon checks the source port number for the request.
4599+ * If the port number is not in the range 0 through 1023, the rshd daemon
4600+ * terminates the connection.
4601+ *
4602+ * 2. The rshd daemon reads characters from the socket up to a null byte.
4603+ * The string read is interpreted as an ASCII number (base 10). If this
4604+ * number is nonzero, the rshd daemon interprets it as the port number
4605+ * of a secondary stream to be used as standard error. A second connection
4606+ * is created to the specified port on the client host. The source port
4607+ * on the local host is in the range 0 through 1023.
4608+ *
4609+ * 3. The rshd daemon uses the source address of the initial connection
4610+ * request to determine the name of the client host. If the name cannot
4611+ * be determined, the rshd daemon uses the dotted decimal representation
4612+ * of the client host's address.
4613+ *
4614+ * 4. The rshd daemon retrieves the following information from the initial
4615+ * socket:
4616+ *
4617+ * * A null-terminated string of at most 16 bytes interpreted as
4618+ * the user name of the user on the client host.
4619+ *
4620+ * * A null-terminated string of at most 16 bytes interpreted as
4621+ * the user name to be used on the local server host.
4622+ *
4623+ * * Another null-terminated string interpreted as a command line
4624+ * to be passed to a shell on the local server host.
4625+ *
4626+ * 5. The rshd daemon attempts to validate the user using the following steps:
4627+ *
4628+ * a. The rshd daemon looks up the local user name in the /etc/passwd
4629+ * file and tries to switch to the home directory (using the chdir
4630+ * subroutine). If either the lookup or the directory change fails,
4631+ * the rshd daemon terminates the connection.
4632+ *
4633+ * b. If the local user ID is a nonzero value, the rshd daemon searches
4634+ * the /etc/hosts.equiv file to see if the name of the client
4635+ * workstation is listed. If the client workstation is listed as an
4636+ * equivalent host, the rshd daemon validates the user.
4637+ *
4638+ * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4639+ * authenticate the user by checking the .rhosts file.
4640+ *
4641+ * d. If either the $HOME/.rhosts authentication fails or the
4642+ * client host is not an equivalent host, the rshd daemon
4643+ * terminates the connection.
4644+ *
4645+ * 6. Once rshd validates the user, the rshd daemon returns a null byte
4646+ * on the initial connection and passes the command line to the user's
4647+ * local login shell. The shell then inherits the network connections
4648+ * established by the rshd daemon."
4649+ *
4650+ */
4651+
4652+
4653+#include <linux/module.h>
4654+#include <linux/netfilter.h>
4655+#include <linux/ip.h>
4656+#include <net/checksum.h>
4657+#include <net/tcp.h>
4658+
4659+#include <linux/netfilter_ipv4/lockhelp.h>
4660+#include <linux/netfilter_ipv4/ip_tables.h>
4661+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4662+#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4663+
4664+#define MAX_PORTS 8
4665+static int ports[MAX_PORTS];
4666+static int ports_n_c = 0;
4667+
4668+MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4669+MODULE_DESCRIPTION("RSH connection tracking module");
4670+MODULE_LICENSE("GPL");
4671+#ifdef MODULE_PARM
4672+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4673+MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4674+#endif
4675+
4676+DECLARE_LOCK(ip_rsh_lock);
4677+struct module *ip_conntrack_rsh = THIS_MODULE;
4678+
4679+#if 0
4680+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4681+ format, ## args)
4682+#else
4683+#define DEBUGP(format, args...)
4684+#endif
4685+
4686+
4687+
4688+/* FIXME: This should be in userspace. Later. */
4689+static int help(const struct iphdr *iph, size_t len,
4690+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4691+{
4692+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4693+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4694+ const char *data = (const char *) tcph + tcph->doff * 4;
4695+ u_int32_t tcplen = len - iph->ihl * 4;
4696+ int dir = CTINFO2DIR(ctinfo);
4697+ struct ip_conntrack_expect expect, *exp = &expect;
4698+ struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4699+ u_int16_t port;
4700+ int maxoctet;
4701+
4702+ /* note that "maxoctet" is used to maintain sanity (8 was the
4703+ * original array size used in rshd/glibc) -- is there a
4704+ * vulnerability in rshd.c in the looped port *= 10?
4705+ */
4706+
4707+
4708+ DEBUGP("entered\n");
4709+
4710+ /* bail if packet is not from RSH client */
4711+ if (dir == IP_CT_DIR_REPLY)
4712+ return NF_ACCEPT;
4713+
4714+ /* Until there's been traffic both ways, don't look in packets. */
4715+ if (ctinfo != IP_CT_ESTABLISHED
4716+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4717+ DEBUGP("Conntrackinfo = %u\n", ctinfo);
4718+ return NF_ACCEPT;
4719+ }
4720+
4721+ /* Not whole TCP header? */
4722+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4723+ DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4724+ return NF_ACCEPT;
4725+ }
4726+
4727+ /* Checksum invalid? Ignore. */
4728+ /* FIXME: Source route IP option packets --RR */
4729+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4730+ csum_partial((char *) tcph, tcplen, 0))) {
4731+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4732+ tcph, tcplen, NIPQUAD(iph->saddr),
4733+ NIPQUAD(iph->daddr));
4734+ return NF_ACCEPT;
4735+ }
4736+
4737+ /* find the rsh stderr port */
4738+ maxoctet = 4;
4739+ port = 0;
4740+ for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4741+ if (*data < 0)
4742+ return(1);
4743+ if (*data == 0)
4744+ break;
4745+ if (*data < 48 || *data > 57) {
4746+ DEBUGP("these aren't the packets you're looking for ..\n");
4747+ return NF_ACCEPT;
4748+ }
4749+ port = port * 10 + ( *data - 48 );
4750+ }
4751+
4752+ /* dont relate sessions that try to expose the client */
4753+ DEBUGP("found port %u\n", port);
4754+ if (port > 1023) {
4755+ DEBUGP("skipping, expected port size is greater than 1023!\n");
4756+ return NF_ACCEPT;
4757+ }
4758+
4759+
4760+ LOCK_BH(&ip_rsh_lock);
4761+
4762+ /* new(,related) connection is;
4763+ * reply + dst (uint)port + src port (0:1023)
4764+ */
4765+ memset(&expect, 0, sizeof(expect));
4766+
4767+ /* save some discovered data, in case someone ever wants to write
4768+ * a NAT module for this bastard ..
4769+ */
4770+ exp_rsh_info->port = port;
4771+
4772+ DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4773+
4774+
4775+ /* Watch out, Radioactive-Man! */
4776+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4777+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4778+ exp->tuple.src.u.tcp.port = 0;
4779+ exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4780+ exp->tuple.dst.protonum = IPPROTO_TCP;
4781+
4782+ exp->mask.src.ip = 0xffffffff;
4783+ exp->mask.dst.ip = 0xffffffff;
4784+
4785+ exp->mask.src.u.tcp.port = htons(0xfc00);
4786+ exp->mask.dst.u.tcp.port = htons(0xfc00);
4787+ exp->mask.dst.protonum = 0xffff;
4788+
4789+ exp->expectfn = NULL;
4790+
4791+ ip_conntrack_expect_related(ct, &expect);
4792+
4793+ DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4794+ NIPQUAD(exp->tuple.src.ip),
4795+ ntohs(exp->tuple.src.u.tcp.port),
4796+ NIPQUAD(exp->tuple.dst.ip),
4797+ ntohs(exp->tuple.dst.u.tcp.port));
4798+
4799+ DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4800+ NIPQUAD(exp->mask.src.ip),
4801+ ntohs(exp->mask.src.u.tcp.port),
4802+ NIPQUAD(exp->mask.dst.ip),
4803+ ntohs(exp->mask.dst.u.tcp.port));
4804+ UNLOCK_BH(&ip_rsh_lock);
4805+
4806+ return NF_ACCEPT;
4807+}
4808+
4809+static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4810+
4811+static void fini(void);
4812+
4813+static int __init init(void)
4814+{
4815+ int port, ret;
4816+ static char name[10];
4817+
4818+
4819+ /* If no port given, default to standard RSH port */
4820+ if (ports[0] == 0)
4821+ ports[0] = RSH_PORT;
4822+
4823+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4824+ memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4825+
4826+ if (ports[port] == RSH_PORT)
4827+ sprintf(name, "rsh");
4828+ else
4829+ sprintf(name, "rsh-%d", port);
4830+
4831+ rsh_helpers[port].name = name;
4832+ rsh_helpers[port].me = THIS_MODULE;
4833+ rsh_helpers[port].max_expected = 1;
4834+ rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4835+ rsh_helpers[port].timeout = 0;
4836+
4837+ rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4838+ rsh_helpers[port].mask.dst.protonum = 0xffff;
4839+
4840+ /* RSH must come from ports 0:1023 to ports[port] (514) */
4841+ rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4842+ rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4843+ rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4844+
4845+ rsh_helpers[port].help = help;
4846+
4847+ DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4848+ DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4849+ NIPQUAD(rsh_helpers[port].tuple.src.ip),
4850+ ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4851+ NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4852+ ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4853+ DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4854+ NIPQUAD(rsh_helpers[port].mask.src.ip),
4855+ ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4856+ NIPQUAD(rsh_helpers[port].mask.dst.ip),
4857+ ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4858+
4859+ ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4860+
4861+ if (ret) {
4862+ printk("ERROR registering port %d\n",
4863+ ports[port]);
4864+ fini();
4865+ return -EBUSY;
4866+ }
4867+ ports_n_c++;
4868+ }
4869+ return 0;
4870+}
4871+
4872+/* This function is intentionally _NOT_ defined as __exit, because
4873+ * it is needed by the init function */
4874+static void fini(void)
4875+{
4876+ int port;
4877+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4878+ DEBUGP("unregistering port %d\n", ports[port]);
4879+ ip_conntrack_helper_unregister(&rsh_helpers[port]);
4880+ }
4881+}
4882+
4883+module_init(init);
4884+module_exit(fini);
4885diff -Nur --exclude '*.orig' 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
4886--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
4887+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-04-29 11:20:13.000000000 +0200
4888@@ -0,0 +1,507 @@
4889+/*
4890+ * RTSP extension for IP connection tracking
4891+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
4892+ * based on ip_conntrack_irc.c
4893+ *
4894+ * This program is free software; you can redistribute it and/or
4895+ * modify it under the terms of the GNU General Public License
4896+ * as published by the Free Software Foundation; either version
4897+ * 2 of the License, or (at your option) any later version.
4898+ *
4899+ * Module load syntax:
4900+ * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
4901+ * max_outstanding=n setup_timeout=secs
4902+ *
4903+ * If no ports are specified, the default will be port 554.
4904+ *
4905+ * With max_outstanding you can define the maximum number of not yet
4906+ * answered SETUP requests per RTSP session (default 8).
4907+ * With setup_timeout you can specify how long the system waits for
4908+ * an expected data channel (default 300 seconds).
4909+ */
4910+
4911+#include <linux/config.h>
4912+#include <linux/module.h>
4913+#include <linux/netfilter.h>
4914+#include <linux/ip.h>
4915+#include <net/checksum.h>
4916+#include <net/tcp.h>
4917+
4918+#include <linux/netfilter_ipv4/lockhelp.h>
4919+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4920+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
4921+
4922+#include <linux/ctype.h>
4923+#define NF_NEED_STRNCASECMP
4924+#define NF_NEED_STRTOU16
4925+#define NF_NEED_STRTOU32
4926+#define NF_NEED_NEXTLINE
4927+#include <linux/netfilter_helpers.h>
4928+#define NF_NEED_MIME_NEXTLINE
4929+#include <linux/netfilter_mime.h>
4930+
4931+#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
4932+
4933+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
4934+#ifdef IP_NF_RTSP_DEBUG
4935+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
4936+#else
4937+#define DEBUGP(fmt, args...)
4938+#endif
4939+
4940+#define MAX_PORTS 8
4941+static int ports[MAX_PORTS];
4942+static int num_ports = 0;
4943+static int max_outstanding = 8;
4944+static unsigned int setup_timeout = 300;
4945+
4946+MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
4947+MODULE_DESCRIPTION("RTSP connection tracking module");
4948+MODULE_LICENSE("GPL");
4949+#ifdef MODULE_PARM
4950+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4951+MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
4952+MODULE_PARM(max_outstanding, "i");
4953+MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
4954+MODULE_PARM(setup_timeout, "i");
4955+MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
4956+#endif
4957+
4958+DECLARE_LOCK(ip_rtsp_lock);
4959+struct module* ip_conntrack_rtsp = THIS_MODULE;
4960+
4961+/*
4962+ * Max mappings we will allow for one RTSP connection (for RTP, the number
4963+ * of allocated ports is twice this value). Note that SMIL burns a lot of
4964+ * ports so keep this reasonably high. If this is too low, you will see a
4965+ * lot of "no free client map entries" messages.
4966+ */
4967+#define MAX_PORT_MAPS 16
4968+
4969+/*** default port list was here in the masq code: 554, 3030, 4040 ***/
4970+
4971+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
4972+
4973+/*
4974+ * Parse an RTSP packet.
4975+ *
4976+ * Returns zero if parsing failed.
4977+ *
4978+ * Parameters:
4979+ * IN ptcp tcp data pointer
4980+ * IN tcplen tcp data len
4981+ * IN/OUT ptcpoff points to current tcp offset
4982+ * OUT phdrsoff set to offset of rtsp headers
4983+ * OUT phdrslen set to length of rtsp headers
4984+ * OUT pcseqoff set to offset of CSeq header
4985+ * OUT pcseqlen set to length of CSeq header
4986+ */
4987+static int
4988+rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
4989+ uint* phdrsoff, uint* phdrslen,
4990+ uint* pcseqoff, uint* pcseqlen)
4991+{
4992+ uint entitylen = 0;
4993+ uint lineoff;
4994+ uint linelen;
4995+
4996+ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
4997+ {
4998+ return 0;
4999+ }
5000+
5001+ *phdrsoff = *ptcpoff;
5002+ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5003+ {
5004+ if (linelen == 0)
5005+ {
5006+ if (entitylen > 0)
5007+ {
5008+ *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5009+ }
5010+ break;
5011+ }
5012+ if (lineoff+linelen > tcplen)
5013+ {
5014+ INFOP("!! overrun !!\n");
5015+ break;
5016+ }
5017+
5018+ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5019+ {
5020+ *pcseqoff = lineoff;
5021+ *pcseqlen = linelen;
5022+ }
5023+ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5024+ {
5025+ uint off = lineoff+15;
5026+ SKIP_WSPACE(ptcp+lineoff, linelen, off);
5027+ nf_strtou32(ptcp+off, &entitylen);
5028+ }
5029+ }
5030+ *phdrslen = (*ptcpoff) - (*phdrsoff);
5031+
5032+ return 1;
5033+}
5034+
5035+/*
5036+ * Find lo/hi client ports (if any) in transport header
5037+ * In:
5038+ * ptcp, tcplen = packet
5039+ * tranoff, tranlen = buffer to search
5040+ *
5041+ * Out:
5042+ * pport_lo, pport_hi = lo/hi ports (host endian)
5043+ *
5044+ * Returns nonzero if any client ports found
5045+ *
5046+ * Note: it is valid (and expected) for the client to request multiple
5047+ * transports, so we need to parse the entire line.
5048+ */
5049+static int
5050+rtsp_parse_transport(char* ptran, uint tranlen,
5051+ struct ip_ct_rtsp_expect* prtspexp)
5052+{
5053+ int rc = 0;
5054+ uint off = 0;
5055+
5056+ if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5057+ nf_strncasecmp(ptran, "Transport:", 10) != 0)
5058+ {
5059+ INFOP("sanity check failed\n");
5060+ return 0;
5061+ }
5062+ DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5063+ off += 10;
5064+ SKIP_WSPACE(ptran, tranlen, off);
5065+
5066+ /* Transport: tran;field;field=val,tran;field;field=val,... */
5067+ while (off < tranlen)
5068+ {
5069+ const char* pparamend;
5070+ uint nextparamoff;
5071+
5072+ pparamend = memchr(ptran+off, ',', tranlen-off);
5073+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5074+ nextparamoff = pparamend-ptran;
5075+
5076+ while (off < nextparamoff)
5077+ {
5078+ const char* pfieldend;
5079+ uint nextfieldoff;
5080+
5081+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5082+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5083+
5084+ if (strncmp(ptran+off, "client_port=", 12) == 0)
5085+ {
5086+ u_int16_t port;
5087+ uint numlen;
5088+
5089+ off += 12;
5090+ numlen = nf_strtou16(ptran+off, &port);
5091+ off += numlen;
5092+ if (prtspexp->loport != 0 && prtspexp->loport != port)
5093+ {
5094+ DEBUGP("multiple ports found, port %hu ignored\n", port);
5095+ }
5096+ else
5097+ {
5098+ prtspexp->loport = prtspexp->hiport = port;
5099+ if (ptran[off] == '-')
5100+ {
5101+ off++;
5102+ numlen = nf_strtou16(ptran+off, &port);
5103+ off += numlen;
5104+ prtspexp->pbtype = pb_range;
5105+ prtspexp->hiport = port;
5106+
5107+ // If we have a range, assume rtp:
5108+ // loport must be even, hiport must be loport+1
5109+ if ((prtspexp->loport & 0x0001) != 0 ||
5110+ prtspexp->hiport != prtspexp->loport+1)
5111+ {
5112+ DEBUGP("incorrect range: %hu-%hu, correcting\n",
5113+ prtspexp->loport, prtspexp->hiport);
5114+ prtspexp->loport &= 0xfffe;
5115+ prtspexp->hiport = prtspexp->loport+1;
5116+ }
5117+ }
5118+ else if (ptran[off] == '/')
5119+ {
5120+ off++;
5121+ numlen = nf_strtou16(ptran+off, &port);
5122+ off += numlen;
5123+ prtspexp->pbtype = pb_discon;
5124+ prtspexp->hiport = port;
5125+ }
5126+ rc = 1;
5127+ }
5128+ }
5129+
5130+ /*
5131+ * Note we don't look for the destination parameter here.
5132+ * If we are using NAT, the NAT module will handle it. If not,
5133+ * and the client is sending packets elsewhere, the expectation
5134+ * will quietly time out.
5135+ */
5136+
5137+ off = nextfieldoff;
5138+ }
5139+
5140+ off = nextparamoff;
5141+ }
5142+
5143+ return rc;
5144+}
5145+
5146+/*** conntrack functions ***/
5147+
5148+/* outbound packet: client->server */
5149+static int
5150+help_out(const struct iphdr* iph, size_t pktlen,
5151+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5152+{
5153+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5154+ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5155+ uint tcplen = pktlen - iph->ihl * 4;
5156+ char* pdata = (char*)tcph + tcph->doff * 4;
5157+ uint datalen = tcplen - tcph->doff * 4;
5158+ uint dataoff = 0;
5159+
5160+ struct ip_conntrack_expect exp;
5161+
5162+ while (dataoff < datalen)
5163+ {
5164+ uint cmdoff = dataoff;
5165+ uint hdrsoff = 0;
5166+ uint hdrslen = 0;
5167+ uint cseqoff = 0;
5168+ uint cseqlen = 0;
5169+ uint lineoff = 0;
5170+ uint linelen = 0;
5171+ uint off;
5172+ int rc;
5173+
5174+ if (!rtsp_parse_message(pdata, datalen, &dataoff,
5175+ &hdrsoff, &hdrslen,
5176+ &cseqoff, &cseqlen))
5177+ {
5178+ break; /* not a valid message */
5179+ }
5180+
5181+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5182+ {
5183+ continue; /* not a SETUP message */
5184+ }
5185+ DEBUGP("found a setup message\n");
5186+
5187+ memset(&exp, 0, sizeof(exp));
5188+
5189+ off = 0;
5190+ while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5191+ &lineoff, &linelen))
5192+ {
5193+ if (linelen == 0)
5194+ {
5195+ break;
5196+ }
5197+ if (off > hdrsoff+hdrslen)
5198+ {
5199+ INFOP("!! overrun !!");
5200+ break;
5201+ }
5202+
5203+ if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5204+ {
5205+ rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5206+ &exp.help.exp_rtsp_info);
5207+ }
5208+ }
5209+
5210+ if (exp.help.exp_rtsp_info.loport == 0)
5211+ {
5212+ DEBUGP("no udp transports found\n");
5213+ continue; /* no udp transports found */
5214+ }
5215+
5216+ DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5217+ (int)exp.help.exp_rtsp_info.pbtype,
5218+ exp.help.exp_rtsp_info.loport,
5219+ exp.help.exp_rtsp_info.hiport);
5220+
5221+ LOCK_BH(&ip_rtsp_lock);
5222+ exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5223+ exp.help.exp_rtsp_info.len = hdrslen;
5224+
5225+ exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5226+ exp.mask.src.ip = 0xffffffff;
5227+ exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5228+ exp.mask.dst.ip = 0xffffffff;
5229+ exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5230+ exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5231+ exp.tuple.dst.protonum = IPPROTO_UDP;
5232+ exp.mask.dst.protonum = 0xffff;
5233+
5234+ DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5235+ NIPQUAD(exp.tuple.src.ip),
5236+ ntohs(exp.tuple.src.u.tcp.port),
5237+ NIPQUAD(exp.tuple.dst.ip),
5238+ ntohs(exp.tuple.dst.u.tcp.port));
5239+
5240+ /* pass the request off to the nat helper */
5241+ rc = ip_conntrack_expect_related(ct, &exp);
5242+ UNLOCK_BH(&ip_rtsp_lock);
5243+ if (rc == 0)
5244+ {
5245+ DEBUGP("ip_conntrack_expect_related succeeded\n");
5246+ }
5247+ else
5248+ {
5249+ INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5250+ }
5251+ }
5252+
5253+ return NF_ACCEPT;
5254+}
5255+
5256+/* inbound packet: server->client */
5257+static int
5258+help_in(const struct iphdr* iph, size_t pktlen,
5259+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5260+{
5261+ return NF_ACCEPT;
5262+}
5263+
5264+static int
5265+help(const struct iphdr* iph, size_t pktlen,
5266+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5267+{
5268+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5269+ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5270+ u_int32_t tcplen = pktlen - iph->ihl * 4;
5271+
5272+ /* Until there's been traffic both ways, don't look in packets. */
5273+ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5274+ {
5275+ DEBUGP("conntrackinfo = %u\n", ctinfo);
5276+ return NF_ACCEPT;
5277+ }
5278+
5279+ /* Not whole TCP header? */
5280+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5281+ {
5282+ DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5283+ return NF_ACCEPT;
5284+ }
5285+
5286+ /* Checksum invalid? Ignore. */
5287+ /* FIXME: Source route IP option packets --RR */
5288+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5289+ csum_partial((char*)tcph, tcplen, 0)))
5290+ {
5291+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5292+ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5293+ return NF_ACCEPT;
5294+ }
5295+
5296+ switch (CTINFO2DIR(ctinfo))
5297+ {
5298+ case IP_CT_DIR_ORIGINAL:
5299+ help_out(iph, pktlen, ct, ctinfo);
5300+ break;
5301+ case IP_CT_DIR_REPLY:
5302+ help_in(iph, pktlen, ct, ctinfo);
5303+ break;
5304+ }
5305+
5306+ return NF_ACCEPT;
5307+}
5308+
5309+static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5310+static char rtsp_names[MAX_PORTS][10];
5311+
5312+/* This function is intentionally _NOT_ defined as __exit */
5313+static void
5314+fini(void)
5315+{
5316+ int i;
5317+ for (i = 0; i < num_ports; i++)
5318+ {
5319+ DEBUGP("unregistering port %d\n", ports[i]);
5320+ ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5321+ }
5322+}
5323+
5324+static int __init
5325+init(void)
5326+{
5327+ int i, ret;
5328+ struct ip_conntrack_helper *hlpr;
5329+ char *tmpname;
5330+
5331+ printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5332+
5333+ if (max_outstanding < 1)
5334+ {
5335+ printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5336+ return -EBUSY;
5337+ }
5338+ if (setup_timeout < 0)
5339+ {
5340+ printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5341+ return -EBUSY;
5342+ }
5343+
5344+ /* If no port given, default to standard rtsp port */
5345+ if (ports[0] == 0)
5346+ {
5347+ ports[0] = RTSP_PORT;
5348+ }
5349+
5350+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5351+ {
5352+ hlpr = &rtsp_helpers[i];
5353+ memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5354+ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5355+ hlpr->tuple.dst.protonum = IPPROTO_TCP;
5356+ hlpr->mask.src.u.tcp.port = 0xFFFF;
5357+ hlpr->mask.dst.protonum = 0xFFFF;
5358+ hlpr->max_expected = max_outstanding;
5359+ hlpr->timeout = setup_timeout;
5360+ hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5361+ hlpr->me = ip_conntrack_rtsp;
5362+ hlpr->help = help;
5363+
5364+ tmpname = &rtsp_names[i][0];
5365+ if (ports[i] == RTSP_PORT)
5366+ {
5367+ sprintf(tmpname, "rtsp");
5368+ }
5369+ else
5370+ {
5371+ sprintf(tmpname, "rtsp-%d", i);
5372+ }
5373+ hlpr->name = tmpname;
5374+
5375+ DEBUGP("port #%d: %d\n", i, ports[i]);
5376+
5377+ ret = ip_conntrack_helper_register(hlpr);
5378+
5379+ if (ret)
5380+ {
5381+ printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5382+ fini();
5383+ return -EBUSY;
5384+ }
5385+ num_ports++;
5386+ }
5387+ return 0;
5388+}
5389+
5390+#ifdef CONFIG_IP_NF_NAT_NEEDED
5391+EXPORT_SYMBOL(ip_rtsp_lock);
5392+#endif
5393+
5394+module_init(init);
5395+module_exit(fini);
5396diff -Nur --exclude '*.orig' 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
5397--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-28 03:35:45.000000000 +0200
5398+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-29 11:18:04.000000000 +0200
5399@@ -110,6 +110,9 @@
5400 len += sprintf(buffer + len, "[ASSURED] ");
5401 len += sprintf(buffer + len, "use=%u ",
5402 atomic_read(&conntrack->ct_general.use));
5403+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5404+ len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5405+#endif
5406 len += sprintf(buffer + len, "\n");
5407
5408 return len;
5409@@ -633,6 +636,7 @@
5410 EXPORT_SYMBOL(ip_conntrack_alter_reply);
5411 EXPORT_SYMBOL(ip_conntrack_destroyed);
5412 EXPORT_SYMBOL(ip_conntrack_get);
5413+EXPORT_SYMBOL(__ip_conntrack_confirm);
5414 EXPORT_SYMBOL(need_ip_conntrack);
5415 EXPORT_SYMBOL(ip_conntrack_helper_register);
5416 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5417diff -Nur --exclude '*.orig' 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
5418--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
5419+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c 2004-04-29 11:21:43.000000000 +0200
5420@@ -0,0 +1,360 @@
5421+/*
5422+ * talk extension for IP connection tracking.
5423+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5424+ *
5425+ * This program is free software; you can redistribute it and/or
5426+ * modify it under the terms of the GNU General Public License
5427+ * as published by the Free Software Foundation; either version
5428+ * 2 of the License, or (at your option) any later version.
5429+ **
5430+ * Module load syntax:
5431+ * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5432+ *
5433+ * talk=[0|1] disable|enable old talk support
5434+ * ntalk=[0|1] disable|enable ntalk support
5435+ * ntalk2=[0|1] disable|enable ntalk2 support
5436+ *
5437+ * The default is talk=1 ntalk=1 ntalk2=1
5438+ *
5439+ * The helper does not support simultaneous talk requests.
5440+ **
5441+ *
5442+ * ASCII art on talk protocols
5443+ *
5444+ *
5445+ * caller server callee server
5446+ * | \ /
5447+ * | \ /
5448+ * | \ /
5449+ * | /
5450+ * | / \
5451+ * 2 | 1 / \ 3
5452+ * caller client ----------- callee client
5453+ * 4
5454+ *
5455+ * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
5456+ * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5457+ * 3. callee client <-> caller server: LOOK_UP invitation
5458+ * 4. callee client <-> caller client: talk data channel
5459+ *
5460+ * [1]: M. Hunter, talk: a historical protocol for interactive communication
5461+ * draft-hunter-talk-00.txt
5462+ * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
5463+ */
5464+#include <linux/config.h>
5465+#include <linux/module.h>
5466+#include <linux/netfilter.h>
5467+#include <linux/ip.h>
5468+#include <net/checksum.h>
5469+#include <net/udp.h>
5470+
5471+#include <linux/netfilter_ipv4/lockhelp.h>
5472+#include <linux/netfilter_ipv4/ip_conntrack.h>
5473+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5474+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5475+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5476+
5477+/* Default all talk protocols are supported */
5478+static int talk = 1;
5479+static int ntalk = 1;
5480+static int ntalk2 = 1;
5481+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5482+MODULE_DESCRIPTION("talk connection tracking module");
5483+MODULE_LICENSE("GPL");
5484+#ifdef MODULE_PARM
5485+MODULE_PARM(talk, "i");
5486+MODULE_PARM_DESC(talk, "support (old) talk protocol");
5487+MODULE_PARM(ntalk, "i");
5488+MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5489+MODULE_PARM(ntalk2, "i");
5490+MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5491+#endif
5492+
5493+DECLARE_LOCK(ip_talk_lock);
5494+struct module *ip_conntrack_talk = THIS_MODULE;
5495+
5496+#if 0
5497+#define DEBUGP printk
5498+#else
5499+#define DEBUGP(format, args...)
5500+#endif
5501+
5502+static int talk_expect(struct ip_conntrack *ct);
5503+static int ntalk_expect(struct ip_conntrack *ct);
5504+
5505+static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
5506+
5507+static int talk_help_response(const struct iphdr *iph, size_t len,
5508+ struct ip_conntrack *ct,
5509+ enum ip_conntrack_info ctinfo,
5510+ int talk_port,
5511+ u_char mode,
5512+ u_char type,
5513+ u_char answer,
5514+ struct talk_addr *addr)
5515+{
5516+ int dir = CTINFO2DIR(ctinfo);
5517+ struct ip_conntrack_expect expect, *exp = &expect;
5518+ struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
5519+
5520+ DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
5521+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5522+ type, answer);
5523+
5524+ if (!(answer == SUCCESS && type == mode))
5525+ return NF_ACCEPT;
5526+
5527+ memset(&expect, 0, sizeof(expect));
5528+
5529+ if (type == ANNOUNCE) {
5530+
5531+ DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
5532+
5533+ /* update the talk info */
5534+ LOCK_BH(&ip_talk_lock);
5535+ exp_talk_info->port = htons(talk_port);
5536+
5537+ /* expect callee client -> caller server message */
5538+ exp->tuple = ((struct ip_conntrack_tuple)
5539+ { { ct->tuplehash[dir].tuple.src.ip,
5540+ { 0 } },
5541+ { ct->tuplehash[dir].tuple.dst.ip,
5542+ { .tcp = { htons(talk_port) } },
5543+ IPPROTO_UDP }});
5544+ exp->mask = ((struct ip_conntrack_tuple)
5545+ { { 0xFFFFFFFF, { 0 } },
5546+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
5547+
5548+ exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
5549+
5550+ DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
5551+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
5552+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
5553+
5554+ /* Ignore failure; should only happen with NAT */
5555+ ip_conntrack_expect_related(ct, &expect);
5556+ UNLOCK_BH(&ip_talk_lock);
5557+ }
5558+ if (type == LOOK_UP) {
5559+
5560+ DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
5561+
5562+ /* update the talk info */
5563+ LOCK_BH(&ip_talk_lock);
5564+ exp_talk_info->port = addr->ta_port;
5565+
5566+ /* expect callee client -> caller client connection */
5567+ exp->tuple = ((struct ip_conntrack_tuple)
5568+ { { ct->tuplehash[!dir].tuple.src.ip,
5569+ { 0 } },
5570+ { addr->ta_addr,
5571+ { addr->ta_port },
5572+ IPPROTO_TCP }});
5573+ exp->mask = ((struct ip_conntrack_tuple)
5574+ { { 0xFFFFFFFF, { 0 } },
5575+ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5576+
5577+ exp->expectfn = NULL;
5578+
5579+ DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
5580+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
5581+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
5582+
5583+ /* Ignore failure; should only happen with NAT */
5584+ ip_conntrack_expect_related(ct, &expect);
5585+ UNLOCK_BH(&ip_talk_lock);
5586+ }
5587+
5588+ return NF_ACCEPT;
5589+}
5590+
5591+/* FIXME: This should be in userspace. Later. */
5592+static int talk_help(const struct iphdr *iph, size_t len,
5593+ struct ip_conntrack *ct,
5594+ enum ip_conntrack_info ctinfo,
5595+ int talk_port,
5596+ u_char mode)
5597+{
5598+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
5599+ const char *data = (const char *)udph + sizeof(struct udphdr);
5600+ int dir = CTINFO2DIR(ctinfo);
5601+ size_t udplen;
5602+
5603+ DEBUGP("ip_ct_talk_help: help entered\n");
5604+
5605+ /* Until there's been traffic both ways, don't look in packets. */
5606+ if (ctinfo != IP_CT_ESTABLISHED
5607+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5608+ DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
5609+ return NF_ACCEPT;
5610+ }
5611+
5612+ /* Not whole UDP header? */
5613+ udplen = len - iph->ihl * 4;
5614+ if (udplen < sizeof(struct udphdr)) {
5615+ DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
5616+ return NF_ACCEPT;
5617+ }
5618+
5619+ /* Checksum invalid? Ignore. */
5620+ /* FIXME: Source route IP option packets --RR */
5621+ if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5622+ csum_partial((char *)udph, udplen, 0))) {
5623+ DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5624+ udph, udplen, NIPQUAD(iph->saddr),
5625+ NIPQUAD(iph->daddr));
5626+ return NF_ACCEPT;
5627+ }
5628+
5629+ DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5630+ NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
5631+
5632+ if (dir == IP_CT_DIR_ORIGINAL)
5633+ return NF_ACCEPT;
5634+
5635+ if (talk_port == TALK_PORT
5636+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
5637+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5638+ ((struct talk_response *)data)->type,
5639+ ((struct talk_response *)data)->answer,
5640+ &(((struct talk_response *)data)->addr));
5641+ else if (talk_port == NTALK_PORT
5642+ && ntalk
5643+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5644+ && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5645+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5646+ ((struct ntalk_response *)data)->type,
5647+ ((struct ntalk_response *)data)->answer,
5648+ &(((struct ntalk_response *)data)->addr));
5649+ else if (talk_port == NTALK_PORT
5650+ && ntalk2
5651+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5652+ && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5653+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5654+ ((struct ntalk2_response *)data)->type,
5655+ ((struct ntalk2_response *)data)->answer,
5656+ &(((struct ntalk2_response *)data)->addr));
5657+ else {
5658+ DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
5659+ (unsigned)udplen - sizeof(struct udphdr),
5660+ sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5661+ return NF_ACCEPT;
5662+ }
5663+}
5664+
5665+static int lookup_help(const struct iphdr *iph, size_t len,
5666+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5667+{
5668+ return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5669+}
5670+
5671+static int lookup_nhelp(const struct iphdr *iph, size_t len,
5672+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5673+{
5674+ return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5675+}
5676+
5677+static struct ip_conntrack_helper lookup_helpers[2] =
5678+ { { { NULL, NULL },
5679+ "talk", /* name */
5680+ 0, /* flags */
5681+ NULL, /* module */
5682+ 1, /* max_expected */
5683+ 240, /* timeout */
5684+ { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5685+ { 0, { 0 }, IPPROTO_UDP } },
5686+ { { 0, { 0xFFFF } }, /* mask */
5687+ { 0, { 0 }, 0xFFFF } },
5688+ lookup_help }, /* helper */
5689+ { { NULL, NULL },
5690+ "ntalk", /* name */
5691+ 0, /* flags */
5692+ NULL, /* module */
5693+ 1, /* max_expected */
5694+ 240, /* timeout */
5695+ { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5696+ { 0, { 0 }, IPPROTO_UDP } },
5697+ { { 0, { 0xFFFF } }, /* mask */
5698+ { 0, { 0 }, 0xFFFF } },
5699+ lookup_nhelp } /* helper */
5700+ };
5701+
5702+static int talk_expect(struct ip_conntrack *ct)
5703+{
5704+ DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5705+ WRITE_LOCK(&ip_conntrack_lock);
5706+ ct->helper = &lookup_helpers[0];
5707+ WRITE_UNLOCK(&ip_conntrack_lock);
5708+
5709+ return NF_ACCEPT; /* unused */
5710+}
5711+
5712+static int ntalk_expect(struct ip_conntrack *ct)
5713+{
5714+ DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5715+ WRITE_LOCK(&ip_conntrack_lock);
5716+ ct->helper = &lookup_helpers[1];
5717+ WRITE_UNLOCK(&ip_conntrack_lock);
5718+
5719+ return NF_ACCEPT; /* unused */
5720+}
5721+
5722+static int help(const struct iphdr *iph, size_t len,
5723+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5724+{
5725+ return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5726+}
5727+
5728+static int nhelp(const struct iphdr *iph, size_t len,
5729+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5730+{
5731+ return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5732+}
5733+
5734+static struct ip_conntrack_helper talk_helpers[2] =
5735+ { { { NULL, NULL },
5736+ "talk", /* name */
5737+ 0, /* flags */
5738+ THIS_MODULE, /* module */
5739+ 1, /* max_expected */
5740+ 240, /* timeout */
5741+ { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5742+ { 0, { 0 }, IPPROTO_UDP } },
5743+ { { 0, { 0xFFFF } }, /* mask */
5744+ { 0, { 0 }, 0xFFFF } },
5745+ help }, /* helper */
5746+ { { NULL, NULL },
5747+ "ntalk", /* name */
5748+ 0, /* flags */
5749+ THIS_MODULE, /* module */
5750+ 1, /* max_expected */
5751+ 240, /* timeout */
5752+ { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5753+ { 0, { 0 }, IPPROTO_UDP } },
5754+ { { 0, { 0xFFFF } }, /* mask */
5755+ { 0, { 0 }, 0xFFFF } },
5756+ nhelp } /* helper */
5757+ };
5758+
5759+static int __init init(void)
5760+{
5761+ if (talk > 0)
5762+ ip_conntrack_helper_register(&talk_helpers[0]);
5763+ if (ntalk > 0 || ntalk2 > 0)
5764+ ip_conntrack_helper_register(&talk_helpers[1]);
5765+
5766+ return 0;
5767+}
5768+
5769+static void __exit fini(void)
5770+{
5771+ if (talk > 0)
5772+ ip_conntrack_helper_unregister(&talk_helpers[0]);
5773+ if (ntalk > 0 || ntalk2 > 0)
5774+ ip_conntrack_helper_unregister(&talk_helpers[1]);
5775+}
5776+
5777+EXPORT_SYMBOL(ip_talk_lock);
5778+
5779+module_init(init);
5780+module_exit(fini);
384c1045 5781diff -Nur --exclude '*.orig' 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
5782--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
5783+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c 2004-04-29 11:18:00.000000000 +0200
5784@@ -0,0 +1,419 @@
5785+/*
5786+ * H.323 'brute force' extension for NAT alteration.
5787+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5788+ *
5789+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
5790+ * (http://www.coritel.it/projects/sofia/nat.html)
5791+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
5792+ * the unregistered helpers to the conntrack entries.
5793+ */
5794+
5795+
5796+#include <linux/module.h>
5797+#include <linux/netfilter.h>
5798+#include <linux/ip.h>
5799+#include <net/checksum.h>
5800+#include <net/tcp.h>
5801+
5802+#include <linux/netfilter_ipv4/lockhelp.h>
5803+#include <linux/netfilter_ipv4/ip_nat.h>
5804+#include <linux/netfilter_ipv4/ip_nat_helper.h>
5805+#include <linux/netfilter_ipv4/ip_nat_rule.h>
5806+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
5807+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5808+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
5809+
5810+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5811+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
5812+MODULE_LICENSE("GPL");
5813+
5814+DECLARE_LOCK_EXTERN(ip_h323_lock);
5815+struct module *ip_nat_h323 = THIS_MODULE;
5816+
5817+#if 0
5818+#define DEBUGP printk
5819+#else
5820+#define DEBUGP(format, args...)
5821+#endif
5822+
5823+/* FIXME: Time out? --RR */
5824+
5825+static unsigned int
5826+h225_nat_expected(struct sk_buff **pskb,
5827+ unsigned int hooknum,
5828+ struct ip_conntrack *ct,
5829+ struct ip_nat_info *info);
5830+
5831+static unsigned int h225_nat_help(struct ip_conntrack *ct,
5832+ struct ip_conntrack_expect *exp,
5833+ struct ip_nat_info *info,
5834+ enum ip_conntrack_info ctinfo,
5835+ unsigned int hooknum,
5836+ struct sk_buff **pskb);
5837+
5838+static struct ip_nat_helper h245 =
5839+ { { NULL, NULL },
5840+ "H.245", /* name */
5841+ 0, /* flags */
5842+ NULL, /* module */
5843+ { { 0, { 0 } }, /* tuple */
5844+ { 0, { 0 }, IPPROTO_TCP } },
5845+ { { 0, { 0xFFFF } }, /* mask */
5846+ { 0, { 0 }, 0xFFFF } },
5847+ h225_nat_help, /* helper */
5848+ h225_nat_expected /* expectfn */
5849+ };
5850+
5851+static unsigned int
5852+h225_nat_expected(struct sk_buff **pskb,
5853+ unsigned int hooknum,
5854+ struct ip_conntrack *ct,
5855+ struct ip_nat_info *info)
5856+{
5857+ struct ip_nat_multi_range mr;
5858+ u_int32_t newdstip, newsrcip, newip;
5859+ u_int16_t port;
5860+ struct ip_ct_h225_expect *exp_info;
5861+ struct ip_ct_h225_master *master_info;
5862+ struct ip_conntrack *master = master_ct(ct);
5863+ unsigned int is_h225, ret;
5864+
5865+ IP_NF_ASSERT(info);
5866+ IP_NF_ASSERT(master);
5867+
5868+ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
5869+
5870+ DEBUGP("h225_nat_expected: We have a connection!\n");
5871+ master_info = &ct->master->expectant->help.ct_h225_info;
5872+ exp_info = &ct->master->help.exp_h225_info;
5873+
5874+ LOCK_BH(&ip_h323_lock);
5875+
5876+ DEBUGP("master: ");
5877+ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5878+ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
5879+ DEBUGP("conntrack: ");
5880+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5881+ if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
5882+ /* Make connection go to the client. */
5883+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5884+ newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5885+ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
5886+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
5887+ } else {
5888+ /* Make the connection go to the server */
5889+ newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
5890+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5891+ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
5892+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
5893+ }
5894+ port = exp_info->port;
5895+ is_h225 = master_info->is_h225 == H225_PORT;
5896+ UNLOCK_BH(&ip_h323_lock);
5897+
5898+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
5899+ newip = newsrcip;
5900+ else
5901+ newip = newdstip;
5902+
5903+ DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
5904+
5905+ mr.rangesize = 1;
5906+ /* We don't want to manip the per-protocol, just the IPs... */
5907+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
5908+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
5909+
5910+ /* ... unless we're doing a MANIP_DST, in which case, make
5911+ sure we map to the correct port */
5912+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
5913+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
5914+ mr.range[0].min = mr.range[0].max
5915+ = ((union ip_conntrack_manip_proto)
5916+ { .tcp = { port } });
5917+ }
5918+
5919+ ret = ip_nat_setup_info(ct, &mr, hooknum);
5920+
5921+ if (is_h225) {
5922+ DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
5923+ /* NAT expectfn called with ip_nat_lock write-locked */
5924+ info->helper = &h245;
5925+ }
5926+ return ret;
5927+}
5928+
5929+static int h323_signal_address_fixup(struct ip_conntrack *ct,
5930+ struct sk_buff **pskb,
5931+ enum ip_conntrack_info ctinfo)
5932+{
5933+ struct iphdr *iph = (*pskb)->nh.iph;
5934+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
5935+ char *data = (char *) tcph + tcph->doff * 4;
5936+ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
5937+ u_int32_t datalen = tcplen - tcph->doff*4;
5938+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
5939+ u_int32_t newip;
5940+ u_int16_t port;
5941+ int i;
5942+
5943+ MUST_BE_LOCKED(&ip_h323_lock);
5944+
5945+ DEBUGP("h323_signal_address_fixup: %s %s\n",
5946+ between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5947+ ? "yes" : "no",
5948+ between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5949+ ? "yes" : "no");
5950+ if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5951+ || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
5952+ return 1;
5953+
5954+ DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
5955+ info->offset[IP_CT_DIR_ORIGINAL],
5956+ info->offset[IP_CT_DIR_REPLY],
5957+ tcplen);
5958+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5959+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5960+
5961+ for (i = 0; i < IP_CT_DIR_MAX; i++) {
5962+ DEBUGP("h323_signal_address_fixup: %s %s\n",
5963+ info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
5964+ i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
5965+ if (!between(info->seq[i], ntohl(tcph->seq),
5966+ ntohl(tcph->seq) + datalen))
5967+ continue;
5968+ if (!between(info->seq[i] + 6, ntohl(tcph->seq),
5969+ ntohl(tcph->seq) + datalen)) {
5970+ /* Partial retransmisison. It's a cracker being funky. */
5971+ if (net_ratelimit()) {
5972+ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
5973+ info->seq[i],
5974+ ntohl(tcph->seq),
5975+ ntohl(tcph->seq) + datalen);
5976+ }
5977+ return 0;
5978+ }
5979+
5980+ /* Change address inside packet to match way we're mapping
5981+ this connection. */
5982+ if (i == IP_CT_DIR_ORIGINAL) {
5983+ newip = ct->tuplehash[!info->dir].tuple.dst.ip;
5984+ port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
5985+ } else {
5986+ newip = ct->tuplehash[!info->dir].tuple.src.ip;
5987+ port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
5988+ }
5989+
5990+ DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
5991+ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
5992+ NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
5993+ ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
5994+
5995+ /* Modify the packet */
5996+ *(u_int32_t *)(data + info->offset[i]) = newip;
5997+ *(u_int16_t *)(data + info->offset[i] + 4) = port;
5998+
5999+ DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6000+ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6001+ NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6002+ ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6003+ }
6004+
6005+ /* fix checksum information */
6006+
6007+ (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6008+ datalen, 0);
6009+
6010+ tcph->check = 0;
6011+ tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6012+ csum_partial((char *)tcph, tcph->doff*4,
6013+ (*pskb)->csum));
6014+ ip_send_check(iph);
6015+
6016+ return 1;
6017+}
6018+
6019+static int h323_data_fixup(struct ip_ct_h225_expect *info,
6020+ struct ip_conntrack *ct,
6021+ struct sk_buff **pskb,
6022+ enum ip_conntrack_info ctinfo,
6023+ struct ip_conntrack_expect *expect)
6024+{
6025+ u_int32_t newip;
6026+ u_int16_t port;
6027+ struct ip_conntrack_tuple newtuple;
6028+ struct iphdr *iph = (*pskb)->nh.iph;
6029+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6030+ char *data = (char *) tcph + tcph->doff * 4;
6031+ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6032+ struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6033+ int is_h225;
6034+
6035+ MUST_BE_LOCKED(&ip_h323_lock);
6036+ DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6037+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6038+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6039+
6040+ if (!between(expect->seq + 6, ntohl(tcph->seq),
6041+ ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6042+ /* Partial retransmisison. It's a cracker being funky. */
6043+ if (net_ratelimit()) {
6044+ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6045+ expect->seq,
6046+ ntohl(tcph->seq),
6047+ ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6048+ }
6049+ return 0;
6050+ }
6051+
6052+ /* Change address inside packet to match way we're mapping
6053+ this connection. */
6054+ if (info->dir == IP_CT_DIR_REPLY) {
6055+ /* Must be where client thinks server is */
6056+ newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6057+ /* Expect something from client->server */
6058+ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6059+ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6060+ } else {
6061+ /* Must be where server thinks client is */
6062+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6063+ /* Expect something from server->client */
6064+ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6065+ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6066+ }
6067+
6068+ is_h225 = (master_info->is_h225 == H225_PORT);
6069+
6070+ if (is_h225) {
6071+ newtuple.dst.protonum = IPPROTO_TCP;
6072+ newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6073+ } else {
6074+ newtuple.dst.protonum = IPPROTO_UDP;
6075+ newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6076+ }
6077+
6078+ /* Try to get same port: if not, try to change it. */
6079+ for (port = ntohs(info->port); port != 0; port++) {
6080+ if (is_h225)
6081+ newtuple.dst.u.tcp.port = htons(port);
6082+ else
6083+ newtuple.dst.u.udp.port = htons(port);
6084+
6085+ if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6086+ break;
6087+ }
6088+ if (port == 0) {
6089+ DEBUGP("h323_data_fixup: no free port found!\n");
6090+ return 0;
6091+ }
6092+
6093+ port = htons(port);
6094+
6095+ DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6096+ NIPQUAD(*((u_int32_t *)(data + info->offset))),
6097+ ntohs(*((u_int16_t *)(data + info->offset + 4))));
6098+
6099+ /* Modify the packet */
6100+ *(u_int32_t *)(data + info->offset) = newip;
6101+ *(u_int16_t *)(data + info->offset + 4) = port;
6102+
6103+ DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6104+ NIPQUAD(*((u_int32_t *)(data + info->offset))),
6105+ ntohs(*((u_int16_t *)(data + info->offset + 4))));
6106+
6107+ /* fix checksum information */
6108+ /* FIXME: usually repeated multiple times in the case of H.245! */
6109+
6110+ (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6111+ tcplen - tcph->doff*4, 0);
6112+
6113+ tcph->check = 0;
6114+ tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6115+ csum_partial((char *)tcph, tcph->doff*4,
6116+ (*pskb)->csum));
6117+ ip_send_check(iph);
6118+
6119+ return 1;
6120+}
6121+
6122+static unsigned int h225_nat_help(struct ip_conntrack *ct,
6123+ struct ip_conntrack_expect *exp,
6124+ struct ip_nat_info *info,
6125+ enum ip_conntrack_info ctinfo,
6126+ unsigned int hooknum,
6127+ struct sk_buff **pskb)
6128+{
6129+ int dir;
6130+ struct ip_ct_h225_expect *exp_info;
6131+
6132+ /* Only mangle things once: original direction in POST_ROUTING
6133+ and reply direction on PRE_ROUTING. */
6134+ dir = CTINFO2DIR(ctinfo);
6135+ DEBUGP("nat_h323: dir %s at hook %s\n",
6136+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6137+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6138+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6139+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6140+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6141+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6142+ DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6143+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6144+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6145+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6146+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6147+ return NF_ACCEPT;
6148+ }
6149+
6150+ if (!exp) {
6151+ LOCK_BH(&ip_h323_lock);
6152+ if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6153+ UNLOCK_BH(&ip_h323_lock);
6154+ return NF_DROP;
6155+ }
6156+ UNLOCK_BH(&ip_h323_lock);
6157+ return NF_ACCEPT;
6158+ }
6159+
6160+ exp_info = &exp->help.exp_h225_info;
6161+
6162+ LOCK_BH(&ip_h323_lock);
6163+ if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6164+ UNLOCK_BH(&ip_h323_lock);
6165+ return NF_DROP;
6166+ }
6167+ UNLOCK_BH(&ip_h323_lock);
6168+
6169+ return NF_ACCEPT;
6170+}
6171+
6172+static struct ip_nat_helper h225 =
6173+ { { NULL, NULL },
6174+ "H.225", /* name */
6175+ IP_NAT_HELPER_F_ALWAYS, /* flags */
6176+ THIS_MODULE, /* module */
6177+ { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
6178+ { 0, { 0 }, IPPROTO_TCP } },
6179+ { { 0, { .tcp = { 0xFFFF } } }, /* mask */
6180+ { 0, { 0 }, 0xFFFF } },
6181+ h225_nat_help, /* helper */
6182+ h225_nat_expected /* expectfn */
6183+ };
6184+
6185+static int __init init(void)
6186+{
6187+ int ret;
6188+
6189+ ret = ip_nat_helper_register(&h225);
6190+
6191+ if (ret != 0)
6192+ printk("ip_nat_h323: cannot initialize the module!\n");
6193+
6194+ return ret;
6195+}
6196+
6197+static void __exit fini(void)
6198+{
6199+ ip_nat_helper_unregister(&h225);
6200+}
6201+
6202+module_init(init);
6203+module_exit(fini);
6204diff -Nur --exclude '*.orig' 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
6205--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6206+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c 2004-04-29 11:19:01.000000000 +0200
6207@@ -0,0 +1,350 @@
6208+/* MMS extension for TCP NAT alteration.
6209+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6210+ * based on ip_nat_ftp.c and ip_nat_irc.c
6211+ *
6212+ * ip_nat_mms.c v0.3 2002-09-22
6213+ *
6214+ * This program is free software; you can redistribute it and/or
6215+ * modify it under the terms of the GNU General Public License
6216+ * as published by the Free Software Foundation; either version
6217+ * 2 of the License, or (at your option) any later version.
6218+ *
6219+ * Module load syntax:
6220+ * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6221+ *
6222+ * Please give the ports of all MMS servers You wish to connect to.
6223+ * If you don't specify ports, the default will be TCP port 1755.
6224+ *
6225+ * More info on MMS protocol, firewalls and NAT:
6226+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6227+ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6228+ *
6229+ * The SDP project people are reverse-engineering MMS:
6230+ * http://get.to/sdp
6231+ */
6232+
6233+/* FIXME: issue with UDP & fragmentation with this URL:
6234+ http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6235+ may be related to out-of-order first packets:
6236+ basically the expectation is set up correctly, then the server sends
6237+ a first UDP packet which is fragmented plus arrives out-of-order.
6238+ the MASQUERADING firewall with ip_nat_mms loaded responds with
6239+ an ICMP unreachable back to the server */
6240+
6241+#include <linux/module.h>
6242+#include <linux/netfilter_ipv4.h>
6243+#include <linux/ip.h>
6244+#include <linux/tcp.h>
6245+#include <net/tcp.h>
6246+#include <linux/netfilter_ipv4/ip_nat.h>
6247+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6248+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6249+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6250+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6251+
6252+#if 0
6253+#define DEBUGP printk
6254+#define DUMP_BYTES(address, counter) \
6255+({ \
6256+ int temp_counter; \
6257+ for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6258+ DEBUGP("%u ", (u8)*(address+temp_counter)); \
6259+ }; \
6260+ DEBUGP("\n"); \
6261+})
6262+#else
6263+#define DEBUGP(format, args...)
6264+#define DUMP_BYTES(address, counter)
6265+#endif
6266+
6267+#define MAX_PORTS 8
6268+static int ports[MAX_PORTS];
6269+static int ports_c = 0;
6270+
6271+#ifdef MODULE_PARM
6272+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6273+#endif
6274+
6275+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6276+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6277+MODULE_LICENSE("GPL");
6278+
6279+DECLARE_LOCK_EXTERN(ip_mms_lock);
6280+
6281+/* FIXME: Time out? --RR */
6282+
6283+static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6284+ struct ip_conntrack *ct,
6285+ struct sk_buff **pskb,
6286+ enum ip_conntrack_info ctinfo,
6287+ struct ip_conntrack_expect *expect)
6288+{
6289+ u_int32_t newip;
6290+ struct ip_conntrack_tuple t;
6291+ struct iphdr *iph = (*pskb)->nh.iph;
6292+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6293+ char *data = (char *)tcph + tcph->doff * 4;
6294+ int i, j, k, port;
6295+ u_int16_t mms_proto;
6296+
6297+ u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6298+ u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6299+ u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6300+
6301+ int zero_padding;
6302+
6303+ char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6304+ char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6305+ char proto_string[6];
6306+
6307+ MUST_BE_LOCKED(&ip_mms_lock);
6308+
6309+ /* what was the protocol again ? */
6310+ mms_proto = expect->tuple.dst.protonum;
6311+ sprintf(proto_string, "%u", mms_proto);
6312+
6313+ DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6314+ expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6315+ mms_proto == IPPROTO_UDP ? "UDP"
6316+ : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6317+
6318+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6319+
6320+ /* Alter conntrack's expectations. */
6321+ t = expect->tuple;
6322+ t.dst.ip = newip;
6323+ for (port = ct_mms_info->port; port != 0; port++) {
6324+ t.dst.u.tcp.port = htons(port);
6325+ if (ip_conntrack_change_expect(expect, &t) == 0) {
6326+ DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6327+ break;
6328+ }
6329+ }
6330+
6331+ if(port == 0)
6332+ return 0;
6333+
6334+ sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6335+ NIPQUAD(newip),
6336+ expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6337+ : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6338+ port);
6339+ DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6340+
6341+ memset(unicode_buffer, 0, sizeof(char)*75);
6342+
6343+ for (i=0; i<strlen(buffer); ++i)
6344+ *(unicode_buffer+i*2)=*(buffer+i);
6345+
6346+ DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6347+ DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6348+ DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6349+
6350+ /* add end of packet to it */
6351+ for (j=0; j<ct_mms_info->padding; ++j) {
6352+ DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6353+ i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6354+ *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6355+ }
6356+
6357+ /* pad with zeroes at the end ? see explanation of weird math below */
6358+ zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6359+ for (k=0; k<zero_padding; ++k)
6360+ *(unicode_buffer+i*2+j+k)= (char)0;
6361+
6362+ DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6363+ DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6364+ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6365+
6366+ /* explanation, before I forget what I did:
6367+ strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6368+ divide by 8 and add 3 to compute the mms_chunkLenLM field,
6369+ but note that things may have to be padded with zeroes to align by 8
6370+ bytes, hence we add 7 and divide by 8 to get the correct length */
6371+ *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6372+ *mms_chunkLenLV = *mms_chunkLenLM+2;
6373+ *mms_messageLength = *mms_chunkLenLV*8;
6374+
6375+ DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6376+ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6377+
6378+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6379+ expect->seq - ntohl(tcph->seq),
6380+ ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6381+ strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6382+ DUMP_BYTES(unicode_buffer, 60);
6383+
6384+ return 1;
6385+}
6386+
6387+static unsigned int
6388+mms_nat_expected(struct sk_buff **pskb,
6389+ unsigned int hooknum,
6390+ struct ip_conntrack *ct,
6391+ struct ip_nat_info *info)
6392+{
6393+ struct ip_nat_multi_range mr;
6394+ u_int32_t newdstip, newsrcip, newip;
6395+
6396+ struct ip_conntrack *master = master_ct(ct);
6397+
6398+ IP_NF_ASSERT(info);
6399+ IP_NF_ASSERT(master);
6400+
6401+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6402+
6403+ DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6404+
6405+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6406+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6407+ DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6408+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6409+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6410+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6411+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
6412+
6413+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6414+ newip = newsrcip;
6415+ else
6416+ newip = newdstip;
6417+
6418+ DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6419+
6420+ mr.rangesize = 1;
6421+ /* We don't want to manip the per-protocol, just the IPs. */
6422+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6423+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
6424+
6425+ return ip_nat_setup_info(ct, &mr, hooknum);
6426+}
6427+
6428+
6429+static unsigned int mms_nat_help(struct ip_conntrack *ct,
6430+ struct ip_conntrack_expect *exp,
6431+ struct ip_nat_info *info,
6432+ enum ip_conntrack_info ctinfo,
6433+ unsigned int hooknum,
6434+ struct sk_buff **pskb)
6435+{
6436+ struct iphdr *iph = (*pskb)->nh.iph;
6437+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6438+ unsigned int datalen;
6439+ int dir;
6440+ struct ip_ct_mms_expect *ct_mms_info;
6441+
6442+ if (!exp)
6443+ DEBUGP("ip_nat_mms: no exp!!");
6444+
6445+ ct_mms_info = &exp->help.exp_mms_info;
6446+
6447+ /* Only mangle things once: original direction in POST_ROUTING
6448+ and reply direction on PRE_ROUTING. */
6449+ dir = CTINFO2DIR(ctinfo);
6450+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6451+ ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6452+ DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6453+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6454+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6455+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6456+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6457+ return NF_ACCEPT;
6458+ }
6459+ DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6460+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6461+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6462+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6463+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6464+
6465+ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6466+
6467+ DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6468+ exp->seq + ct_mms_info->len,
6469+ ntohl(tcph->seq),
6470+ ntohl(tcph->seq) + datalen);
6471+
6472+ LOCK_BH(&ip_mms_lock);
6473+ /* Check wether the whole IP/proto/port pattern is carried in the payload */
6474+ if (between(exp->seq + ct_mms_info->len,
6475+ ntohl(tcph->seq),
6476+ ntohl(tcph->seq) + datalen)) {
6477+ if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6478+ UNLOCK_BH(&ip_mms_lock);
6479+ return NF_DROP;
6480+ }
6481+ } else {
6482+ /* Half a match? This means a partial retransmisison.
6483+ It's a cracker being funky. */
6484+ if (net_ratelimit()) {
6485+ printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6486+ exp->seq, ct_mms_info->len,
6487+ ntohl(tcph->seq),
6488+ ntohl(tcph->seq) + datalen);
6489+ }
6490+ UNLOCK_BH(&ip_mms_lock);
6491+ return NF_DROP;
6492+ }
6493+ UNLOCK_BH(&ip_mms_lock);
6494+
6495+ return NF_ACCEPT;
6496+}
6497+
6498+static struct ip_nat_helper mms[MAX_PORTS];
6499+static char mms_names[MAX_PORTS][10];
6500+
6501+/* Not __exit: called from init() */
6502+static void fini(void)
6503+{
6504+ int i;
6505+
6506+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6507+ DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6508+ ip_nat_helper_unregister(&mms[i]);
6509+ }
6510+}
6511+
6512+static int __init init(void)
6513+{
6514+ int i, ret = 0;
6515+ char *tmpname;
6516+
6517+ if (ports[0] == 0)
6518+ ports[0] = MMS_PORT;
6519+
6520+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6521+
6522+ memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6523+
6524+ mms[i].tuple.dst.protonum = IPPROTO_TCP;
6525+ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6526+ mms[i].mask.dst.protonum = 0xFFFF;
6527+ mms[i].mask.src.u.tcp.port = 0xFFFF;
6528+ mms[i].help = mms_nat_help;
6529+ mms[i].me = THIS_MODULE;
6530+ mms[i].flags = 0;
6531+ mms[i].expect = mms_nat_expected;
6532+
6533+ tmpname = &mms_names[i][0];
6534+ if (ports[i] == MMS_PORT)
6535+ sprintf(tmpname, "mms");
6536+ else
6537+ sprintf(tmpname, "mms-%d", i);
6538+ mms[i].name = tmpname;
6539+
6540+ DEBUGP("ip_nat_mms: register helper for port %d\n",
6541+ ports[i]);
6542+ ret = ip_nat_helper_register(&mms[i]);
6543+
6544+ if (ret) {
6545+ printk("ip_nat_mms: error registering "
6546+ "helper for port %d\n", ports[i]);
6547+ fini();
6548+ return ret;
6549+ }
6550+ ports_c++;
6551+ }
6552+
6553+ return ret;
6554+}
6555+
6556+module_init(init);
6557+module_exit(fini);
6558diff -Nur --exclude '*.orig' 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
6559--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
6560+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c 2004-04-29 11:19:53.000000000 +0200
6561@@ -0,0 +1,249 @@
6562+/* Quake3 extension for UDP NAT alteration.
6563+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6564+ * based on ip_nat_ftp.c and ip_nat_tftp.c
6565+ *
6566+ * ip_nat_quake3.c v0.0.3 2002-08-31
6567+ *
6568+ * This program is free software; you can redistribute it and/or
6569+ * modify it under the terms of the GNU General Public License
6570+ * as published by the Free Software Foundation; either version
6571+ * 2 of the License, or (at your option) any later version.
6572+ *
6573+ * Module load syntax:
6574+ * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6575+ *
6576+ * please give the ports of all Quake3 master servers You wish to
6577+ * connect to. If you don't specify ports, the default will be UDP
6578+ * port 27950.
6579+ *
6580+ * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6581+ *
6582+ * Notes:
6583+ * - If you're one of those people who would try anything to lower
6584+ * latency while playing Quake (and who isn't :-) ), you may want to
6585+ * consider not loading ip_nat_quake3 at all and just MASQUERADE all
6586+ * outgoing UDP traffic.
6587+ * This will make ip_conntrack_quake3 add the necessary expectations,
6588+ * but there will be no overhead for client->server UDP streams. If
6589+ * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6590+ * hook for every packet in the client->server UDP stream.
6591+ * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6592+ * The IP addresses in the master connection payload (=IP addresses
6593+ * of Quake servers) have no relation with the master server so
6594+ * DNAT'ing the master connection to a server should not change the
6595+ * expected connections.
6596+ * - Not tested due to lack of equipment:
6597+ * - multiple Quake3 clients behind one MASQUERADE gateway
6598+ * - what if Quake3 client is running on router too
6599+ */
6600+
6601+#include <linux/module.h>
6602+#include <linux/netfilter_ipv4.h>
6603+#include <linux/ip.h>
6604+#include <linux/udp.h>
6605+
6606+#include <linux/netfilter.h>
6607+#include <linux/netfilter_ipv4/ip_tables.h>
6608+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6609+#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6610+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6611+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6612+
6613+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6614+MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6615+MODULE_LICENSE("GPL");
6616+
6617+#define MAX_PORTS 8
6618+
6619+static int ports[MAX_PORTS];
6620+static int ports_c = 0;
6621+#ifdef MODULE_PARM
6622+MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
6623+MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
6624+#endif
6625+
6626+/* Quake3 master server reply will add > 100 expectations per reply packet; when
6627+ doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
6628+#if 0
6629+#define DEBUGP printk
6630+#else
6631+#define DEBUGP(format, args...)
6632+#endif
6633+
6634+static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
6635+
6636+static unsigned int
6637+quake3_nat_help(struct ip_conntrack *ct,
6638+ struct ip_conntrack_expect *exp,
6639+ struct ip_nat_info *info,
6640+ enum ip_conntrack_info ctinfo,
6641+ unsigned int hooknum,
6642+ struct sk_buff **pskb)
6643+{
6644+ struct iphdr *iph = (*pskb)->nh.iph;
6645+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
6646+ struct ip_conntrack_tuple repl;
6647+ int dir = CTINFO2DIR(ctinfo);
6648+ int i;
6649+
6650+ DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
6651+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6652+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6653+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6654+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6655+ );
6656+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6657+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6658+
6659+ /* Only mangle things once: original direction in POST_ROUTING
6660+ and reply direction on PRE_ROUTING. */
6661+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6662+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6663+ DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
6664+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6665+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6666+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6667+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6668+ return NF_ACCEPT;
6669+ }
6670+
6671+ if (!exp) {
6672+ DEBUGP("no conntrack expectation to modify\n");
6673+ return NF_ACCEPT;
6674+ }
6675+
6676+ if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
6677+ for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
6678+ i+6 < ntohs(udph->len);
6679+ i+=7) {
6680+ DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
6681+ i, ntohs(udph->len),
6682+ NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
6683+ ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
6684+
6685+ memset(&repl, 0, sizeof(repl));
6686+
6687+ repl.dst.protonum = IPPROTO_UDP;
6688+ repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6689+ repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
6690+ repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
6691+
6692+ ip_conntrack_change_expect(exp, &repl);
6693+ }
6694+ }
6695+ return NF_ACCEPT;
6696+}
6697+
6698+static unsigned int
6699+quake3_nat_expected(struct sk_buff **pskb,
6700+ unsigned int hooknum,
6701+ struct ip_conntrack *ct,
6702+ struct ip_nat_info *info)
6703+{
6704+ const struct ip_conntrack *master = ct->master->expectant;
6705+ struct ip_nat_multi_range mr;
6706+ u_int32_t newsrcip, newdstip, newip;
6707+#if 0
6708+ const struct ip_conntrack_tuple *repl =
6709+ &master->tuplehash[IP_CT_DIR_REPLY].tuple;
6710+ struct iphdr *iph = (*pskb)->nh.iph;
6711+ struct udphdr *udph = (void *)iph + iph->ihl*4;
6712+#endif
6713+
6714+ DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
6715+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6716+
6717+ IP_NF_ASSERT(info);
6718+ IP_NF_ASSERT(master);
6719+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6720+
6721+ newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6722+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6723+
6724+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
6725+ newip = newsrcip;
6726+ DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6727+ "newsrc: %u.%u.%u.%u\n",
6728+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6729+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6730+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6731+ NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6732+ NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6733+ NIPQUAD(newip));
6734+
6735+ } else {
6736+ newip = newdstip;
6737+ DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6738+ "newdst: %u.%u.%u.%u\n",
6739+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6740+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6741+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6742+ NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6743+ NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6744+ NIPQUAD(newip));
6745+ }
6746+
6747+ mr.rangesize = 1;
6748+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6749+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
6750+
6751+ return ip_nat_setup_info(ct,&mr,hooknum);
6752+}
6753+
6754+static struct ip_nat_helper quake3[MAX_PORTS];
6755+static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
6756+
6757+static void fini(void)
6758+{
6759+ int i;
6760+
6761+ for (i = 0 ; i < ports_c; i++) {
6762+ DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
6763+ ip_nat_helper_unregister(&quake3[i]);
6764+ }
6765+}
6766+
6767+static int __init init(void)
6768+ {
6769+ int i, ret = 0;
6770+ char *tmpname;
6771+
6772+ if (!ports[0])
6773+ ports[0] = QUAKE3_MASTER_PORT;
6774+
6775+ for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6776+ memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
6777+
6778+ quake3[i].tuple.dst.protonum = IPPROTO_UDP;
6779+ quake3[i].tuple.src.u.udp.port = htons(ports[i]);
6780+ quake3[i].mask.dst.protonum = 0xFFFF;
6781+ quake3[i].mask.src.u.udp.port = 0xFFFF;
6782+ quake3[i].help = quake3_nat_help;
6783+ quake3[i].flags = 0;
6784+ quake3[i].me = THIS_MODULE;
6785+ quake3[i].expect = quake3_nat_expected;
6786+
6787+ tmpname = &quake3_names[i][0];
6788+ if (ports[i] == QUAKE3_MASTER_PORT)
6789+ sprintf(tmpname, "quake3");
6790+ else
6791+ sprintf(tmpname, "quake3-%d", i);
6792+ quake3[i].name = tmpname;
6793+
6794+ DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
6795+ ports[i], quake3[i].name);
6796+ ret = ip_nat_helper_register(&quake3[i]);
6797+
6798+ if (ret) {
6799+ printk("ip_nat_quake3: unable to register helper for port %d\n",
6800+ ports[i]);
6801+ fini();
6802+ return ret;
6803+ }
6804+ ports_c++;
6805+ }
6806+ return ret;
6807+ }
6808+
6809+module_init(init);
6810+module_exit(fini);
6811diff -Nur --exclude '*.orig' 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
6812--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
6813+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c 2004-04-29 11:20:13.000000000 +0200
6814@@ -0,0 +1,621 @@
6815+/*
6816+ * RTSP extension for TCP NAT alteration
6817+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
6818+ * based on ip_nat_irc.c
6819+ *
6820+ * This program is free software; you can redistribute it and/or
6821+ * modify it under the terms of the GNU General Public License
6822+ * as published by the Free Software Foundation; either version
6823+ * 2 of the License, or (at your option) any later version.
6824+ *
6825+ * Module load syntax:
6826+ * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6827+ * stunaddr=<address>
6828+ * destaction=[auto|strip|none]
6829+ *
6830+ * If no ports are specified, the default will be port 554 only.
6831+ *
6832+ * stunaddr specifies the address used to detect that a client is using STUN.
6833+ * If this address is seen in the destination parameter, it is assumed that
6834+ * the client has already punched a UDP hole in the firewall, so we don't
6835+ * mangle the client_port. If none is specified, it is autodetected. It
6836+ * only needs to be set if you have multiple levels of NAT. It should be
6837+ * set to the external address that the STUN clients detect. Note that in
6838+ * this case, it will not be possible for clients to use UDP with servers
6839+ * between the NATs.
6840+ *
6841+ * If no destaction is specified, auto is used.
6842+ * destaction=auto: strip destination parameter if it is not stunaddr.
6843+ * destaction=strip: always strip destination parameter (not recommended).
6844+ * destaction=none: do not touch destination parameter (not recommended).
6845+ */
6846+
6847+#include <linux/module.h>
6848+#include <linux/netfilter_ipv4.h>
6849+#include <linux/ip.h>
6850+#include <linux/tcp.h>
6851+#include <linux/kernel.h>
6852+#include <net/tcp.h>
6853+#include <linux/netfilter_ipv4/ip_nat.h>
6854+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6855+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6856+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6857+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6858+
6859+#include <linux/inet.h>
6860+#include <linux/ctype.h>
6861+#define NF_NEED_STRNCASECMP
6862+#define NF_NEED_STRTOU16
6863+#include <linux/netfilter_helpers.h>
6864+#define NF_NEED_MIME_NEXTLINE
6865+#include <linux/netfilter_mime.h>
6866+
6867+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
6868+#ifdef IP_NF_RTSP_DEBUG
6869+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
6870+#else
6871+#define DEBUGP(fmt, args...)
6872+#endif
6873+
6874+#define MAX_PORTS 8
6875+#define DSTACT_AUTO 0
6876+#define DSTACT_STRIP 1
6877+#define DSTACT_NONE 2
6878+
6879+static int ports[MAX_PORTS];
6880+static char* stunaddr = NULL;
6881+static char* destaction = NULL;
6882+
6883+static int num_ports = 0;
6884+static u_int32_t extip = 0;
6885+static int dstact = 0;
6886+
6887+MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
6888+MODULE_DESCRIPTION("RTSP network address translation module");
6889+MODULE_LICENSE("GPL");
6890+#ifdef MODULE_PARM
6891+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6892+MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
6893+MODULE_PARM(stunaddr, "s");
6894+MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
6895+MODULE_PARM(destaction, "s");
6896+MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
6897+#endif
6898+
6899+/* protects rtsp part of conntracks */
6900+DECLARE_LOCK_EXTERN(ip_rtsp_lock);
6901+
6902+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
6903+
6904+/*** helper functions ***/
6905+
6906+static void
6907+get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
6908+{
6909+ struct iphdr* iph = (struct iphdr*)skb->nh.iph;
6910+ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
6911+
6912+ *pptcpdata = (char*)tcph + tcph->doff*4;
6913+ *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
6914+}
6915+
6916+/*** nat functions ***/
6917+
6918+/*
6919+ * Mangle the "Transport:" header:
6920+ * - Replace all occurences of "client_port=<spec>"
6921+ * - Handle destination parameter
6922+ *
6923+ * In:
6924+ * ct, ctinfo = conntrack context
6925+ * pskb = packet
6926+ * tranoff = Transport header offset from TCP data
6927+ * tranlen = Transport header length (incl. CRLF)
6928+ * rport_lo = replacement low port (host endian)
6929+ * rport_hi = replacement high port (host endian)
6930+ *
6931+ * Returns packet size difference.
6932+ *
6933+ * Assumes that a complete transport header is present, ending with CR or LF
6934+ */
6935+static int
6936+rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
6937+ struct ip_conntrack_expect* exp,
6938+ struct sk_buff** pskb, uint tranoff, uint tranlen)
6939+{
6940+ char* ptcp;
6941+ uint tcplen;
6942+ char* ptran;
6943+ char rbuf1[16]; /* Replacement buffer (one port) */
6944+ uint rbuf1len; /* Replacement len (one port) */
6945+ char rbufa[16]; /* Replacement buffer (all ports) */
6946+ uint rbufalen; /* Replacement len (all ports) */
6947+ u_int32_t newip;
6948+ u_int16_t loport, hiport;
6949+ uint off = 0;
6950+ uint diff; /* Number of bytes we removed */
6951+
6952+ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
6953+ struct ip_conntrack_tuple t;
6954+
6955+ char szextaddr[15+1];
6956+ uint extaddrlen;
6957+ int is_stun;
6958+
6959+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
6960+ ptran = ptcp+tranoff;
6961+
6962+ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
6963+ tranlen < 10 || !iseol(ptran[tranlen-1]) ||
6964+ nf_strncasecmp(ptran, "Transport:", 10) != 0)
6965+ {
6966+ INFOP("sanity check failed\n");
6967+ return 0;
6968+ }
6969+ off += 10;
6970+ SKIP_WSPACE(ptcp+tranoff, tranlen, off);
6971+
6972+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6973+ t = exp->tuple;
6974+ t.dst.ip = newip;
6975+
6976+ extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
6977+ : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
6978+ DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
6979+
6980+ rbuf1len = rbufalen = 0;
6981+ switch (prtspexp->pbtype)
6982+ {
6983+ case pb_single:
6984+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
6985+ {
6986+ t.dst.u.udp.port = htons(loport);
6987+ if (ip_conntrack_change_expect(exp, &t) == 0)
6988+ {
6989+ DEBUGP("using port %hu\n", loport);
6990+ break;
6991+ }
6992+ }
6993+ if (loport != 0)
6994+ {
6995+ rbuf1len = sprintf(rbuf1, "%hu", loport);
6996+ rbufalen = sprintf(rbufa, "%hu", loport);
6997+ }
6998+ break;
6999+ case pb_range:
7000+ for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7001+ {
7002+ t.dst.u.udp.port = htons(loport);
7003+ if (ip_conntrack_change_expect(exp, &t) == 0)
7004+ {
7005+ hiport = loport + ~exp->mask.dst.u.udp.port;
7006+ DEBUGP("using ports %hu-%hu\n", loport, hiport);
7007+ break;
7008+ }
7009+ }
7010+ if (loport != 0)
7011+ {
7012+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7013+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7014+ }
7015+ break;
7016+ case pb_discon:
7017+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7018+ {
7019+ t.dst.u.udp.port = htons(loport);
7020+ if (ip_conntrack_change_expect(exp, &t) == 0)
7021+ {
7022+ DEBUGP("using port %hu (1 of 2)\n", loport);
7023+ break;
7024+ }
7025+ }
7026+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7027+ {
7028+ t.dst.u.udp.port = htons(hiport);
7029+ if (ip_conntrack_change_expect(exp, &t) == 0)
7030+ {
7031+ DEBUGP("using port %hu (2 of 2)\n", hiport);
7032+ break;
7033+ }
7034+ }
7035+ if (loport != 0 && hiport != 0)
7036+ {
7037+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7038+ if (hiport == loport+1)
7039+ {
7040+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7041+ }
7042+ else
7043+ {
7044+ rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7045+ }
7046+ }
7047+ break;
7048+ }
7049+
7050+ if (rbuf1len == 0)
7051+ {
7052+ return 0; /* cannot get replacement port(s) */
7053+ }
7054+
7055+ /* Transport: tran;field;field=val,tran;field;field=val,... */
7056+ while (off < tranlen)
7057+ {
7058+ uint saveoff;
7059+ const char* pparamend;
7060+ uint nextparamoff;
7061+
7062+ pparamend = memchr(ptran+off, ',', tranlen-off);
7063+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7064+ nextparamoff = pparamend-ptcp;
7065+
7066+ /*
7067+ * We pass over each param twice. On the first pass, we look for a
7068+ * destination= field. It is handled by the security policy. If it
7069+ * is present, allowed, and equal to our external address, we assume
7070+ * that STUN is being used and we leave the client_port= field alone.
7071+ */
7072+ is_stun = 0;
7073+ saveoff = off;
7074+ while (off < nextparamoff)
7075+ {
7076+ const char* pfieldend;
7077+ uint nextfieldoff;
7078+
7079+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7080+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7081+
7082+ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7083+ {
7084+ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7085+ {
7086+ is_stun = 1;
7087+ }
7088+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7089+ {
7090+ diff = nextfieldoff-off;
7091+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7092+ off, diff, NULL, 0))
7093+ {
7094+ /* mangle failed, all we can do is bail */
7095+ return 0;
7096+ }
7097+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7098+ ptran = ptcp+tranoff;
7099+ tranlen -= diff;
7100+ nextparamoff -= diff;
7101+ nextfieldoff -= diff;
7102+ }
7103+ }
7104+
7105+ off = nextfieldoff;
7106+ }
7107+ if (is_stun)
7108+ {
7109+ continue;
7110+ }
7111+ off = saveoff;
7112+ while (off < nextparamoff)
7113+ {
7114+ const char* pfieldend;
7115+ uint nextfieldoff;
7116+
7117+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7118+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7119+
7120+ if (strncmp(ptran+off, "client_port=", 12) == 0)
7121+ {
7122+ u_int16_t port;
7123+ uint numlen;
7124+ uint origoff;
7125+ uint origlen;
7126+ char* rbuf = rbuf1;
7127+ uint rbuflen = rbuf1len;
7128+
7129+ off += 12;
7130+ origoff = (ptran-ptcp)+off;
7131+ origlen = 0;
7132+ numlen = nf_strtou16(ptran+off, &port);
7133+ off += numlen;
7134+ origlen += numlen;
7135+ if (port != prtspexp->loport)
7136+ {
7137+ DEBUGP("multiple ports found, port %hu ignored\n", port);
7138+ }
7139+ else
7140+ {
7141+ if (ptran[off] == '-' || ptran[off] == '/')
7142+ {
7143+ off++;
7144+ origlen++;
7145+ numlen = nf_strtou16(ptran+off, &port);
7146+ off += numlen;
7147+ origlen += numlen;
7148+ rbuf = rbufa;
7149+ rbuflen = rbufalen;
7150+ }
7151+
7152+ /*
7153+ * note we cannot just memcpy() if the sizes are the same.
7154+ * the mangle function does skb resizing, checks for a
7155+ * cloned skb, and updates the checksums.
7156+ *
7157+ * parameter 4 below is offset from start of tcp data.
7158+ */
7159+ diff = origlen-rbuflen;
7160+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7161+ origoff, origlen, rbuf, rbuflen))
7162+ {
7163+ /* mangle failed, all we can do is bail */
7164+ return 0;
7165+ }
7166+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7167+ ptran = ptcp+tranoff;
7168+ tranlen -= diff;
7169+ nextparamoff -= diff;
7170+ nextfieldoff -= diff;
7171+ }
7172+ }
7173+
7174+ off = nextfieldoff;
7175+ }
7176+
7177+ off = nextparamoff;
7178+ }
7179+
7180+ return 1;
7181+}
7182+
7183+static unsigned int
7184+expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7185+{
7186+ struct ip_nat_multi_range mr;
7187+ u_int32_t newdstip, newsrcip, newip;
7188+
7189+ struct ip_conntrack *master = master_ct(ct);
7190+
7191+ IP_NF_ASSERT(info);
7192+ IP_NF_ASSERT(master);
7193+
7194+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7195+
7196+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7197+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7198+ newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7199+
7200+ DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7201+ NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7202+
7203+ mr.rangesize = 1;
7204+ /* We don't want to manip the per-protocol, just the IPs. */
7205+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7206+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
7207+
7208+ return ip_nat_setup_info(ct, &mr, hooknum);
7209+}
7210+
7211+static uint
7212+help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7213+ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7214+{
7215+ char* ptcp;
7216+ uint tcplen;
7217+ uint hdrsoff;
7218+ uint hdrslen;
7219+ uint lineoff;
7220+ uint linelen;
7221+ uint off;
7222+
7223+ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7224+ struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7225+
7226+ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7227+
7228+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7229+
7230+ hdrsoff = exp->seq - ntohl(tcph->seq);
7231+ hdrslen = prtspexp->len;
7232+ off = hdrsoff;
7233+
7234+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7235+ {
7236+ if (linelen == 0)
7237+ {
7238+ break;
7239+ }
7240+ if (off > hdrsoff+hdrslen)
7241+ {
7242+ INFOP("!! overrun !!");
7243+ break;
7244+ }
7245+ DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7246+
7247+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7248+ {
7249+ uint oldtcplen = tcplen;
7250+ if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7251+ {
7252+ break;
7253+ }
7254+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7255+ hdrslen -= (oldtcplen-tcplen);
7256+ off -= (oldtcplen-tcplen);
7257+ lineoff -= (oldtcplen-tcplen);
7258+ linelen -= (oldtcplen-tcplen);
7259+ DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7260+ }
7261+ }
7262+
7263+ return NF_ACCEPT;
7264+}
7265+
7266+static uint
7267+help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7268+ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7269+{
7270+ /* XXX: unmangle */
7271+ return NF_ACCEPT;
7272+}
7273+
7274+static uint
7275+help(struct ip_conntrack* ct,
7276+ struct ip_conntrack_expect* exp,
7277+ struct ip_nat_info* info,
7278+ enum ip_conntrack_info ctinfo,
7279+ unsigned int hooknum,
7280+ struct sk_buff** pskb)
7281+{
7282+ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7283+ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7284+ uint datalen;
7285+ int dir;
7286+ struct ip_ct_rtsp_expect* ct_rtsp_info;
7287+ int rc = NF_ACCEPT;
7288+
7289+ if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7290+ {
7291+ DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7292+ return NF_ACCEPT;
7293+ }
7294+
7295+ ct_rtsp_info = &exp->help.exp_rtsp_info;
7296+
7297+ /*
7298+ * Only mangle things once: original direction in POST_ROUTING
7299+ * and reply direction on PRE_ROUTING.
7300+ */
7301+ dir = CTINFO2DIR(ctinfo);
7302+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7303+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7304+ {
7305+ DEBUGP("Not touching dir %s at hook %s\n",
7306+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7307+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7308+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7309+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7310+ return NF_ACCEPT;
7311+ }
7312+ DEBUGP("got beyond not touching\n");
7313+
7314+ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7315+
7316+ LOCK_BH(&ip_rtsp_lock);
7317+ /* Ensure the packet contains all of the marked data */
7318+ if (!between(exp->seq + ct_rtsp_info->len,
7319+ ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7320+ {
7321+ /* Partial retransmission? Probably a hacker. */
7322+ if (net_ratelimit())
7323+ {
7324+ INFOP("partial packet %u/%u in %u/%u\n",
7325+ exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7326+ }
7327+ UNLOCK_BH(&ip_rtsp_lock);
7328+ return NF_DROP;
7329+ }
7330+
7331+ switch (dir)
7332+ {
7333+ case IP_CT_DIR_ORIGINAL:
7334+ rc = help_out(ct, ctinfo, exp, pskb);
7335+ break;
7336+ case IP_CT_DIR_REPLY:
7337+ rc = help_in(ct, ctinfo, exp, pskb);
7338+ break;
7339+ }
7340+ UNLOCK_BH(&ip_rtsp_lock);
7341+
7342+ return rc;
7343+}
7344+
7345+static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7346+static char rtsp_names[MAX_PORTS][10];
7347+
7348+/* This function is intentionally _NOT_ defined as __exit */
7349+static void
7350+fini(void)
7351+{
7352+ int i;
7353+
7354+ for (i = 0; i < num_ports; i++)
7355+ {
7356+ DEBUGP("unregistering helper for port %d\n", ports[i]);
7357+ ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7358+ }
7359+}
7360+
7361+static int __init
7362+init(void)
7363+{
7364+ int ret = 0;
7365+ int i;
7366+ struct ip_nat_helper* hlpr;
7367+ char* tmpname;
7368+
7369+ printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7370+
7371+ if (ports[0] == 0)
7372+ {
7373+ ports[0] = RTSP_PORT;
7374+ }
7375+
7376+ for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7377+ {
7378+ hlpr = &ip_nat_rtsp_helpers[i];
7379+ memset(hlpr, 0, sizeof(struct ip_nat_helper));
7380+
7381+ hlpr->tuple.dst.protonum = IPPROTO_TCP;
7382+ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7383+ hlpr->mask.src.u.tcp.port = 0xFFFF;
7384+ hlpr->mask.dst.protonum = 0xFFFF;
7385+ hlpr->help = help;
7386+ hlpr->flags = 0;
7387+ hlpr->me = THIS_MODULE;
7388+ hlpr->expect = expected;
7389+
7390+ tmpname = &rtsp_names[i][0];
7391+ if (ports[i] == RTSP_PORT)
7392+ {
7393+ sprintf(tmpname, "rtsp");
7394+ }
7395+ else
7396+ {
7397+ sprintf(tmpname, "rtsp-%d", i);
7398+ }
7399+ hlpr->name = tmpname;
7400+
7401+ DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7402+ ret = ip_nat_helper_register(hlpr);
7403+
7404+ if (ret)
7405+ {
7406+ printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7407+ fini();
7408+ return 1;
7409+ }
7410+ num_ports++;
7411+ }
7412+ if (stunaddr != NULL)
7413+ {
7414+ extip = in_aton(stunaddr);
7415+ }
7416+ if (destaction != NULL)
7417+ {
7418+ if (strcmp(destaction, "auto") == 0)
7419+ {
7420+ dstact = DSTACT_AUTO;
7421+ }
7422+ if (strcmp(destaction, "strip") == 0)
7423+ {
7424+ dstact = DSTACT_STRIP;
7425+ }
7426+ if (strcmp(destaction, "none") == 0)
7427+ {
7428+ dstact = DSTACT_NONE;
7429+ }
7430+ }
7431+ return ret;
7432+}
7433+
7434+module_init(init);
7435+module_exit(fini);
7436diff -Nur --exclude '*.orig' 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
7437--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c 2004-04-28 03:35:44.000000000 +0200
7438+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c 2004-04-29 11:17:15.000000000 +0200
7439@@ -75,7 +75,7 @@
7440 0,
7441 sizeof(struct ipt_entry),
7442 sizeof(struct ipt_standard),
7443- 0, { 0, 0 }, { } },
7444+ 0, NULL, 0, { 0, 0 }, { } },
7445 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7446 -NF_ACCEPT - 1 } },
7447 /* POST_ROUTING */
7448@@ -83,7 +83,7 @@
7449 0,
7450 sizeof(struct ipt_entry),
7451 sizeof(struct ipt_standard),
7452- 0, { 0, 0 }, { } },
7453+ 0, NULL, 0, { 0, 0 }, { } },
7454 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7455 -NF_ACCEPT - 1 } },
7456 /* LOCAL_OUT */
7457@@ -91,7 +91,7 @@
7458 0,
7459 sizeof(struct ipt_entry),
7460 sizeof(struct ipt_standard),
7461- 0, { 0, 0 }, { } },
7462+ 0, NULL, 0, { 0, 0 }, { } },
7463 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7464 -NF_ACCEPT - 1 } }
7465 },
7466@@ -100,7 +100,7 @@
7467 0,
7468 sizeof(struct ipt_entry),
7469 sizeof(struct ipt_error),
7470- 0, { 0, 0 }, { } },
7471+ 0, NULL, 0, { 0, 0 }, { } },
7472 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7473 { } },
7474 "ERROR"
7475diff -Nur --exclude '*.orig' 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
7476--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-28 03:36:29.000000000 +0200
7477+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-29 11:18:04.000000000 +0200
7478@@ -175,6 +175,45 @@
7479 return do_bindings(ct, ctinfo, info, hooknum, pskb);
7480 }
7481
7482+struct nat_route_key
7483+{
7484+ u_int32_t addr;
7485+#ifdef CONFIG_XFRM
7486+ u_int16_t port;
7487+#endif
7488+};
7489+
7490+static inline void
7491+nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
7492+{
7493+ struct iphdr *iph = skb->nh.iph;
7494+
7495+ key->addr = which ? iph->daddr : iph->saddr;
7496+#ifdef CONFIG_XFRM
7497+ key->port = 0;
7498+ if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7499+ u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7500+ key->port = ports[which];
7501+ }
7502+#endif
7503+}
7504+
7505+static inline int
7506+nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
7507+{
7508+ struct iphdr *iph = skb->nh.iph;
7509+
7510+ if (key->addr != (which ? iph->daddr : iph->saddr))
7511+ return 1;
7512+#ifdef CONFIG_XFRM
7513+ if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7514+ u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7515+ if (key->port != ports[which])
7516+ return 1;
7517+ }
7518+#endif
7519+}
7520+
7521 static unsigned int
7522 ip_nat_out(unsigned int hooknum,
7523 struct sk_buff **pskb,
7524@@ -182,6 +221,9 @@
7525 const struct net_device *out,
7526 int (*okfn)(struct sk_buff *))
7527 {
7528+ struct nat_route_key key;
7529+ unsigned int ret;
7530+
7531 /* root is playing with raw sockets. */
7532 if ((*pskb)->len < sizeof(struct iphdr)
7533 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7534@@ -204,7 +246,29 @@
7535 return NF_STOLEN;
7536 }
7537
7538- return ip_nat_fn(hooknum, pskb, in, out, okfn);
7539+ nat_route_key_get(*pskb, &key, 0);
7540+ ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7541+
7542+ if (ret != NF_DROP && ret != NF_STOLEN
7543+ && nat_route_key_compare(*pskb, &key, 0)) {
7544+ if (ip_route_me_harder(pskb) != 0)
7545+ ret = NF_DROP;
7546+#ifdef CONFIG_XFRM
7547+ /*
7548+ * POST_ROUTING hook is called with fixed outfn, we need
7549+ * to manually confirm the packet and direct it to the
7550+ * transformers if a policy matches.
7551+ */
7552+ else if ((*pskb)->dst->xfrm != NULL) {
7553+ ret = ip_conntrack_confirm(*pskb);
7554+ if (ret != NF_DROP) {
7555+ dst_output(*pskb);
7556+ ret = NF_STOLEN;
7557+ }
7558+ }
7559+#endif
7560+ }
7561+ return ret;
7562 }
7563
7564 #ifdef CONFIG_IP_NF_NAT_LOCAL
7565@@ -215,7 +279,7 @@
7566 const struct net_device *out,
7567 int (*okfn)(struct sk_buff *))
7568 {
7569- u_int32_t saddr, daddr;
7570+ struct nat_route_key key;
7571 unsigned int ret;
7572
7573 /* root is playing with raw sockets. */
7574@@ -223,14 +287,14 @@
7575 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7576 return NF_ACCEPT;
7577
7578- saddr = (*pskb)->nh.iph->saddr;
7579- daddr = (*pskb)->nh.iph->daddr;
7580-
7581+ nat_route_key_get(*pskb, &key, 1);
7582 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7583+
7584 if (ret != NF_DROP && ret != NF_STOLEN
7585- && ((*pskb)->nh.iph->saddr != saddr
7586- || (*pskb)->nh.iph->daddr != daddr))
7587- return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
7588+ && nat_route_key_compare(*pskb, &key, 1)) {
7589+ if (ip_route_me_harder(pskb) != 0)
7590+ ret = NF_DROP;
7591+ }
7592 return ret;
7593 }
7594 #endif
7595diff -Nur --exclude '*.orig' 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
7596--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
7597+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c 2004-04-29 11:21:43.000000000 +0200
7598@@ -0,0 +1,473 @@
7599+/*
7600+ * talk extension for UDP NAT alteration.
7601+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7602+ *
7603+ * This program is free software; you can redistribute it and/or
7604+ * modify it under the terms of the GNU General Public License
7605+ * as published by the Free Software Foundation; either version
7606+ * 2 of the License, or (at your option) any later version.
7607+ **
7608+ * Module load syntax:
7609+ * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7610+ *
7611+ * talk=[0|1] disable|enable old talk support
7612+ * ntalk=[0|1] disable|enable ntalk support
7613+ * ntalk2=[0|1] disable|enable ntalk2 support
7614+ *
7615+ * The default is talk=1 ntalk=1 ntalk2=1
7616+ *
7617+ *
7618+ */
7619+#include <linux/module.h>
7620+#include <linux/netfilter_ipv4.h>
7621+#include <linux/ip.h>
7622+#include <linux/udp.h>
7623+#include <linux/kernel.h>
7624+#include <net/tcp.h>
7625+#include <net/udp.h>
7626+
7627+#include <linux/netfilter_ipv4/ip_nat.h>
7628+#include <linux/netfilter_ipv4/ip_nat_helper.h>
7629+#include <linux/netfilter_ipv4/ip_nat_rule.h>
7630+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7631+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7632+
7633+/* Default all talk protocols are supported */
7634+static int talk = 1;
7635+static int ntalk = 1;
7636+static int ntalk2 = 1;
7637+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7638+MODULE_DESCRIPTION("talk network address translation module");
7639+#ifdef MODULE_PARM
7640+MODULE_PARM(talk, "i");
7641+MODULE_PARM_DESC(talk, "support (old) talk protocol");
7642+MODULE_PARM(ntalk, "i");
7643+MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7644+MODULE_PARM(ntalk2, "i");
7645+MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7646+#endif
7647+
7648+#if 0
7649+#define DEBUGP printk
7650+#define IP_NAT_TALK_DEBUG
7651+#else
7652+#define DEBUGP(format, args...)
7653+#endif
7654+
7655+/* FIXME: Time out? --RR */
7656+
7657+static int
7658+mangle_packet(struct sk_buff **pskb,
7659+ struct ip_conntrack *ct,
7660+ u_int32_t newip,
7661+ u_int16_t port,
7662+ struct talk_addr *addr,
7663+ struct talk_addr *ctl_addr)
7664+{
7665+ struct iphdr *iph = (*pskb)->nh.iph;
7666+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
7667+ size_t udplen = (*pskb)->len - iph->ihl * 4;
7668+
7669+ /* Fortunately talk sends a structure with the address and
7670+ port in it. The size of the packet won't change. */
7671+
7672+ if (ctl_addr == NULL) {
7673+ /* response */
7674+ if (addr->ta_addr == INADDR_ANY)
7675+ return 1;
7676+ DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7677+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7678+ NIPQUAD(newip), ntohs(port));
7679+ addr->ta_addr = newip;
7680+ addr->ta_port = port;
7681+ } else {
7682+ /* message */
7683+ if (addr->ta_addr != INADDR_ANY) {
7684+ /* Change address inside packet to match way we're mapping
7685+ this connection. */
7686+ DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7687+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7688+ NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7689+ ntohs(addr->ta_port));
7690+ addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7691+ }
7692+ DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
7693+ NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7694+ NIPQUAD(newip), ntohs(port));
7695+ ctl_addr->ta_addr = newip;
7696+ ctl_addr->ta_port = port;
7697+ }
7698+
7699+ /* Fix checksums */
7700+ (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
7701+ udph->check = 0;
7702+ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7703+ csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
7704+
7705+ ip_send_check(iph);
7706+ return 1;
7707+}
7708+
7709+static int talk_help_msg(struct ip_conntrack *ct,
7710+ struct sk_buff **pskb,
7711+ u_char type,
7712+ struct talk_addr *addr,
7713+ struct talk_addr *ctl_addr)
7714+{
7715+ u_int32_t newip;
7716+ u_int16_t port;
7717+
7718+ unsigned int verdict = NF_ACCEPT;
7719+
7720+ DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
7721+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7722+ NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7723+ type);
7724+
7725+ /* Change address inside packet to match way we're mapping
7726+ this connection. */
7727+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7728+ port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7729+ DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
7730+ NIPQUAD(newip), ntohs(port));
7731+
7732+ if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
7733+ verdict = NF_DROP;
7734+
7735+ return verdict;
7736+}
7737+
7738+static int talk_help_response(struct ip_conntrack *ct,
7739+ struct ip_conntrack_expect *exp,
7740+ struct sk_buff **pskb,
7741+ u_char type,
7742+ u_char answer,
7743+ struct talk_addr *addr)
7744+{
7745+ u_int32_t newip;
7746+ u_int16_t port;
7747+ struct ip_conntrack_tuple t;
7748+ struct ip_ct_talk_expect *ct_talk_info;
7749+
7750+ DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
7751+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7752+ type, answer);
7753+
7754+ LOCK_BH(&ip_talk_lock);
7755+ ct_talk_info = &exp->help.exp_talk_info;
7756+
7757+ if (!(answer == SUCCESS
7758+ && (type == LOOK_UP || type == ANNOUNCE)
7759+ && exp != NULL)) {
7760+ UNLOCK_BH(&ip_talk_lock);
7761+ return NF_ACCEPT;
7762+ }
7763+
7764+ DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
7765+ ntohs(ct_talk_info->port),
7766+ type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
7767+
7768+ /* Change address inside packet to match way we're mapping
7769+ this connection. */
7770+ newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
7771+ IP_CT_DIR_REPLY].tuple.dst.ip;
7772+ /* We can read expect here without conntrack lock, since it's
7773+ only set in ip_conntrack_talk , with ip_talk_lock held
7774+ writable */
7775+ t = exp->tuple;
7776+ t.dst.ip = newip;
7777+
7778+ /* Try to get same port: if not, try to change it. */
7779+ for (port = ntohs(ct_talk_info->port); port != 0; port++) {
7780+ if (type == LOOK_UP)
7781+ t.dst.u.tcp.port = htons(port);
7782+ else
7783+ t.dst.u.udp.port = htons(port);
7784+
7785+ if (ip_conntrack_change_expect(exp, &t) == 0) {
7786+ DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
7787+ break;
7788+ }
7789+ }
7790+ UNLOCK_BH(&ip_talk_lock);
7791+
7792+ if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
7793+ return NF_DROP;
7794+
7795+ return NF_ACCEPT;
7796+}
7797+
7798+static unsigned int talk_help(struct ip_conntrack *ct,
7799+ struct ip_conntrack_expect *exp,
7800+ struct ip_nat_info *info,
7801+ enum ip_conntrack_info ctinfo,
7802+ unsigned int hooknum,
7803+ struct sk_buff **pskb,
7804+ int talk_port)
7805+{
7806+ struct iphdr *iph = (*pskb)->nh.iph;
7807+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
7808+ unsigned int udplen = (*pskb)->len - iph->ihl * 4;
7809+ char *data = (char *)udph + sizeof(struct udphdr);
7810+ int dir;
7811+
7812+ /* Only mangle things once: original direction in POST_ROUTING
7813+ and reply direction on PRE_ROUTING. */
7814+ dir = CTINFO2DIR(ctinfo);
7815+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7816+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7817+ DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
7818+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7819+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7820+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7821+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7822+ return NF_ACCEPT;
7823+ }
7824+ DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
7825+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7826+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7827+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7828+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7829+ NIPQUAD(iph->saddr), ntohs(udph->source),
7830+ NIPQUAD(iph->daddr), ntohs(udph->dest),
7831+ talk_port);
7832+
7833+ /* Because conntrack does not drop packets, checking must be repeated here... */
7834+ if (talk_port == TALK_PORT) {
7835+ if (dir == IP_CT_DIR_ORIGINAL
7836+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
7837+ return talk_help_msg(ct, pskb,
7838+ ((struct talk_msg *)data)->type,
7839+ &(((struct talk_msg *)data)->addr),
7840+ &(((struct talk_msg *)data)->ctl_addr));
7841+ else if (dir == IP_CT_DIR_REPLY
7842+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7843+ return talk_help_response(ct, exp, pskb,
7844+ ((struct talk_response *)data)->type,
7845+ ((struct talk_response *)data)->answer,
7846+ &(((struct talk_response *)data)->addr));
7847+ else {
7848+ DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
7849+ dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
7850+ (unsigned)udplen - sizeof(struct udphdr),
7851+ dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
7852+ return NF_DROP;
7853+ }
7854+ } else {
7855+ if (dir == IP_CT_DIR_ORIGINAL) {
7856+ if (ntalk
7857+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
7858+ && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
7859+ return talk_help_msg(ct, pskb,
7860+ ((struct ntalk_msg *)data)->type,
7861+ &(((struct ntalk_msg *)data)->addr),
7862+ &(((struct ntalk_msg *)data)->ctl_addr));
7863+ else if (ntalk2
7864+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
7865+ && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
7866+ && udplen == sizeof(struct udphdr)
7867+ + sizeof(struct ntalk2_msg)
7868+ + ((struct ntalk2_msg *)data)->extended)
7869+ return talk_help_msg(ct, pskb,
7870+ ((struct ntalk2_msg *)data)->type,
7871+ &(((struct ntalk2_msg *)data)->addr),
7872+ &(((struct ntalk2_msg *)data)->ctl_addr));
7873+ else {
7874+ DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
7875+ (unsigned)udplen - sizeof(struct udphdr),
7876+ sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
7877+ return NF_DROP;
7878+ }
7879+ } else {
7880+ if (ntalk
7881+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
7882+ && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
7883+ return talk_help_response(ct, exp, pskb,
7884+ ((struct ntalk_response *)data)->type,
7885+ ((struct ntalk_response *)data)->answer,
7886+ &(((struct ntalk_response *)data)->addr));
7887+ else if (ntalk2
7888+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
7889+ && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
7890+ return talk_help_response(ct, exp, pskb,
7891+ ((struct ntalk2_response *)data)->type,
7892+ ((struct ntalk2_response *)data)->answer,
7893+ &(((struct ntalk2_response *)data)->addr));
7894+ else {
7895+ DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
7896+ (unsigned)udplen - sizeof(struct udphdr),
7897+ sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
7898+ return NF_DROP;
7899+ }
7900+ }
7901+ }
7902+}
7903+
7904+static unsigned int help(struct ip_conntrack *ct,
7905+ struct ip_conntrack_expect *exp,
7906+ struct ip_nat_info *info,
7907+ enum ip_conntrack_info ctinfo,
7908+ unsigned int hooknum,
7909+ struct sk_buff **pskb)
7910+{
7911+ return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
7912+}
7913+
7914+static unsigned int nhelp(struct ip_conntrack *ct,
7915+ struct ip_conntrack_expect *exp,
7916+ struct ip_nat_info *info,
7917+ enum ip_conntrack_info ctinfo,
7918+ unsigned int hooknum,
7919+ struct sk_buff **pskb)
7920+{
7921+ return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
7922+}
7923+
7924+static unsigned int
7925+talk_nat_expected(struct sk_buff **pskb,
7926+ unsigned int hooknum,
7927+ struct ip_conntrack *ct,
7928+ struct ip_nat_info *info);
7929+
7930+static struct ip_nat_helper talk_helpers[2] =
7931+ { { { NULL, NULL },
7932+ "talk", /* name */
7933+ IP_NAT_HELPER_F_ALWAYS, /* flags */
7934+ THIS_MODULE, /* module */
7935+ { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
7936+ { 0, { 0 }, IPPROTO_UDP } },
7937+ { { 0, { .udp = { 0xFFFF } } }, /* mask */
7938+ { 0, { 0 }, 0xFFFF } },
7939+ help, /* helper */
7940+ talk_nat_expected }, /* expectfn */
7941+ { { NULL, NULL },
7942+ "ntalk", /* name */
7943+ IP_NAT_HELPER_F_ALWAYS, /* flags */
7944+ THIS_MODULE, /* module */
7945+ { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
7946+ { 0, { 0 }, IPPROTO_UDP } },
7947+ { { 0, { .udp = { 0xFFFF } } }, /* mask */
7948+ { 0, { 0 }, 0xFFFF } },
7949+ nhelp, /* helper */
7950+ talk_nat_expected } /* expectfn */
7951+ };
7952+
7953+static unsigned int
7954+talk_nat_expected(struct sk_buff **pskb,
7955+ unsigned int hooknum,
7956+ struct ip_conntrack *ct,
7957+ struct ip_nat_info *info)
7958+{
7959+ struct ip_nat_multi_range mr;
7960+ u_int32_t newdstip, newsrcip, newip;
7961+ u_int16_t port;
7962+ unsigned int ret;
7963+
7964+ struct ip_conntrack *master = master_ct(ct);
7965+
7966+ IP_NF_ASSERT(info);
7967+ IP_NF_ASSERT(master);
7968+
7969+ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
7970+
7971+ DEBUGP("ip_nat_talk_expected: We have a connection!\n");
7972+
7973+ LOCK_BH(&ip_talk_lock);
7974+ port = ct->master->help.exp_talk_info.port;
7975+ UNLOCK_BH(&ip_talk_lock);
7976+
7977+ DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
7978+ CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7979+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7980+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7981+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7982+ ct, master);
7983+
7984+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
7985+ /* Callee client -> caller server */
7986+#ifdef IP_NAT_TALK_DEBUG
7987+ struct iphdr *iph = (*pskb)->nh.iph;
7988+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
7989+
7990+ DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7991+ NIPQUAD(iph->saddr), ntohs(udph->source),
7992+ NIPQUAD(iph->daddr), ntohs(udph->dest));
7993+#endif
7994+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7995+ newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7996+ DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
7997+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
7998+ } else {
7999+ /* Callee client -> caller client */
8000+#ifdef IP_NAT_TALK_DEBUG
8001+ struct iphdr *iph = (*pskb)->nh.iph;
8002+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8003+
8004+ DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8005+ NIPQUAD(iph->saddr), ntohs(tcph->source),
8006+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
8007+#endif
8008+ newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8009+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8010+ DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8011+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
8012+ }
8013+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8014+ newip = newsrcip;
8015+ else
8016+ newip = newdstip;
8017+
8018+ DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8019+
8020+ mr.rangesize = 1;
8021+ /* We don't want to manip the per-protocol, just the IPs... */
8022+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8023+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
8024+
8025+ /* ... unless we're doing a MANIP_DST, in which case, make
8026+ sure we map to the correct port */
8027+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8028+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8029+ mr.range[0].min = mr.range[0].max
8030+ = ((union ip_conntrack_manip_proto)
8031+ { .udp = { port } });
8032+ }
8033+ ret = ip_nat_setup_info(ct, &mr, hooknum);
8034+
8035+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8036+ DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8037+ /* NAT expectfn called with ip_nat_lock write-locked */
8038+ info->helper = &talk_helpers[htons(port) - TALK_PORT];
8039+ }
8040+ return ret;
8041+}
8042+
8043+static int __init init(void)
8044+{
8045+ int ret = 0;
8046+
8047+ if (talk > 0) {
8048+ ret = ip_nat_helper_register(&talk_helpers[0]);
8049+
8050+ if (ret != 0)
8051+ return ret;
8052+ }
8053+ if (ntalk > 0 || ntalk2 > 0) {
8054+ ret = ip_nat_helper_register(&talk_helpers[1]);
8055+
8056+ if (ret != 0 && talk > 0)
8057+ ip_nat_helper_unregister(&talk_helpers[0]);
8058+ }
8059+ return ret;
8060+}
8061+
8062+static void __exit fini(void)
8063+{
8064+ if (talk > 0)
8065+ ip_nat_helper_unregister(&talk_helpers[0]);
8066+ if (ntalk > 0 || ntalk2 > 0)
8067+ ip_nat_helper_unregister(&talk_helpers[1]);
8068+}
8069+
8070+module_init(init);
8071+module_exit(fini);
8072diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c
8073--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-04-29 11:24:39.000000000 +0200
8074+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c 2004-04-29 11:17:15.000000000 +0200
8075@@ -29,6 +29,14 @@
8076
8077 #include <linux/netfilter_ipv4/ip_tables.h>
8078
8079+static const char *hooknames[] = {
8080+ [NF_IP_PRE_ROUTING] "PREROUTING",
8081+ [NF_IP_LOCAL_IN] "INPUT",
8082+ [NF_IP_FORWARD] "FORWARD",
8083+ [NF_IP_LOCAL_OUT] "OUTPUT",
8084+ [NF_IP_POST_ROUTING] "POSTROUTING",
8085+};
8086+
8087 MODULE_LICENSE("GPL");
8088 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8089 MODULE_DESCRIPTION("IPv4 packet filter");
8090@@ -326,6 +334,12 @@
8091
8092 t = ipt_get_target(e);
8093 IP_NF_ASSERT(t->u.kernel.target);
8094+
8095+ /* The packet traced and the rule isn't an unconditional return/END. */
8096+ if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
8097+ nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8098+ table->name, e->chainname, e->rulenum);
8099+ }
8100 /* Standard target? */
8101 if (!t->u.kernel.target->target) {
8102 int v;
8103@@ -352,7 +366,6 @@
8104 /* set back pointer to next entry */
8105 back = next;
8106 }
8107-
8108 e = get_entry(table_base, v);
8109 } else {
8110 /* Targets which reenter must return
8111@@ -478,6 +491,29 @@
8112 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8113 }
8114
8115+static inline int
8116+find_error_target(struct ipt_entry *s,
8117+ struct ipt_entry *e,
8118+ char **chainname)
8119+{
8120+ struct ipt_entry_target *t;
8121+ static struct ipt_entry *found = NULL;
8122+
8123+ if (s == e) {
8124+ if (!found)
8125+ return 0;
8126+ t = ipt_get_target(found);
8127+ if (strcmp(t->u.user.name,
8128+ IPT_ERROR_TARGET) == 0) {
8129+ *chainname = t->data;
8130+ return 1;
8131+ }
8132+ } else
8133+ found = s;
8134+
8135+ return 0;
8136+}
8137+
8138 /* All zeroes == unconditional rule. */
8139 static inline int
8140 unconditional(const struct ipt_ip *ip)
8141@@ -497,6 +533,8 @@
8142 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
8143 {
8144 unsigned int hook;
8145+ char *chainname = NULL;
8146+ u_int32_t rulenum;
8147
8148 /* No recursion; use packet counter to save back ptrs (reset
8149 to 0 as we leave), and comefrom to save source hook bitmask */
8150@@ -510,6 +548,8 @@
8151
8152 /* Set initial back pointer. */
8153 e->counters.pcnt = pos;
8154+ rulenum = 1;
8155+ chainname = (char *) hooknames[hook];
8156
8157 for (;;) {
8158 struct ipt_standard_target *t
8159@@ -522,6 +562,8 @@
8160 }
8161 e->comefrom
8162 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
8163+ e->rulenum = rulenum++;
8164+ e->chainname = chainname;
8165
8166 /* Unconditional return/END. */
8167 if (e->target_offset == sizeof(struct ipt_entry)
8168@@ -531,6 +573,10 @@
8169 && unconditional(&e->ip)) {
8170 unsigned int oldpos, size;
8171
8172+ /* Set unconditional rulenum to zero. */
8173+ e->rulenum = 0;
8174+ e->counters.bcnt = 0;
8175+
8176 /* Return: backtrack through the last
8177 big jump. */
8178 do {
8179@@ -556,6 +602,11 @@
8180 (newinfo->entries + pos);
8181 } while (oldpos == pos + e->next_offset);
8182
8183+ /* Restore chainname, rulenum. */
8184+ chainname = e->chainname;
8185+ rulenum = e->counters.bcnt;
8186+ e->counters.bcnt = 0;
8187+
8188 /* Move along one */
8189 size = e->next_offset;
8190 e = (struct ipt_entry *)
8191@@ -571,6 +622,17 @@
8192 /* This a jump; chase it. */
8193 duprintf("Jump rule %u -> %u\n",
8194 pos, newpos);
8195+ e->counters.bcnt = rulenum++;
8196+ rulenum = 1;
8197+ e = (struct ipt_entry *)
8198+ (newinfo->entries + newpos);
8199+ if (IPT_ENTRY_ITERATE(newinfo->entries,
8200+ newinfo->size,
8201+ find_error_target,
8202+ e, &chainname) == 0) {
8203+ printk("ip_tables: table screwed up!\n");
8204+ return 0;
8205+ }
8206 } else {
8207 /* ... this is a fallthru */
8208 newpos = pos + e->next_offset;
8209diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
8210--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
8211+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c 2004-04-29 11:10:59.000000000 +0200
8212@@ -0,0 +1,118 @@
8213+/* This kernel module is used to modify the connection mark values, or
8214+ * to optionally restore the skb nfmark from the connection mark
8215+ *
8216+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8217+ * by Henrik Nordstrom <hno@marasystems.com>
8218+ *
8219+ * This program is free software; you can redistribute it and/or modify
8220+ * it under the terms of the GNU General Public License as published by
8221+ * the Free Software Foundation; either version 2 of the License, or
8222+ * (at your option) any later version.
8223+ *
8224+ * This program is distributed in the hope that it will be useful,
8225+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8226+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8227+ * GNU General Public License for more details.
8228+ *
8229+ * You should have received a copy of the GNU General Public License
8230+ * along with this program; if not, write to the Free Software
8231+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8232+ */
8233+#include <linux/module.h>
8234+#include <linux/skbuff.h>
8235+#include <linux/ip.h>
8236+#include <net/checksum.h>
8237+
8238+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8239+MODULE_DESCRIPTION("IP tables CONNMARK matching module");
8240+MODULE_LICENSE("GPL");
8241+
8242+#include <linux/netfilter_ipv4/ip_tables.h>
8243+#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
8244+#include <linux/netfilter_ipv4/ip_conntrack.h>
8245+
8246+static unsigned int
8247+target(struct sk_buff **pskb,
8248+ const struct net_device *in,
8249+ const struct net_device *out,
8250+ unsigned int hooknum,
8251+ const void *targinfo,
8252+ void *userinfo)
8253+{
8254+ const struct ipt_connmark_target_info *markinfo = targinfo;
8255+ unsigned long diff;
8256+ unsigned long nfmark;
8257+ unsigned long newmark;
8258+
8259+ enum ip_conntrack_info ctinfo;
8260+ struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
8261+ if (ct) {
8262+ switch(markinfo->mode) {
8263+ case IPT_CONNMARK_SET:
8264+ newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
8265+ if (newmark != ct->mark)
8266+ ct->mark = newmark;
8267+ break;
8268+ case IPT_CONNMARK_SAVE:
8269+ newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
8270+ if (ct->mark != newmark)
8271+ ct->mark = newmark;
8272+ break;
8273+ case IPT_CONNMARK_RESTORE:
8274+ nfmark = (*pskb)->nfmark;
8275+ diff = (ct->mark ^ nfmark & markinfo->mask);
8276+ if (diff != 0) {
8277+ (*pskb)->nfmark = nfmark ^ diff;
8278+ (*pskb)->nfcache |= NFC_ALTERED;
8279+ }
8280+ break;
8281+ }
8282+ }
8283+
8284+ return IPT_CONTINUE;
8285+}
8286+
8287+static int
8288+checkentry(const char *tablename,
8289+ const struct ipt_entry *e,
8290+ void *targinfo,
8291+ unsigned int targinfosize,
8292+ unsigned int hook_mask)
8293+{
8294+ struct ipt_connmark_target_info *matchinfo = targinfo;
8295+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
8296+ printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
8297+ targinfosize,
8298+ IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
8299+ return 0;
8300+ }
8301+
8302+ if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
8303+ if (strcmp(tablename, "mangle") != 0) {
8304+ printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8305+ return 0;
8306+ }
8307+ }
8308+
8309+ return 1;
8310+}
8311+
8312+static struct ipt_target ipt_connmark_reg = {
8313+ .name = "CONNMARK",
8314+ .target = &target,
8315+ .checkentry = &checkentry,
8316+ .me = THIS_MODULE
8317+};
8318+
8319+static int __init init(void)
8320+{
8321+ return ipt_register_target(&ipt_connmark_reg);
8322+}
8323+
8324+static void __exit fini(void)
8325+{
8326+ ipt_unregister_target(&ipt_connmark_reg);
8327+}
8328+
8329+module_init(init);
8330+module_exit(fini);
8331diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c
8332--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
8333+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c 2004-04-29 11:17:03.000000000 +0200
8334@@ -0,0 +1,81 @@
8335+/* This is a module which is used for setting the NFMARK field of an skb. */
8336+#include <linux/module.h>
8337+#include <linux/skbuff.h>
8338+#include <linux/ip.h>
8339+#include <net/checksum.h>
8340+
8341+#include <linux/netfilter_ipv4/ip_tables.h>
8342+#include <linux/netfilter_ipv4/ipt_IPMARK.h>
8343+
8344+MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
8345+MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
8346+MODULE_LICENSE("GPL");
8347+
8348+static unsigned int
8349+target(struct sk_buff **pskb,
8350+ const struct net_device *in,
8351+ const struct net_device *out,
8352+ unsigned int hooknum,
8353+ const void *targinfo,
8354+ void *userinfo)
8355+{
8356+ const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
8357+ struct iphdr *iph = (*pskb)->nh.iph;
8358+ unsigned long mark;
8359+
8360+ if (ipmarkinfo->addr == IPT_IPMARK_SRC)
8361+ mark = (unsigned long) ntohl(iph->saddr);
8362+ else
8363+ mark = (unsigned long) ntohl(iph->daddr);
8364+
8365+ mark &= ipmarkinfo->andmask;
8366+ mark |= ipmarkinfo->ormask;
8367+
8368+ if ((*pskb)->nfmark != mark) {
8369+ (*pskb)->nfmark = mark;
8370+ (*pskb)->nfcache |= NFC_ALTERED;
8371+ }
8372+ return IPT_CONTINUE;
8373+}
8374+
8375+static int
8376+checkentry(const char *tablename,
8377+ const struct ipt_entry *e,
8378+ void *targinfo,
8379+ unsigned int targinfosize,
8380+ unsigned int hook_mask)
8381+{
8382+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
8383+ printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
8384+ targinfosize,
8385+ IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
8386+ return 0;
8387+ }
8388+
8389+ if (strcmp(tablename, "mangle") != 0) {
8390+ printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8391+ return 0;
8392+ }
8393+
8394+ return 1;
8395+}
8396+
8397+static struct ipt_target ipt_ipmark_reg = {
8398+ .name = "IPMARK",
8399+ .target = target,
8400+ .checkentry = checkentry,
8401+ .me = THIS_MODULE
8402+};
8403+
8404+static int __init init(void)
8405+{
8406+ return ipt_register_target(&ipt_ipmark_reg);
8407+}
8408+
8409+static void __exit fini(void)
8410+{
8411+ ipt_unregister_target(&ipt_ipmark_reg);
8412+}
8413+
8414+module_init(init);
8415+module_exit(fini);
8416diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c
8417--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
8418+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c 2004-04-29 11:17:08.000000000 +0200
8419@@ -0,0 +1,289 @@
8420+/*
8421+ * Kernel module to capture and hold incoming TCP connections using
8422+ * no local per-connection resources.
8423+ *
8424+ * Based on ipt_REJECT.c and offering functionality similar to
8425+ * LaBrea <http://www.hackbusters.net/LaBrea/>.
8426+ *
8427+ * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
8428+ *
8429+ * This program is free software; you can redistribute it and/or modify
8430+ * it under the terms of the GNU General Public License as published by
8431+ * the Free Software Foundation; either version 2 of the License, or
8432+ * (at your option) any later version.
8433+ *
8434+ * This program is distributed in the hope that it will be useful,
8435+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8436+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8437+ * GNU General Public License for more details.
8438+ *
8439+ * You should have received a copy of the GNU General Public License
8440+ * along with this program; if not, write to the Free Software
8441+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8442+ *
8443+ * Goal:
8444+ * - Allow incoming TCP connections to be established.
8445+ * - Passing data should result in the connection being switched to the
8446+ * persist state (0 byte window), in which the remote side stops sending
8447+ * data and asks to continue every 60 seconds.
8448+ * - Attempts to shut down the connection should be ignored completely, so
8449+ * the remote side ends up having to time it out.
8450+ *
8451+ * This means:
8452+ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
8453+ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
8454+ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
8455+ */
8456+
8457+#include <linux/config.h>
8458+#include <linux/module.h>
8459+#include <linux/skbuff.h>
8460+#include <linux/ip.h>
8461+#include <net/ip.h>
8462+#include <net/tcp.h>
8463+#include <net/icmp.h>
8464+struct in_device;
8465+#include <net/route.h>
8466+#include <linux/random.h>
8467+#include <linux/netfilter_ipv4/ip_tables.h>
8468+
8469+#if 0
8470+#define DEBUGP printk
8471+#else
8472+#define DEBUGP(format, args...)
8473+#endif
8474+
8475+MODULE_LICENSE("GPL");
8476+MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
8477+
8478+/* Stolen from ip_finish_output2 */
8479+static int ip_direct_send(struct sk_buff *skb)
8480+{
8481+ struct dst_entry *dst = skb->dst;
8482+ struct hh_cache *hh = dst->hh;
8483+
8484+ if (hh) {
8485+ read_lock_bh(&hh->hh_lock);
8486+ memcpy(skb->data - 16, hh->hh_data, 16);
8487+ read_unlock_bh(&hh->hh_lock);
8488+ skb_push(skb, hh->hh_len);
8489+ return hh->hh_output(skb);
8490+ } else if (dst->neighbour)
8491+ return dst->neighbour->output(skb);
8492+
8493+ if (net_ratelimit())
8494+ printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
8495+ kfree_skb(skb);
8496+ return -EINVAL;
8497+}
8498+
8499+
8500+/* Send reply */
8501+static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
8502+{
8503+ struct sk_buff *nskb;
8504+ struct rtable *nrt;
8505+ struct tcphdr *otcph, *ntcph;
8506+ unsigned int otcplen;
8507+ u_int16_t tmp;
8508+ struct flowi fl = {};
8509+
8510+ /* A truncated TCP header isn't going to be useful */
8511+ if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
8512+ return;
8513+
8514+ otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
8515+ + oskb->nh.iph->ihl);
8516+ otcplen = oskb->len - oskb->nh.iph->ihl*4;
8517+
8518+ /* No replies for RST or FIN */
8519+ if (otcph->rst || otcph->fin)
8520+ return;
8521+
8522+ /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
8523+ if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
8524+ return;
8525+
8526+ /* Check checksum. */
8527+ if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
8528+ oskb->nh.iph->daddr,
8529+ csum_partial((char *)otcph, otcplen, 0)) != 0)
8530+ return;
8531+
8532+ /* Copy skb (even if skb is about to be dropped, we can't just
8533+ clone it because there may be other things, such as tcpdump,
8534+ interested in it) */
8535+ nskb = skb_copy(oskb, GFP_ATOMIC);
8536+ if (!nskb)
8537+ return;
8538+
8539+ /* This packet will not be the same as the other: clear nf fields */
8540+ nf_conntrack_put(nskb->nfct);
8541+ nskb->nfct = NULL;
8542+ nskb->nfcache = 0;
8543+#ifdef CONFIG_NETFILTER_DEBUG
8544+ nskb->nf_debug = 0;
8545+#endif
8546+
8547+ ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
8548+
8549+ /* Truncate to length (no data) */
8550+ ntcph->doff = sizeof(struct tcphdr)/4;
8551+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
8552+ nskb->nh.iph->tot_len = htons(nskb->len);
8553+
8554+ /* Swap source and dest */
8555+ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
8556+ tmp = ntcph->source;
8557+ ntcph->source = ntcph->dest;
8558+ ntcph->dest = tmp;
8559+
8560+ /* Use supplied sequence number or make a new one */
8561+ ntcph->seq = otcph->ack ? otcph->ack_seq
8562+ : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
8563+ nskb->nh.iph->daddr,
8564+ ntcph->source,
8565+ ntcph->dest));
8566+
8567+ /* Our SYN-ACKs must have a >0 window */
8568+ ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
8569+
8570+ ntcph->urg_ptr = 0;
8571+
8572+ /* Reset flags */
8573+ ((u_int8_t *)ntcph)[13] = 0;
8574+
8575+ if (otcph->syn && otcph->ack) {
8576+ ntcph->rst = 1;
8577+ ntcph->ack_seq = 0;
8578+ } else {
8579+ ntcph->syn = otcph->syn;
8580+ ntcph->ack = 1;
8581+ ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
8582+ }
8583+
8584+ /* Adjust TCP checksum */
8585+ ntcph->check = 0;
8586+ ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
8587+ nskb->nh.iph->saddr,
8588+ nskb->nh.iph->daddr,
8589+ csum_partial((char *)ntcph,
8590+ sizeof(struct tcphdr), 0));
8591+
8592+ /* Adjust IP TTL */
8593+ nskb->nh.iph->ttl = sysctl_ip_default_ttl;
8594+
8595+ /* Set DF, id = 0 */
8596+ nskb->nh.iph->frag_off = htons(IP_DF);
8597+ nskb->nh.iph->id = 0;
8598+
8599+ /* Adjust IP checksum */
8600+ nskb->nh.iph->check = 0;
8601+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
8602+ nskb->nh.iph->ihl);
8603+
8604+ fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
8605+ fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
8606+ fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
8607+ fl.oif = 0;
8608+ if (ip_route_output_key(&nrt, &fl) != 0)
8609+ goto free_nskb;
8610+
8611+ dst_release(nskb->dst);
8612+ nskb->dst = &nrt->u.dst;
8613+
8614+ /* "Never happens" */
8615+ if (nskb->len > dst_pmtu(nskb->dst))
8616+ goto free_nskb;
8617+
8618+ ip_direct_send (nskb);
8619+
8620+ return;
8621+
8622+ free_nskb:
8623+ kfree_skb(nskb);
8624+}
8625+
8626+
8627+static unsigned int tarpit(struct sk_buff **pskb,
8628+ const struct net_device *in,
8629+ const struct net_device *out,
8630+ unsigned int hooknum,
8631+ const void *targinfo,
8632+ void *userinfo)
8633+{
8634+ struct sk_buff *skb = *pskb;
8635+ struct rtable *rt = (struct rtable*)skb->dst;
8636+
8637+ /* Do we have an input route cache entry? */
8638+ if (!rt)
8639+ return NF_DROP;
8640+
8641+ /* No replies to physical multicast/broadcast */
8642+ if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
8643+ return NF_DROP;
8644+
8645+ /* Now check at the protocol level */
8646+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
8647+ return NF_DROP;
8648+
8649+ /* Our naive response construction doesn't deal with IP
8650+ options, and probably shouldn't try. */
8651+ if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
8652+ return NF_DROP;
8653+
8654+ /* We aren't interested in fragments */
8655+ if (skb->nh.iph->frag_off & htons(IP_OFFSET))
8656+ return NF_DROP;
8657+
8658+ tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
8659+
8660+ return NF_DROP;
8661+}
8662+
8663+
8664+static int check(const char *tablename,
8665+ const struct ipt_entry *e,
8666+ void *targinfo,
8667+ unsigned int targinfosize,
8668+ unsigned int hook_mask)
8669+{
8670+ /* Only allow these for input/forward packet filtering. */
8671+ if (strcmp(tablename, "filter") != 0) {
8672+ DEBUGP("TARPIT: bad table %s'.\n", tablename);
8673+ return 0;
8674+ }
8675+ if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
8676+ | (1 << NF_IP_FORWARD))) != 0) {
8677+ DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
8678+ return 0;
8679+ }
8680+
8681+ /* Must specify that it's a TCP packet */
8682+ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
8683+ DEBUGP("TARPIT: not valid for non-tcp\n");
8684+ return 0;
8685+ }
8686+
8687+ return 1;
8688+}
8689+
8690+static struct ipt_target ipt_tarpit_reg = {
8691+ .name = "TARPIT",
8692+ .target = tarpit,
8693+ .checkentry = check,
8694+ .me = THIS_MODULE
8695+};
8696+
8697+static int __init init(void)
8698+{
8699+ return ipt_register_target(&ipt_tarpit_reg);
8700+}
8701+
8702+static void __exit fini(void)
8703+{
8704+ ipt_unregister_target(&ipt_tarpit_reg);
8705+}
8706+
8707+module_init(init);
8708+module_exit(fini);
8709diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c
8710--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
8711+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c 2004-04-29 11:17:15.000000000 +0200
8712@@ -0,0 +1,64 @@
8713+/* This is a module which is used for setting
8714+ * the NFC_TRACE flag in the nfcache field of an skb.
8715+ */
8716+#include <linux/module.h>
8717+#include <linux/skbuff.h>
8718+
8719+#include <linux/netfilter_ipv4/ip_tables.h>
8720+
8721+static unsigned int
8722+target(struct sk_buff **pskb,
8723+ const struct net_device *in,
8724+ const struct net_device *out,
8725+ unsigned int hooknum,
8726+ const void *targinfo,
8727+ void *userinfo)
8728+{
8729+ (*pskb)->nfcache |= NFC_TRACE;
8730+ return IPT_CONTINUE;
8731+}
8732+
8733+static int
8734+checkentry(const char *tablename,
8735+ const struct ipt_entry *e,
8736+ void *targinfo,
8737+ unsigned int targinfosize,
8738+ unsigned int hook_mask)
8739+{
8740+ if (targinfosize != 0) {
8741+ printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
8742+ targinfosize);
8743+ return 0;
8744+ }
8745+
8746+ if (strcmp(tablename, "raw") != 0) {
8747+ printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
8748+ return 0;
8749+ }
8750+
8751+ return 1;
8752+}
8753+
8754+static struct ipt_target ipt_trace_reg = {
8755+ .name = "TRACE",
8756+ .target = target,
8757+ .checkentry = checkentry,
8758+ .me = THIS_MODULE
8759+};
8760+
8761+static int __init init(void)
8762+{
8763+ if (ipt_register_target(&ipt_trace_reg))
8764+ return -EINVAL;
8765+
8766+ return 0;
8767+}
8768+
8769+static void __exit fini(void)
8770+{
8771+ ipt_unregister_target(&ipt_trace_reg);
8772+}
8773+
8774+module_init(init);
8775+module_exit(fini);
8776+MODULE_LICENSE("GPL");
8777diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c
8778--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
8779+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c 2004-04-29 11:17:18.000000000 +0200
8780@@ -0,0 +1,117 @@
8781+/* XOR target for IP tables
8782+ * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
8783+ * Based on ipt_TTL.c
8784+ *
8785+ * Version 1.0
8786+ *
8787+ * This software is distributed under the terms of GNU GPL
8788+ */
8789+
8790+#include <linux/module.h>
8791+#include <linux/skbuff.h>
8792+#include <linux/ip.h>
8793+#include <linux/tcp.h>
8794+#include <linux/udp.h>
8795+
8796+#include <linux/netfilter_ipv4/ip_tables.h>
8797+#include <linux/netfilter_ipv4/ipt_XOR.h>
8798+
8799+MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
8800+MODULE_DESCRIPTION("IP tables XOR module");
8801+MODULE_LICENSE("GPL");
8802+
8803+static unsigned int
8804+ipt_xor_target(struct sk_buff **pskb,
8805+ const struct net_device *in, const struct net_device *out,
8806+ unsigned int hooknum, const void *targinfo, void *userinfo)
8807+{
8808+ struct ipt_XOR_info *info = (void *) targinfo;
8809+ struct iphdr *iph;
8810+ struct tcphdr *tcph;
8811+ struct udphdr *udph;
8812+ int i, j, k;
8813+
8814+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
8815+ return NF_DROP;
8816+
8817+ iph = (*pskb)->nh.iph;
8818+
8819+ if (iph->protocol == IPPROTO_TCP) {
8820+ tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
8821+ for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
8822+ for (k=0; k<=info->block_size; k++) {
8823+ (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
8824+ info->key[j];
8825+ i++;
8826+ }
8827+ j++;
8828+ if (info->key[j] == 0x00)
8829+ j = 0;
8830+ }
8831+ } else if (iph->protocol == IPPROTO_UDP) {
8832+ udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
8833+ for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
8834+ for (k=0; k<=info->block_size; k++) {
8835+ (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
8836+ info->key[j];
8837+ i++;
8838+ }
8839+ j++;
8840+ if (info->key[j] == 0x00)
8841+ j = 0;
8842+ }
8843+ }
8844+
8845+ return IPT_CONTINUE;
8846+}
8847+
8848+static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
8849+ void *targinfo, unsigned int targinfosize,
8850+ unsigned int hook_mask)
8851+{
8852+ struct ipt_XOR_info *info = targinfo;
8853+
8854+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
8855+ printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
8856+ targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
8857+ return 0;
8858+ }
8859+
8860+ if (strcmp(tablename, "mangle")) {
8861+ printk(KERN_WARNING "XOR: can only be called from"
8862+ "\"mangle\" table, not \"%s\"\n", tablename);
8863+ return 0;
8864+ }
8865+
8866+ if (!strcmp(info->key, "")) {
8867+ printk(KERN_WARNING "XOR: You must specify a key");
8868+ return 0;
8869+ }
8870+
8871+ if (info->block_size == 0) {
8872+ printk(KERN_WARNING "XOR: You must specify a block-size");
8873+ return 0;
8874+ }
8875+
8876+ return 1;
8877+}
8878+
8879+static struct ipt_target ipt_XOR = {
8880+ .name = "XOR",
8881+ .target = ipt_xor_target,
8882+ .checkentry = ipt_xor_checkentry,
8883+ .me = THIS_MODULE,
8884+};
8885+
8886+static int __init init(void)
8887+{
8888+ return ipt_register_target(&ipt_XOR);
8889+}
8890+
8891+static void __exit fini(void)
8892+{
8893+ ipt_unregister_target(&ipt_XOR);
8894+}
8895+
8896+module_init(init);
8897+module_exit(fini);
8898diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c
8899--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
8900+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c 2004-04-29 11:17:23.000000000 +0200
8901@@ -0,0 +1,68 @@
8902+/*
8903+ * iptables module to match inet_addr_type() of an ip.
8904+ */
8905+
8906+#include <linux/module.h>
8907+#include <linux/skbuff.h>
8908+#include <linux/netdevice.h>
8909+#include <net/route.h>
8910+
8911+#include <linux/netfilter_ipv4/ipt_addrtype.h>
8912+#include <linux/netfilter_ipv4/ip_tables.h>
8913+
8914+MODULE_LICENSE("GPL");
8915+
8916+static inline int match_type(u_int32_t addr, u_int16_t mask)
8917+{
8918+ return !!(mask & (1 << inet_addr_type(addr)));
8919+}
8920+
8921+static int match(const struct sk_buff *skb, const struct net_device *in,
8922+ const struct net_device *out, const void *matchinfo,
8923+ int offset, int *hotdrop)
8924+{
8925+ const struct ipt_addrtype_info *info = matchinfo;
8926+ const struct iphdr *iph = skb->nh.iph;
8927+ int ret = 1;
8928+
8929+ if (info->source)
8930+ ret &= match_type(iph->saddr, info->source)^info->invert_source;
8931+ if (info->dest)
8932+ ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
8933+
8934+ return ret;
8935+}
8936+
8937+static int checkentry(const char *tablename, const struct ipt_ip *ip,
8938+ void *matchinfo, unsigned int matchsize,
8939+ unsigned int hook_mask)
8940+{
8941+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
8942+ printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
8943+ matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
8944+ return 0;
8945+ }
8946+
8947+ return 1;
8948+}
8949+
8950+static struct ipt_match addrtype_match = {
8951+ .name = "addrtype",
8952+ .match = match,
8953+ .checkentry = checkentry,
8954+ .me = THIS_MODULE
8955+};
8956+
8957+static int __init init(void)
8958+{
8959+ return ipt_register_match(&addrtype_match);
8960+}
8961+
8962+static void __exit fini(void)
8963+{
8964+ ipt_unregister_match(&addrtype_match);
8965+
8966+}
8967+
8968+module_init(init);
8969+module_exit(fini);
8970diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c
8971--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
8972+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c 2004-04-29 11:10:59.000000000 +0200
8973@@ -0,0 +1,81 @@
8974+/* This kernel module matches connection mark values set by the
8975+ * CONNMARK target
8976+ *
8977+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8978+ * by Henrik Nordstrom <hno@marasystems.com>
8979+ *
8980+ * This program is free software; you can redistribute it and/or modify
8981+ * it under the terms of the GNU General Public License as published by
8982+ * the Free Software Foundation; either version 2 of the License, or
8983+ * (at your option) any later version.
8984+ *
8985+ * This program is distributed in the hope that it will be useful,
8986+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8987+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8988+ * GNU General Public License for more details.
8989+ *
8990+ * You should have received a copy of the GNU General Public License
8991+ * along with this program; if not, write to the Free Software
8992+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8993+ */
8994+
8995+#include <linux/module.h>
8996+#include <linux/skbuff.h>
8997+
8998+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8999+MODULE_DESCRIPTION("IP tables connmark match module");
9000+MODULE_LICENSE("GPL");
9001+
9002+#include <linux/netfilter_ipv4/ip_tables.h>
9003+#include <linux/netfilter_ipv4/ipt_connmark.h>
9004+#include <linux/netfilter_ipv4/ip_conntrack.h>
9005+
9006+static int
9007+match(const struct sk_buff *skb,
9008+ const struct net_device *in,
9009+ const struct net_device *out,
9010+ const void *matchinfo,
9011+ int offset,
9012+ int *hotdrop)
9013+{
9014+ const struct ipt_connmark_info *info = matchinfo;
9015+ enum ip_conntrack_info ctinfo;
9016+ struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
9017+ if (!ct)
9018+ return 0;
9019+
9020+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
9021+}
9022+
9023+static int
9024+checkentry(const char *tablename,
9025+ const struct ipt_ip *ip,
9026+ void *matchinfo,
9027+ unsigned int matchsize,
9028+ unsigned int hook_mask)
9029+{
9030+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
9031+ return 0;
9032+
9033+ return 1;
9034+}
9035+
9036+static struct ipt_match connmark_match = {
9037+ .name = "connmark",
9038+ .match = &match,
9039+ .checkentry = &checkentry,
9040+ .me = THIS_MODULE
9041+};
9042+
9043+static int __init init(void)
9044+{
9045+ return ipt_register_match(&connmark_match);
9046+}
9047+
9048+static void __exit fini(void)
9049+{
9050+ ipt_unregister_match(&connmark_match);
9051+}
9052+
9053+module_init(init);
9054+module_exit(fini);
9055diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c
9056--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-04-29 11:24:39.000000000 +0200
9057+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c 2004-04-29 11:18:37.000000000 +0200
9058@@ -71,8 +71,11 @@
9059 DEBUGP("master's name = %s , info->name = %s\n",
9060 exp->expectant->helper->name, info->name);
9061
9062- ret ^= !strncmp(exp->expectant->helper->name, info->name,
9063- strlen(exp->expectant->helper->name));
9064+ if (info->name[0] == '\0')
9065+ ret ^= 1;
9066+ else
9067+ ret ^= !strncmp(exp->expectant->helper->name, info->name,
9068+ strlen(exp->expectant->helper->name));
9069 out_unlock:
9070 READ_UNLOCK(&ip_conntrack_lock);
9071 return ret;
9072@@ -92,10 +95,6 @@
9073 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
9074 return 0;
9075
9076- /* verify that we actually should match anything */
9077- if ( strlen(info->name) == 0 )
9078- return 0;
9079-
9080 return 1;
9081 }
9082
9083diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c
9084--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c 2004-04-28 03:36:37.000000000 +0200
9085+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c 2004-04-29 11:19:32.000000000 +0200
9086@@ -6,12 +6,19 @@
9087 * This program is free software; you can redistribute it and/or modify
9088 * it under the terms of the GNU General Public License version 2 as
9089 * published by the Free Software Foundation.
9090+ *
9091+ * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
9092 */
9093
9094 #include <linux/module.h>
9095 #include <linux/skbuff.h>
9096 #include <linux/file.h>
9097+#include <linux/ip.h>
9098+#include <linux/tcp.h>
9099+#include <linux/udp.h>
9100 #include <net/sock.h>
9101+#include <net/tcp.h>
9102+#include <net/udp.h>
9103
9104 #include <linux/netfilter_ipv4/ipt_owner.h>
9105 #include <linux/netfilter_ipv4/ip_tables.h>
9106@@ -21,7 +28,7 @@
9107 MODULE_DESCRIPTION("iptables owner match");
9108
9109 static int
9110-match_comm(const struct sk_buff *skb, const char *comm)
9111+match_comm(const struct sock *sk, const char *comm)
9112 {
9113 struct task_struct *g, *p;
9114 struct files_struct *files;
9115@@ -38,7 +45,7 @@
9116 spin_lock(&files->file_lock);
9117 for (i=0; i < files->max_fds; i++) {
9118 if (fcheck_files(files, i) ==
9119- skb->sk->sk_socket->file) {
9120+ sk->sk_socket->file) {
9121 spin_unlock(&files->file_lock);
9122 task_unlock(p);
9123 read_unlock(&tasklist_lock);
9124@@ -54,7 +61,7 @@
9125 }
9126
9127 static int
9128-match_pid(const struct sk_buff *skb, pid_t pid)
9129+match_pid(const struct sock *sk, pid_t pid)
9130 {
9131 struct task_struct *p;
9132 struct files_struct *files;
9133@@ -70,7 +77,7 @@
9134 spin_lock(&files->file_lock);
9135 for (i=0; i < files->max_fds; i++) {
9136 if (fcheck_files(files, i) ==
9137- skb->sk->sk_socket->file) {
9138+ sk->sk_socket->file) {
9139 spin_unlock(&files->file_lock);
9140 task_unlock(p);
9141 read_unlock(&tasklist_lock);
9142@@ -86,10 +93,10 @@
9143 }
9144
9145 static int
9146-match_sid(const struct sk_buff *skb, pid_t sid)
9147+match_sid(const struct sock *sk, pid_t sid)
9148 {
9149 struct task_struct *g, *p;
9150- struct file *file = skb->sk->sk_socket->file;
9151+ struct file *file = sk->sk_socket->file;
9152 int i, found=0;
9153
9154 read_lock(&tasklist_lock);
9155@@ -129,41 +136,71 @@
9156 int *hotdrop)
9157 {
9158 const struct ipt_owner_info *info = matchinfo;
9159+ struct iphdr *iph = skb->nh.iph;
9160+ struct sock *sk = NULL;
9161+ int ret = 0;
9162+
9163+ if (out) {
9164+ sk = skb->sk;
9165+ } else {
9166+ if (iph->protocol == IPPROTO_TCP) {
9167+ struct tcphdr *tcph =
9168+ (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
9169+ sk = tcp_v4_lookup(iph->saddr, tcph->source,
9170+ iph->daddr, tcph->dest,
9171+ skb->dev->ifindex);
9172+ if (sk && sk->sk_state == TCP_TIME_WAIT) {
9173+ tcp_tw_put((struct tcp_tw_bucket *)sk);
9174+ return ret;
9175+ }
9176+ } else if (iph->protocol == IPPROTO_UDP) {
9177+ struct udphdr *udph =
9178+ (struct udphdr *)((u_int32_t *)iph + iph->ihl);
9179+ sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
9180+ udph->dest, skb->dev->ifindex);
9181+ }
9182+ }
9183
9184- if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
9185- return 0;
9186+ if (!sk || !sk->sk_socket || !sk->sk_socket->file)
9187+ goto out;
9188
9189 if(info->match & IPT_OWNER_UID) {
9190- if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
9191+ if ((sk->sk_socket->file->f_uid != info->uid) ^
9192 !!(info->invert & IPT_OWNER_UID))
9193- return 0;
9194+ goto out;
9195 }
9196
9197 if(info->match & IPT_OWNER_GID) {
9198- if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
9199+ if ((sk->sk_socket->file->f_gid != info->gid) ^
9200 !!(info->invert & IPT_OWNER_GID))
9201- return 0;
9202+ goto out;
9203 }
9204
9205 if(info->match & IPT_OWNER_PID) {
9206- if (!match_pid(skb, info->pid) ^
9207+ if (!match_pid(sk, info->pid) ^
9208 !!(info->invert & IPT_OWNER_PID))
9209- return 0;
9210+ goto out;
9211 }
9212
9213 if(info->match & IPT_OWNER_SID) {
9214- if (!match_sid(skb, info->sid) ^
9215+ if (!match_sid(sk, info->sid) ^
9216 !!(info->invert & IPT_OWNER_SID))
9217- return 0;
9218+ goto out;
9219 }
9220
9221 if(info->match & IPT_OWNER_COMM) {
9222- if (!match_comm(skb, info->comm) ^
9223+ if (!match_comm(sk, info->comm) ^
9224 !!(info->invert & IPT_OWNER_COMM))
9225- return 0;
9226+ goto out;
9227 }
9228
9229- return 1;
9230+ ret = 1;
9231+
9232+out:
9233+ if (in && sk)
9234+ sock_put(sk);
9235+
9236+ return ret;
9237 }
9238
9239 static int
9240@@ -173,11 +210,19 @@
9241 unsigned int matchsize,
9242 unsigned int hook_mask)
9243 {
9244- if (hook_mask
9245- & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
9246- printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
9247- return 0;
9248- }
9249+ if (hook_mask
9250+ & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
9251+ (1 << NF_IP_LOCAL_IN))) {
9252+ printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
9253+ "or POST_ROUTING.\n");
9254+ return 0;
9255+ }
9256+
9257+ if ((hook_mask & (1 << NF_IP_LOCAL_IN))
9258+ && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
9259+ printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
9260+ return 0;
9261+ }
9262
9263 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
9264 printk("Matchsize %u != %Zu\n", matchsize,
9265diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c
9266--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
9267+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c 2004-04-29 11:19:41.000000000 +0200
9268@@ -0,0 +1,176 @@
9269+/* IP tables module for matching IPsec policy
9270+ *
9271+ * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
9272+ *
9273+ * This program is free software; you can redistribute it and/or modify
9274+ * it under the terms of the GNU General Public License version 2 as
9275+ * published by the Free Software Foundation.
9276+ */
9277+
9278+#include <linux/kernel.h>
9279+#include <linux/config.h>
9280+#include <linux/module.h>
9281+#include <linux/skbuff.h>
9282+#include <linux/init.h>
9283+#include <net/xfrm.h>
9284+
9285+#include <linux/netfilter_ipv4.h>
9286+#include <linux/netfilter_ipv4/ipt_policy.h>
9287+#include <linux/netfilter_ipv4/ip_tables.h>
9288+
9289+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
9290+MODULE_DESCRIPTION("IPtables IPsec policy matching module");
9291+MODULE_LICENSE("GPL");
9292+
9293+
9294+static inline int
9295+match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
9296+{
9297+#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
9298+
9299+ if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
9300+ MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
9301+ MISMATCH(proto, x->id.proto) ||
9302+ MISMATCH(mode, x->props.mode) ||
9303+ MISMATCH(spi, x->id.spi) ||
9304+ MISMATCH(reqid, x->props.reqid))
9305+ return 0;
9306+ return 1;
9307+}
9308+
9309+static int
9310+match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
9311+{
9312+ const struct ipt_policy_elem *e;
9313+ struct sec_path *sp = skb->sp;
9314+ int strict = info->flags & POLICY_MATCH_STRICT;
9315+ int i, pos;
9316+
9317+ if (sp == NULL)
9318+ return -1;
9319+ if (strict && info->len != sp->len)
9320+ return 0;
9321+
9322+ for (i = sp->len - 1; i >= 0; i--) {
9323+ pos = strict ? i - sp->len + 1 : 0;
9324+ if (pos >= info->len)
9325+ return 0;
9326+ e = &info->pol[pos];
9327+
9328+ if (match_xfrm_state(sp->x[i].xvec, e)) {
9329+ if (!strict)
9330+ return 1;
9331+ } else if (strict)
9332+ return 0;
9333+ }
9334+
9335+ return strict ? 1 : 0;
9336+}
9337+
9338+static int
9339+match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
9340+{
9341+ const struct ipt_policy_elem *e;
9342+ struct dst_entry *dst = skb->dst;
9343+ int strict = info->flags & POLICY_MATCH_STRICT;
9344+ int i, pos;
9345+
9346+ if (dst->xfrm == NULL)
9347+ return -1;
9348+
9349+ for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
9350+ pos = strict ? i : 0;
9351+ if (pos >= info->len)
9352+ return 0;
9353+ e = &info->pol[pos];
9354+
9355+ if (match_xfrm_state(dst->xfrm, e)) {
9356+ if (!strict)
9357+ return 1;
9358+ } else if (strict)
9359+ return 0;
9360+ }
9361+
9362+ return strict ? 1 : 0;
9363+}
9364+
9365+static int match(const struct sk_buff *skb,
9366+ const struct net_device *in,
9367+ const struct net_device *out,
9368+ const void *matchinfo, int offset, int *hotdrop)
9369+{
9370+ const struct ipt_policy_info *info = matchinfo;
9371+ int ret;
9372+
9373+ if (info->flags & POLICY_MATCH_IN)
9374+ ret = match_policy_in(skb, info);
9375+ else
9376+ ret = match_policy_out(skb, info);
9377+
9378+ if (ret < 0) {
9379+ if (info->flags & POLICY_MATCH_NONE)
9380+ ret = 1;
9381+ else
9382+ ret = 0;
9383+ } else if (info->flags & POLICY_MATCH_NONE)
9384+ ret = 0;
9385+
9386+ return ret;
9387+}
9388+
9389+static int checkentry(const char *tablename, const struct ipt_ip *ip,
9390+ void *matchinfo, unsigned int matchsize,
9391+ unsigned int hook_mask)
9392+{
9393+ struct ipt_policy_info *info = matchinfo;
9394+
9395+ if (matchsize != IPT_ALIGN(sizeof(*info))) {
9396+ printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
9397+ matchsize, IPT_ALIGN(sizeof(*info)));
9398+ return 0;
9399+ }
9400+ if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
9401+ printk(KERN_ERR "ipt_policy: neither incoming nor "
9402+ "outgoing policy selected\n");
9403+ return 0;
9404+ }
9405+ if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
9406+ && info->flags & POLICY_MATCH_OUT) {
9407+ printk(KERN_ERR "ipt_policy: output policy not valid in "
9408+ "PRE_ROUTING and INPUT\n");
9409+ return 0;
9410+ }
9411+ if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
9412+ && info->flags & POLICY_MATCH_IN) {
9413+ printk(KERN_ERR "ipt_policy: input policy not valid in "
9414+ "POST_ROUTING and OUTPUT\n");
9415+ return 0;
9416+ }
9417+ if (info->len > POLICY_MAX_ELEM) {
9418+ printk(KERN_ERR "ipt_policy: too many policy elements\n");
9419+ return 0;
9420+ }
9421+
9422+ return 1;
9423+}
9424+
9425+static struct ipt_match policy_match =
9426+{
9427+ .name = "policy",
9428+ .match = match,
9429+ .checkentry = checkentry,
9430+ .me = THIS_MODULE,
9431+};
9432+
9433+static int __init init(void)
9434+{
9435+ return ipt_register_match(&policy_match);
9436+}
9437+
9438+static void __exit fini(void)
9439+{
9440+ ipt_unregister_match(&policy_match);
9441+}
9442+
9443+module_init(init);
9444+module_exit(fini);
9445diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_rpc.c
9446--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
9447+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_rpc.c 2004-04-29 11:20:02.000000000 +0200
9448@@ -0,0 +1,428 @@
9449+/* RPC extension for IP connection matching, Version 2.2
9450+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
9451+ * - original rpc tracking module
9452+ * - "recent" connection handling for kernel 2.3+ netfilter
9453+ *
9454+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
9455+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
9456+ *
9457+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
9458+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
9459+ * - extended matching to support filtering on procedures
9460+ *
9461+ * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
9462+ *
9463+ * This program is free software; you can redistribute it and/or
9464+ * modify it under the terms of the GNU General Public License
9465+ * as published by the Free Software Foundation; either version
9466+ * 2 of the License, or (at your option) any later version.
9467+ **
9468+ * Module load syntax:
9469+ * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
9470+ *
9471+ * Please give the ports of all RPC servers you wish to connect to.
9472+ * If you don't specify ports, the default will be port 111.
9473+ **
9474+ * Note to all:
9475+ *
9476+ * RPCs should not be exposed to the internet - ask the Pentagon;
9477+ *
9478+ * "The unidentified crackers pleaded guilty in July to charges
9479+ * of juvenile delinquency stemming from a string of Pentagon
9480+ * network intrusions in February.
9481+ *
9482+ * The youths, going by the names TooShort and Makaveli, used
9483+ * a common server security hole to break in, according to
9484+ * Dane Jasper, owner of the California Internet service
9485+ * provider, Sonic. They used the hole, known as the 'statd'
9486+ * exploit, to attempt more than 800 break-ins, Jasper said."
9487+ *
9488+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
9489+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
9490+ **
9491+ */
9492+
9493+#include <linux/module.h>
9494+#include <linux/skbuff.h>
9495+#include <linux/list.h>
9496+#include <linux/udp.h>
9497+#include <linux/tcp.h>
9498+#include <linux/netfilter_ipv4/ip_conntrack.h>
9499+#include <linux/netfilter_ipv4/ip_tables.h>
9500+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
9501+#include <linux/netfilter_ipv4/lockhelp.h>
9502+#include <linux/netfilter_ipv4/ipt_rpc.h>
9503+
9504+#define MAX_PORTS 8
9505+static int ports[MAX_PORTS];
9506+static int ports_n_c = 0;
9507+
9508+#ifdef MODULE_PARM
9509+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9510+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
9511+#endif
9512+
9513+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
9514+MODULE_DESCRIPTION("RPC connection matching module");
9515+MODULE_LICENSE("GPL");
9516+
9517+#if 0
9518+#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
9519+ format, ## args)
9520+#else
9521+#define DEBUGP(format, args...)
9522+#endif
9523+
9524+EXPORT_NO_SYMBOLS;
9525+
9526+/* vars from ip_conntrack_rpc_tcp */
9527+extern struct list_head request_p_list_tcp;
9528+extern struct module *ip_conntrack_rpc_tcp;
9529+
9530+/* vars from ip_conntrack_rpc_udp */
9531+extern struct list_head request_p_list_udp;
9532+extern struct module *ip_conntrack_rpc_udp;
9533+
9534+DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
9535+DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
9536+
9537+#define ASSERT_READ_LOCK(x) \
9538+do { \
9539+ if (x == &request_p_list_udp) \
9540+ MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
9541+ else if (x == &request_p_list_tcp) \
9542+ MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
9543+} while (0)
9544+
9545+#define ASSERT_WRITE_LOCK(x) \
9546+do { \
9547+ if (x == &request_p_list_udp) \
9548+ MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
9549+ else if (x == &request_p_list_tcp) \
9550+ MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
9551+} while (0)
9552+
9553+#include <linux/netfilter_ipv4/listhelp.h>
9554+
9555+const int IPT_RPC_CHAR_LEN = 11;
9556+
9557+
9558+static int k_atoi(char *string)
9559+{
9560+ unsigned int result = 0;
9561+ int maxoctet = IPT_RPC_CHAR_LEN;
9562+
9563+ for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
9564+ if (*string < 0)
9565+ return(0);
9566+ if (*string == 0)
9567+ break;
9568+ if (*string < 48 || *string > 57) {
9569+ return(0);
9570+ }
9571+ result = result * 10 + ( *string - 48 );
9572+ }
9573+ return(result);
9574+}
9575+
9576+
9577+static int match_rpcs(char *c_procs, int i_procs, int proc)
9578+{
9579+ int proc_ctr;
9580+ char *proc_ptr;
9581+ unsigned int proc_num;
9582+
9583+ DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
9584+
9585+ if (i_procs == -1)
9586+ return 1;
9587+
9588+ for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
9589+
9590+ proc_ptr = c_procs;
9591+ proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
9592+ proc_num = k_atoi(proc_ptr);
9593+
9594+ if (proc_num == proc)
9595+ return 1;
9596+ }
9597+
9598+ return 0;
9599+}
9600+
9601+
9602+static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
9603+ int *hotdrop, int dir, struct ip_conntrack *ct,
9604+ int offset, struct list_head request_p_list)
9605+{
9606+ const struct ipt_rpc_info *rpcinfo = matchinfo;
9607+ struct request_p *req_p;
9608+ u_int32_t xid;
9609+
9610+
9611+ /* Get XID */
9612+ xid = *data;
9613+
9614+ /* This does sanity checking on RPC payloads,
9615+ * and permits only the RPC "get port" (3)
9616+ * in authorised procedures in client
9617+ * communications with the portmapper.
9618+ */
9619+
9620+ data += 5;
9621+
9622+ /* Get RPC requestor */
9623+ if (IXDR_GET_INT32(data) != 3) {
9624+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
9625+ if(rpcinfo->strict == 1)
9626+ *hotdrop = 1;
9627+ return 0;
9628+ }
9629+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
9630+
9631+ data++;
9632+
9633+ /* Jump Credentials and Verfifier */
9634+ data = data + IXDR_GET_INT32(data) + 2;
9635+ data = data + IXDR_GET_INT32(data) + 2;
9636+
9637+ /* Get RPC procedure */
9638+ if (match_rpcs((char *)&rpcinfo->c_procs,
9639+ rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
9640+ DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
9641+ (unsigned int)IXDR_GET_INT32(data));
9642+
9643+ /* If the RPC conntrack half entry already exists .. */
9644+
9645+ switch (ct->tuplehash[0].tuple.dst.protonum) {
9646+ case IPPROTO_UDP:
9647+ WRITE_LOCK(&ipct_rpc_udp_lock);
9648+ case IPPROTO_TCP:
9649+ WRITE_LOCK(&ipct_rpc_tcp_lock);
9650+ }
9651+ req_p = LIST_FIND(&request_p_list, request_p_cmp,
9652+ struct request_p *, xid,
9653+ ct->tuplehash[dir].tuple.src.ip,
9654+ ct->tuplehash[dir].tuple.src.u.all);
9655+
9656+ if (req_p) {
9657+ DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
9658+ xid, ct->tuplehash[dir].tuple.dst.protonum,
9659+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
9660+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
9661+
9662+ /* .. remove it */
9663+ if (del_timer(&req_p->timeout))
9664+ req_p->timeout.expires = 0;
9665+
9666+ LIST_DELETE(&request_p_list, req_p);
9667+ DEBUGP("RPC req_p removed. [done]\n");
9668+
9669+ } else {
9670+ DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
9671+ xid, ct->tuplehash[dir].tuple.dst.protonum,
9672+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
9673+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
9674+
9675+ }
9676+ switch (ct->tuplehash[0].tuple.dst.protonum) {
9677+ case IPPROTO_UDP:
9678+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
9679+ case IPPROTO_TCP:
9680+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
9681+ }
9682+
9683+ if(rpcinfo->strict == 1)
9684+ *hotdrop = 1;
9685+ return 0;
9686+ }
9687+
9688+ DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
9689+ (unsigned int)IXDR_GET_INT32(data));
9690+ return (1 && (!offset));
9691+}
9692+
9693+
9694+static int match(const struct sk_buff *skb, const struct net_device *in,
9695+ const struct net_device *out, const void *matchinfo,
9696+ int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
9697+{
9698+ struct ip_conntrack *ct;
9699+ enum ip_conntrack_info ctinfo;
9700+ const u_int32_t *data;
9701+ enum ip_conntrack_dir dir;
9702+ const struct tcphdr *tcp;
9703+ const struct ipt_rpc_info *rpcinfo = matchinfo;
9704+ int port, portsok;
9705+ int tval;
9706+
9707+
9708+ DEBUGP("new packet to evaluate ..\n");
9709+
9710+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
9711+ if (!ct) {
9712+ DEBUGP("no ct available [skip]\n");
9713+ return 0;
9714+ }
9715+
9716+ DEBUGP("ct detected. [cont]\n");
9717+ dir = CTINFO2DIR(ctinfo);
9718+
9719+ /* we only want the client to server packets for matching */
9720+ if (dir != IP_CT_DIR_ORIGINAL)
9721+ return 0;
9722+
9723+ /* This does sanity checking on UDP or TCP packets,
9724+ * like their respective modules.
9725+ */
9726+
9727+ switch (ct->tuplehash[0].tuple.dst.protonum) {
9728+
9729+ case IPPROTO_UDP:
9730+ DEBUGP("PROTO_UDP [cont]\n");
9731+ if (offset == 0 && datalen < sizeof(struct udphdr)) {
9732+ DEBUGP("packet does not contain a complete header. [drop]\n");
9733+ return 0;
9734+ }
9735+
9736+ for (port=0,portsok=0; port <= ports_n_c; port++) {
9737+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
9738+ portsok++;
9739+ break;
9740+ }
9741+ }
9742+ if (portsok == 0) {
9743+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
9744+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
9745+ return 0;
9746+ }
9747+
9748+ if ((datalen - sizeof(struct udphdr)) != 56) {
9749+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
9750+ if (rpcinfo->strict == 1)
9751+ *hotdrop = 1;
9752+ return 0;
9753+ }
9754+ DEBUGP("packet length is correct. [cont]\n");
9755+
9756+ /* Get to the data */
9757+ data = (const u_int32_t *)hdr + 2;
9758+
9759+ /* Check the RPC data */
9760+ tval = check_rpc_packet(data, matchinfo, hotdrop,
9761+ dir, ct, offset,
9762+ request_p_list_udp);
9763+
9764+ return tval;
9765+
9766+
9767+ case IPPROTO_TCP:
9768+ DEBUGP("PROTO_TCP [cont]\n");
9769+ if (offset == 0 && datalen < sizeof(struct tcphdr)) {
9770+ DEBUGP("packet does not contain a complete header. [drop]\n");
9771+ return 0;
9772+ }
9773+
9774+ for (port=0,portsok=0; port <= ports_n_c; port++) {
9775+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
9776+ portsok++;
9777+ break;
9778+ }
9779+ }
9780+ if (portsok == 0) {
9781+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
9782+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
9783+ return 0;
9784+ }
9785+
9786+ tcp = hdr;
9787+ if (datalen == (tcp->doff * 4)) {
9788+ DEBUGP("packet does not contain any data. [match]\n");
9789+ return (1 && (!offset));
9790+ }
9791+
9792+ /* Tests if packet len is ok */
9793+ if ((datalen - (tcp->doff * 4)) != 60) {
9794+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
9795+ if(rpcinfo->strict == 1)
9796+ *hotdrop = 1;
9797+ return 0;
9798+ }
9799+ DEBUGP("packet length is correct. [cont]\n");
9800+
9801+ /* Get to the data */
9802+ data = (const u_int32_t *)tcp + tcp->doff + 1;
9803+
9804+ /* Check the RPC data */
9805+ tval = check_rpc_packet(data, matchinfo, hotdrop,
9806+ dir, ct, offset,
9807+ request_p_list_tcp);
9808+
9809+ return tval;
9810+
9811+ }
9812+
9813+ DEBUGP("transport protocol=%u, is not supported [skip]\n",
9814+ ct->tuplehash[0].tuple.dst.protonum);
9815+ return 0;
9816+}
9817+
9818+
9819+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
9820+ unsigned int matchsize, unsigned int hook_mask)
9821+{
9822+ if (hook_mask
9823+ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
9824+ | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
9825+ printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
9826+ return 0;
9827+ }
9828+
9829+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
9830+ return 0;
9831+
9832+ return 1;
9833+}
9834+
9835+
9836+static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
9837+ &match, &checkentry, NULL,
9838+ THIS_MODULE };
9839+
9840+
9841+static int __init init(void)
9842+{
9843+ int port;
9844+
9845+ DEBUGP("incrementing usage counts\n");
9846+ __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
9847+ __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
9848+
9849+ /* If no port given, default to standard RPC port */
9850+ if (ports[0] == 0)
9851+ ports[0] = RPC_PORT;
9852+
9853+ DEBUGP("registering match [%s] for;\n", rpc_match.name);
9854+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
9855+ DEBUGP(" port %i (UDP|TCP);\n", ports[port]);
9856+ ports_n_c++;
9857+ }
9858+
9859+ return ipt_register_match(&rpc_match);
9860+}
9861+
9862+
9863+static void fini(void)
9864+{
9865+ DEBUGP("unregistering match\n");
9866+ ipt_unregister_match(&rpc_match);
9867+
9868+ DEBUGP("decrementing usage counts\n");
9869+ __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
9870+ __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
9871+}
9872+
9873+
9874+module_init(init);
9875+module_exit(fini);
9876+
9877diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c
9878--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
9879+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c 2004-04-29 11:21:38.000000000 +0200
9880@@ -0,0 +1,183 @@
9881+/* Kernel module to match a string into a packet.
9882+ *
9883+ * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
9884+ *
9885+ * ChangeLog
9886+ * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
9887+ * Initial 2.6 port
9888+ * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
9889+ * Fixed SMP re-entrancy problem using per-cpu data areas
9890+ * for the skip/shift tables.
9891+ * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
9892+ * Fixed kernel panic, due to overrunning boyer moore string
9893+ * tables. Also slightly tweaked heuristic for deciding what
9894+ * search algo to use.
9895+ * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
9896+ * Implemented Boyer Moore Sublinear search algorithm
9897+ * alongside the existing linear search based on memcmp().
9898+ * Also a quick check to decide which method to use on a per
9899+ * packet basis.
9900+ */
9901+
9902+#include <linux/smp.h>
9903+#include <linux/percpu.h>
9904+#include <linux/module.h>
9905+#include <linux/skbuff.h>
9906+#include <linux/file.h>
9907+#include <net/sock.h>
9908+
9909+#include <linux/netfilter_ipv4/ip_tables.h>
9910+#include <linux/netfilter_ipv4/ipt_string.h>
9911+
9912+MODULE_LICENSE("GPL");
9913+
9914+struct string_per_cpu {
9915+ int skip[BM_MAX_HLEN];
9916+ int shift[BM_MAX_HLEN];
9917+ int len[BM_MAX_HLEN];
9918+};
9919+
9920+static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
9921+
9922+
9923+/* Boyer Moore Sublinear string search - VERY FAST */
9924+char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
9925+{
9926+ int M1, right_end, sk, sh;
9927+ int ended, j, i;
9928+
9929+ int *skip, *shift, *len;
9930+
9931+ /* use data suitable for this CPU */
9932+ shift=__get_cpu_var(bm_string_data).shift;
9933+ skip=__get_cpu_var(bm_string_data).skip;
9934+ len=__get_cpu_var(bm_string_data).len;
9935+
9936+ /* Setup skip/shift tables */
9937+ M1 = right_end = needle_len-1;
9938+ for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
9939+ for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
9940+
9941+ for (i = 1; i < needle_len; i++) {
9942+ for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
9943+ len[i] = j;
9944+ }
9945+
9946+ shift[0] = 1;
9947+ for (i = 1; i < needle_len; i++) shift[i] = needle_len;
9948+ for (i = M1; i > 0; i--) shift[len[i]] = i;
9949+ ended = 0;
9950+
9951+ for (i = 0; i < needle_len; i++) {
9952+ if (len[i] == M1 - i) ended = i;
9953+ if (ended) shift[i] = ended;
9954+ }
9955+
9956+ /* Do the search*/
9957+ while (right_end < haystack_len)
9958+ {
9959+ for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
9960+ if (i == needle_len) {
9961+ return haystack+(right_end - M1);
9962+ }
9963+
9964+ sk = skip[(int)haystack[right_end - i]];
9965+ sh = shift[i];
9966+ right_end = max(right_end - i + sk, right_end + sh);
9967+ }
9968+
9969+ return NULL;
9970+}
9971+
9972+/* Linear string search based on memcmp() */
9973+char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
9974+{
9975+ char *k = haystack + (haystack_len-needle_len);
9976+ char *t = haystack;
9977+
9978+ while ( t <= k ) {
9979+ if (memcmp(t, needle, needle_len) == 0)
9980+ return t;
9981+ t++;
9982+ }
9983+
9984+ return NULL;
9985+}
9986+
9987+static int
9988+match(const struct sk_buff *skb,
9989+ const struct net_device *in,
9990+ const struct net_device *out,
9991+ const void *matchinfo,
9992+ int offset,
9993+ int *hotdrop)
9994+{
9995+ const struct ipt_string_info *info = matchinfo;
9996+ struct iphdr *ip = skb->nh.iph;
9997+ int hlen, nlen;
9998+ char *needle, *haystack;
9999+ proc_ipt_search search=search_linear;
10000+
10001+ if ( !ip ) return 0;
10002+
10003+ /* get lenghts, and validate them */
10004+ nlen=info->len;
10005+ hlen=ntohs(ip->tot_len)-(ip->ihl*4);
10006+ if ( nlen > hlen ) return 0;
10007+
10008+ needle=(char *)&info->string;
10009+ haystack=(char *)ip+(ip->ihl*4);
10010+
10011+ /* The sublinear search comes in to its own
10012+ * on the larger packets */
10013+ if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
10014+ (nlen>IPT_STRING_NEEDLE_THRESH) ) {
10015+ if ( hlen < BM_MAX_HLEN ) {
10016+ search=search_sublinear;
10017+ }else{
10018+ if (net_ratelimit())
10019+ printk(KERN_INFO "ipt_string: Packet too big "
10020+ "to attempt sublinear string search "
10021+ "(%d bytes)\n", hlen );
10022+ }
10023+ }
10024+
10025+ return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
10026+}
10027+
10028+static int
10029+checkentry(const char *tablename,
10030+ const struct ipt_ip *ip,
10031+ void *matchinfo,
10032+ unsigned int matchsize,
10033+ unsigned int hook_mask)
10034+{
10035+
10036+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
10037+ return 0;
10038+
10039+ return 1;
10040+}
10041+
10042+static struct ipt_match string_match = {
10043+ .name = "string",
10044+ .match = &match,
10045+ .checkentry = &checkentry,
10046+ .me = THIS_MODULE
10047+};
10048+
10049+
10050+static int __init init(void)
10051+{
10052+ return ipt_register_match(&string_match);
10053+}
10054+
10055+static void __exit fini(void)
10056+{
10057+ ipt_unregister_match(&string_match);
10058+}
10059+
10060+module_init(init);
10061+module_exit(fini);
10062+
10063+
10064diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c
10065--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
10066+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c 2004-04-29 11:21:33.000000000 +0200
10067@@ -0,0 +1,604 @@
10068+/* Kernel module to match suspect packets. */
10069+#include <linux/module.h>
10070+#include <linux/skbuff.h>
10071+#include <linux/ip.h>
10072+#include <linux/udp.h>
10073+#include <linux/tcp.h>
10074+#include <linux/icmp.h>
10075+#include <net/checksum.h>
10076+
10077+#include <linux/netfilter_ipv4/ip_tables.h>
10078+
10079+#define limpk(format, args...) \
10080+do { \
10081+ if (net_ratelimit()) \
10082+ printk("ipt_unclean: %s" format, \
10083+ embedded ? "(embedded packet) " : "" , ## args); \
10084+} while(0)
10085+
10086+enum icmp_error_status
10087+{
10088+ ICMP_MAY_BE_ERROR,
10089+ ICMP_IS_ERROR,
10090+ ICMP_NOT_ERROR
10091+};
10092+
10093+struct icmp_info
10094+{
10095+ size_t min_len, max_len;
10096+ enum icmp_error_status err;
10097+ u_int8_t min_code, max_code;
10098+};
10099+
10100+static int
10101+check_ip(struct iphdr *iph, size_t length, int embedded);
10102+
10103+/* ICMP-specific checks. */
10104+static int
10105+check_icmp(const struct icmphdr *icmph,
10106+ u_int16_t datalen,
10107+ unsigned int offset,
10108+ int more_frags,
10109+ int embedded)
10110+{
10111+ static struct icmp_info info[]
10112+ = { [ICMP_ECHOREPLY]
10113+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10114+ [ICMP_DEST_UNREACH]
10115+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
10116+ [ICMP_SOURCE_QUENCH]
10117+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
10118+ [ICMP_REDIRECT]
10119+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
10120+ [ICMP_ECHO]
10121+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10122+ /* Router advertisement. */
10123+ [9]
10124+ = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
10125+ /* Router solicitation. */
10126+ [10]
10127+ = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
10128+ [ICMP_TIME_EXCEEDED]
10129+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
10130+ [ICMP_PARAMETERPROB]
10131+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
10132+ [ICMP_TIMESTAMP]
10133+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10134+ [ICMP_TIMESTAMPREPLY]
10135+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10136+ [ICMP_INFO_REQUEST]
10137+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10138+ [ICMP_INFO_REPLY]
10139+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10140+ [ICMP_ADDRESS]
10141+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
10142+ [ICMP_ADDRESSREPLY]
10143+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
10144+
10145+ /* Can't do anything if it's a fragment. */
10146+ if (offset)
10147+ return 1;
10148+
10149+ /* Must cover type and code. */
10150+ if (datalen < 2) {
10151+ limpk("ICMP len=%u too short\n", datalen);
10152+ return 0;
10153+ }
10154+
10155+ /* If not embedded. */
10156+ if (!embedded) {
10157+ /* Bad checksum? Don't print, just ignore. */
10158+ if (!more_frags
10159+ && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
10160+ return 0;
10161+
10162+ /* CHECK: Truncated ICMP (even if first fragment). */
10163+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10164+ && info[icmph->type].min_len != 0
10165+ && datalen < info[icmph->type].min_len) {
10166+ limpk("ICMP type %u len %u too short\n",
10167+ icmph->type, datalen);
10168+ return 0;
10169+ }
10170+
10171+ /* CHECK: Check within known error ICMPs. */
10172+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10173+ && info[icmph->type].err == ICMP_IS_ERROR) {
10174+ /* CHECK: Embedded packet must be at least
10175+ length of iph + 8 bytes. */
10176+ struct iphdr *inner = (void *)icmph + 8;
10177+
10178+ /* datalen > 8 since all ICMP_IS_ERROR types
10179+ have min length > 8 */
10180+ if (datalen - 8 < sizeof(struct iphdr)) {
10181+ limpk("ICMP error internal way too short\n");
10182+ return 0;
10183+ }
10184+ if (datalen - 8 < inner->ihl*4 + 8) {
10185+ limpk("ICMP error internal too short\n");
10186+ return 0;
10187+ }
10188+ if (!check_ip(inner, datalen - 8, 1))
10189+ return 0;
10190+ }
10191+ } else {
10192+ /* CHECK: Can't embed ICMP unless known non-error. */
10193+ if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
10194+ || info[icmph->type].err != ICMP_NOT_ERROR) {
10195+ limpk("ICMP type %u not embeddable\n",
10196+ icmph->type);
10197+ return 0;
10198+ }
10199+ }
10200+
10201+ /* CHECK: Invalid ICMP codes. */
10202+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10203+ && (icmph->code < info[icmph->type].min_code
10204+ || icmph->code > info[icmph->type].max_code)) {
10205+ limpk("ICMP type=%u code=%u\n",
10206+ icmph->type, icmph->code);
10207+ return 0;
10208+ }
10209+
10210+ /* CHECK: Above maximum length. */
10211+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10212+ && info[icmph->type].max_len != 0
10213+ && datalen > info[icmph->type].max_len) {
10214+ limpk("ICMP type=%u too long: %u bytes\n",
10215+ icmph->type, datalen);
10216+ return 0;
10217+ }
10218+
10219+ switch (icmph->type) {
10220+ case ICMP_PARAMETERPROB: {
10221+ /* CHECK: Problem param must be within error packet's
10222+ * IP header. */
10223+ struct iphdr *iph = (void *)icmph + 8;
10224+ u_int32_t arg = ntohl(icmph->un.gateway);
10225+
10226+ if (icmph->code == 0) {
10227+ /* Code 0 means that upper 8 bits is pointer
10228+ to problem. */
10229+ if ((arg >> 24) >= iph->ihl*4) {
10230+ limpk("ICMP PARAMETERPROB ptr = %u\n",
10231+ ntohl(icmph->un.gateway) >> 24);
10232+ return 0;
10233+ }
10234+ arg &= 0x00FFFFFF;
10235+ }
10236+
10237+ /* CHECK: Rest must be zero. */
10238+ if (arg) {
10239+ limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
10240+ arg);
10241+ return 0;
10242+ }
10243+ break;
10244+ }
10245+
10246+ case ICMP_TIME_EXCEEDED:
10247+ case ICMP_SOURCE_QUENCH:
10248+ /* CHECK: Unused must be zero. */
10249+ if (icmph->un.gateway != 0) {
10250+ limpk("ICMP type=%u unused = %u\n",
10251+ icmph->type, ntohl(icmph->un.gateway));
10252+ return 0;
10253+ }
10254+ break;
10255+ }
10256+
10257+ return 1;
10258+}
10259+
10260+/* UDP-specific checks. */
10261+static int
10262+check_udp(const struct iphdr *iph,
10263+ const struct udphdr *udph,
10264+ u_int16_t datalen,
10265+ unsigned int offset,
10266+ int more_frags,
10267+ int embedded)
10268+{
10269+ /* Can't do anything if it's a fragment. */
10270+ if (offset)
10271+ return 1;
10272+
10273+ /* CHECK: Must cover UDP header. */
10274+ if (datalen < sizeof(struct udphdr)) {
10275+ limpk("UDP len=%u too short\n", datalen);
10276+ return 0;
10277+ }
10278+
10279+ /* Bad checksum? Don't print, just say it's unclean. */
10280+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
10281+ if (!more_frags && !embedded && udph->check
10282+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
10283+ csum_partial((char *)udph, datalen, 0)) != 0)
10284+ return 0;
10285+
10286+ /* CHECK: Destination port can't be zero. */
10287+ if (!udph->dest) {
10288+ limpk("UDP zero destination port\n");
10289+ return 0;
10290+ }
10291+
10292+ if (!more_frags) {
10293+ if (!embedded) {
10294+ /* CHECK: UDP length must match. */
10295+ if (ntohs(udph->len) != datalen) {
10296+ limpk("UDP len too short %u vs %u\n",
10297+ ntohs(udph->len), datalen);
10298+ return 0;
10299+ }
10300+ } else {
10301+ /* CHECK: UDP length be >= this truncated pkt. */
10302+ if (ntohs(udph->len) < datalen) {
10303+ limpk("UDP len too long %u vs %u\n",
10304+ ntohs(udph->len), datalen);
10305+ return 0;
10306+ }
10307+ }
10308+ } else {
10309+ /* CHECK: UDP length must be > this frag's length. */
10310+ if (ntohs(udph->len) <= datalen) {
10311+ limpk("UDP fragment len too short %u vs %u\n",
10312+ ntohs(udph->len), datalen);
10313+ return 0;
10314+ }
10315+ }
10316+
10317+ return 1;
10318+}
10319+
10320+#define TH_FIN 0x01
10321+#define TH_SYN 0x02
10322+#define TH_RST 0x04
10323+#define TH_PUSH 0x08
10324+#define TH_ACK 0x10
10325+#define TH_URG 0x20
10326+#define TH_ECE 0x40
10327+#define TH_CWR 0x80
10328+
10329+/* table of valid flag combinations - ECE and CWR are always valid */
10330+static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
10331+{
10332+ [TH_SYN] = 1,
10333+ [TH_SYN|TH_ACK] = 1,
10334+ [TH_RST] = 1,
10335+ [TH_RST|TH_ACK] = 1,
10336+ [TH_RST|TH_ACK|TH_PUSH] = 1,
10337+ [TH_FIN|TH_ACK] = 1,
10338+ [TH_ACK] = 1,
10339+ [TH_ACK|TH_PUSH] = 1,
10340+ [TH_ACK|TH_URG] = 1,
10341+ [TH_ACK|TH_URG|TH_PUSH] = 1,
10342+ [TH_FIN|TH_ACK|TH_PUSH] = 1,
10343+ [TH_FIN|TH_ACK|TH_URG] = 1,
10344+ [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
10345+};
10346+
10347+/* TCP-specific checks. */
10348+static int
10349+check_tcp(const struct iphdr *iph,
10350+ const struct tcphdr *tcph,
10351+ u_int16_t datalen,
10352+ unsigned int offset,
10353+ int more_frags,
10354+ int embedded)
10355+{
10356+ u_int8_t *opt = (u_int8_t *)tcph;
10357+ u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
10358+ u_int8_t tcpflags;
10359+ int end_of_options = 0;
10360+ size_t i;
10361+
10362+ /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
10363+ /* In fact, this is caught below (offset < 516). */
10364+
10365+ /* Can't do anything if it's a fragment. */
10366+ if (offset)
10367+ return 1;
10368+
10369+ /* CHECK: Smaller than minimal TCP hdr. */
10370+ if (datalen < sizeof(struct tcphdr)) {
10371+ if (!embedded) {
10372+ limpk("Packet length %u < TCP header.\n", datalen);
10373+ return 0;
10374+ }
10375+ /* Must have ports available (datalen >= 8), from
10376+ check_icmp which set embedded = 1 */
10377+ /* CHECK: TCP ports inside ICMP error */
10378+ if (!tcph->source || !tcph->dest) {
10379+ limpk("Zero TCP ports %u/%u.\n",
10380+ htons(tcph->source), htons(tcph->dest));
10381+ return 0;
10382+ }
10383+ return 1;
10384+ }
10385+
10386+ /* CHECK: Smaller than actual TCP hdr. */
10387+ if (datalen < tcph->doff * 4) {
10388+ if (!embedded) {
10389+ limpk("Packet length %u < actual TCP header.\n",
10390+ datalen);
10391+ return 0;
10392+ } else
10393+ return 1;
10394+ }
10395+
10396+ /* Bad checksum? Don't print, just say it's unclean. */
10397+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
10398+ if (!more_frags && !embedded
10399+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
10400+ csum_partial((char *)tcph, datalen, 0)) != 0)
10401+ return 0;
10402+
10403+ /* CHECK: TCP ports non-zero */
10404+ if (!tcph->source || !tcph->dest) {
10405+ limpk("Zero TCP ports %u/%u.\n",
10406+ htons(tcph->source), htons(tcph->dest));
10407+ return 0;
10408+ }
10409+
10410+ /* CHECK: TCP reserved bits zero. */
10411+ if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
10412+ limpk("TCP reserved bits not zero\n");
10413+ return 0;
10414+ }
10415+
10416+ /* CHECK: TCP flags. */
10417+ tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
10418+ if (!tcp_valid_flags[tcpflags]) {
10419+ limpk("TCP flags bad: %u\n", tcpflags);
10420+ return 0;
10421+ }
10422+
10423+ for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
10424+ switch (opt[i]) {
10425+ case 0:
10426+ end_of_options = 1;
10427+ i++;
10428+ break;
10429+ case 1:
10430+ i++;
10431+ break;
10432+ default:
10433+ /* CHECK: options after EOO. */
10434+ if (end_of_options) {
10435+ limpk("TCP option %u after end\n",
10436+ opt[i]);
10437+ return 0;
10438+ }
10439+ /* CHECK: options at tail. */
10440+ else if (i+1 >= tcph->doff * 4) {
10441+ limpk("TCP option %u at tail\n",
10442+ opt[i]);
10443+ return 0;
10444+ }
10445+ /* CHECK: zero-length options. */
10446+ else if (opt[i+1] == 0) {
10447+ limpk("TCP option %u 0 len\n",
10448+ opt[i]);
10449+ return 0;
10450+ }
10451+ /* CHECK: oversize options. */
10452+ else if (&opt[i] + opt[i+1] > endhdr) {
10453+ limpk("TCP option %u at %Zu too long\n",
10454+ (unsigned int) opt[i], i);
10455+ return 0;
10456+ }
10457+ /* Move to next option */
10458+ i += opt[i+1];
10459+ }
10460+ }
10461+
10462+ return 1;
10463+}
10464+
10465+/* Returns 1 if ok */
10466+/* Standard IP checks. */
10467+static int
10468+check_ip(struct iphdr *iph, size_t length, int embedded)
10469+{
10470+ u_int8_t *opt = (u_int8_t *)iph;
10471+ u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
10472+ int end_of_options = 0;
10473+ void *protoh;
10474+ size_t datalen;
10475+ unsigned int i;
10476+ unsigned int offset;
10477+
10478+ /* Should only happen for local outgoing raw-socket packets. */
10479+ /* CHECK: length >= ip header. */
10480+ if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
10481+ limpk("Packet length %Zu < IP header.\n", length);
10482+ return 0;
10483+ }
10484+
10485+ offset = ntohs(iph->frag_off) & IP_OFFSET;
10486+ protoh = (void *)iph + iph->ihl * 4;
10487+ datalen = length - iph->ihl * 4;
10488+
10489+ /* CHECK: Embedded fragment. */
10490+ if (embedded && offset) {
10491+ limpk("Embedded fragment.\n");
10492+ return 0;
10493+ }
10494+
10495+ for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
10496+ switch (opt[i]) {
10497+ case 0:
10498+ end_of_options = 1;
10499+ i++;
10500+ break;
10501+ case 1:
10502+ i++;
10503+ break;
10504+ default:
10505+ /* CHECK: options after EOO. */
10506+ if (end_of_options) {
10507+ limpk("IP option %u after end\n",
10508+ opt[i]);
10509+ return 0;
10510+ }
10511+ /* CHECK: options at tail. */
10512+ else if (i+1 >= iph->ihl * 4) {
10513+ limpk("IP option %u at tail\n",
10514+ opt[i]);
10515+ return 0;
10516+ }
10517+ /* CHECK: zero-length or one-length options. */
10518+ else if (opt[i+1] < 2) {
10519+ limpk("IP option %u %u len\n",
10520+ opt[i], opt[i+1]);
10521+ return 0;
10522+ }
10523+ /* CHECK: oversize options. */
10524+ else if (&opt[i] + opt[i+1] > endhdr) {
10525+ limpk("IP option %u at %u too long\n",
10526+ opt[i], i);
10527+ return 0;
10528+ }
10529+ /* Move to next option */
10530+ i += opt[i+1];
10531+ }
10532+ }
10533+
10534+ /* Fragment checks. */
10535+
10536+ /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
10537+ if ((ntohs(iph->frag_off) & IP_MF)
10538+ && (ntohs(iph->tot_len) % 8) != 0) {
10539+ limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
10540+ return 0;
10541+ }
10542+
10543+ /* CHECK: Oversize fragment a-la Ping of Death. */
10544+ if (offset * 8 + datalen > 65535) {
10545+ limpk("Oversize fragment to %u.\n", offset * 8);
10546+ return 0;
10547+ }
10548+
10549+ /* CHECK: DF set and offset or MF set. */
10550+ if ((ntohs(iph->frag_off) & IP_DF)
10551+ && (offset || (ntohs(iph->frag_off) & IP_MF))) {
10552+ limpk("DF set and offset=%u, MF=%u.\n",
10553+ offset, ntohs(iph->frag_off) & IP_MF);
10554+ return 0;
10555+ }
10556+
10557+ /* CHECK: Zero-sized fragments. */
10558+ if ((offset || (ntohs(iph->frag_off) & IP_MF))
10559+ && datalen == 0) {
10560+ limpk("Zero size fragment offset=%u\n", offset);
10561+ return 0;
10562+ }
10563+
10564+ /* Note: we can have even middle fragments smaller than this:
10565+ consider a large packet passing through a 600MTU then
10566+ 576MTU link: this gives a fragment of 24 data bytes. But
10567+ everyone packs fragments largest first, hence a fragment
10568+ can't START before 576 - MAX_IP_HEADER_LEN. */
10569+
10570+ /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
10571+ down to 128 (576 taken from RFC 791: All hosts must be
10572+ prepared to accept datagrams of up to 576 octets). Use 128
10573+ here. */
10574+#define MIN_LIKELY_MTU 128
10575+ /* CHECK: Min size of first frag = 128. */
10576+ if ((ntohs(iph->frag_off) & IP_MF)
10577+ && offset == 0
10578+ && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
10579+ limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
10580+ MIN_LIKELY_MTU);
10581+ return 0;
10582+ }
10583+
10584+ /* CHECK: Min offset of frag = 128 - IP hdr len. */
10585+ if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
10586+ limpk("Fragment starts at %u < %u\n", offset * 8,
10587+ MIN_LIKELY_MTU - iph->ihl * 4);
10588+ return 0;
10589+ }
10590+
10591+ /* CHECK: Protocol specification non-zero. */
10592+ if (iph->protocol == 0) {
10593+ limpk("Zero protocol\n");
10594+ return 0;
10595+ }
10596+
10597+ /* CHECK: Do not use what is unused.
10598+ * First bit of fragmentation flags should be unused.
10599+ * May be used by OS fingerprinting tools.
10600+ * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
10601+ */
10602+ if (ntohs(iph->frag_off)>>15) {
10603+ limpk("IP unused bit set\n");
10604+ return 0;
10605+ }
10606+
10607+ /* Per-protocol checks. */
10608+ switch (iph->protocol) {
10609+ case IPPROTO_ICMP:
10610+ return check_icmp(protoh, datalen, offset,
10611+ (ntohs(iph->frag_off) & IP_MF),
10612+ embedded);
10613+
10614+ case IPPROTO_UDP:
10615+ return check_udp(iph, protoh, datalen, offset,
10616+ (ntohs(iph->frag_off) & IP_MF),
10617+ embedded);
10618+
10619+ case IPPROTO_TCP:
10620+ return check_tcp(iph, protoh, datalen, offset,
10621+ (ntohs(iph->frag_off) & IP_MF),
10622+ embedded);
10623+ default:
10624+ /* Ignorance is bliss. */
10625+ return 1;
10626+ }
10627+}
10628+
10629+static int
10630+match(const struct sk_buff *skb,
10631+ const struct net_device *in,
10632+ const struct net_device *out,
10633+ const void *matchinfo,
10634+ int offset,
10635+ const void *hdr,
10636+ u_int16_t datalen,
10637+ int *hotdrop)
10638+{
10639+ return !check_ip(skb->nh.iph, skb->len, 0);
10640+}
10641+
10642+/* Called when user tries to insert an entry of this type. */
10643+static int
10644+checkentry(const char *tablename,
10645+ const struct ipt_ip *ip,
10646+ void *matchinfo,
10647+ unsigned int matchsize,
10648+ unsigned int hook_mask)
10649+{
10650+ if (matchsize != IPT_ALIGN(0))
10651+ return 0;
10652+
10653+ return 1;
10654+}
10655+
10656+static struct ipt_match unclean_match
10657+= { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
10658+
10659+static int __init init(void)
10660+{
10661+ return ipt_register_match(&unclean_match);
10662+}
10663+
10664+static void __exit fini(void)
10665+{
10666+ ipt_unregister_match(&unclean_match);
10667+}
10668+
10669+module_init(init);
10670+module_exit(fini);
10671+MODULE_LICENSE("GPL");
10672diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c
10673--- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c 2004-04-28 03:35:43.000000000 +0200
10674+++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c 2004-04-29 11:17:15.000000000 +0200
10675@@ -59,7 +59,7 @@
10676 0,
10677 sizeof(struct ipt_entry),
10678 sizeof(struct ipt_standard),
10679- 0, { 0, 0 }, { } },
10680+ 0, NULL, 0, { 0, 0 }, { } },
10681 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10682 -NF_ACCEPT - 1 } },
10683 /* FORWARD */
10684@@ -67,7 +67,7 @@
10685 0,
10686 sizeof(struct ipt_entry),
10687 sizeof(struct ipt_standard),
10688- 0, { 0, 0 }, { } },
10689+ 0, NULL, 0, { 0, 0 }, { } },
10690 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10691 -NF_ACCEPT - 1 } },
10692 /* LOCAL_OUT */
10693@@ -75,7 +75,7 @@
10694 0,
10695 sizeof(struct ipt_entry),
10696 sizeof(struct ipt_standard),
10697- 0, { 0, 0 }, { } },
10698+ 0, NULL, 0, { 0, 0 }, { } },
10699 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10700 -NF_ACCEPT - 1 } }
10701 },
10702@@ -84,7 +84,7 @@
10703 0,
10704 sizeof(struct ipt_entry),
10705 sizeof(struct ipt_error),
10706- 0, { 0, 0 }, { } },
10707+ 0, NULL, 0, { 0, 0 }, { } },
10708 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
10709 { } },
10710 "ERROR"
10711diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c
10712--- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c 2004-04-28 03:36:34.000000000 +0200
10713+++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-04-29 11:17:15.000000000 +0200
10714@@ -74,7 +74,7 @@
10715 0,
10716 sizeof(struct ipt_entry),
10717 sizeof(struct ipt_standard),
10718- 0, { 0, 0 }, { } },
10719+ 0, NULL, 0, { 0, 0 }, { } },
10720 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10721 -NF_ACCEPT - 1 } },
10722 /* LOCAL_IN */
10723@@ -82,7 +82,7 @@
10724 0,
10725 sizeof(struct ipt_entry),
10726 sizeof(struct ipt_standard),
10727- 0, { 0, 0 }, { } },
10728+ 0, NULL, 0, { 0, 0 }, { } },
10729 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10730 -NF_ACCEPT - 1 } },
10731 /* FORWARD */
10732@@ -90,7 +90,7 @@
10733 0,
10734 sizeof(struct ipt_entry),
10735 sizeof(struct ipt_standard),
10736- 0, { 0, 0 }, { } },
10737+ 0, NULL, 0, { 0, 0 }, { } },
10738 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10739 -NF_ACCEPT - 1 } },
10740 /* LOCAL_OUT */
10741@@ -98,7 +98,7 @@
10742 0,
10743 sizeof(struct ipt_entry),
10744 sizeof(struct ipt_standard),
10745- 0, { 0, 0 }, { } },
10746+ 0, NULL, 0, { 0, 0 }, { } },
10747 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10748 -NF_ACCEPT - 1 } },
10749 /* POST_ROUTING */
10750@@ -106,7 +106,7 @@
10751 0,
10752 sizeof(struct ipt_entry),
10753 sizeof(struct ipt_standard),
10754- 0, { 0, 0 }, { } },
10755+ 0, NULL, 0, { 0, 0 }, { } },
10756 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10757 -NF_ACCEPT - 1 } },
10758 },
10759@@ -115,7 +115,7 @@
10760 0,
10761 sizeof(struct ipt_entry),
10762 sizeof(struct ipt_error),
10763- 0, { 0, 0 }, { } },
10764+ 0, NULL, 0, { 0, 0 }, { } },
10765 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
10766 { } },
10767 "ERROR"
10768diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c
10769--- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c 2004-04-28 03:36:36.000000000 +0200
10770+++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c 2004-04-29 11:17:15.000000000 +0200
10771@@ -46,7 +46,7 @@
10772 0,
10773 sizeof(struct ipt_entry),
10774 sizeof(struct ipt_standard),
10775- 0, { 0, 0 }, { } },
10776+ 0, NULL, 0, { 0, 0 }, { } },
10777 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10778 -NF_ACCEPT - 1 } },
10779 /* LOCAL_OUT */
10780@@ -54,7 +54,7 @@
10781 0,
10782 sizeof(struct ipt_entry),
10783 sizeof(struct ipt_standard),
10784- 0, { 0, 0 }, { } },
10785+ 0, NULL, 0, { 0, 0 }, { } },
10786 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10787 -NF_ACCEPT - 1 } }
10788 },
10789@@ -63,7 +63,7 @@
10790 0,
10791 sizeof(struct ipt_entry),
10792 sizeof(struct ipt_error),
10793- 0, { 0, 0 }, { } },
10794+ 0, NULL, 0, { 0, 0 }, { } },
10795 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
10796 { } },
10797 "ERROR"
10798diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/raw.c linux-2.6.6-rc3/net/ipv4/raw.c
10799--- linux-2.6.6-rc3.org/net/ipv4/raw.c 2004-04-28 03:35:49.000000000 +0200
10800+++ linux-2.6.6-rc3/net/ipv4/raw.c 2004-04-29 11:18:06.000000000 +0200
10801@@ -249,6 +249,7 @@
10802 kfree_skb(skb);
10803 return NET_RX_DROP;
10804 }
10805+ nf_reset(skb);
10806
10807 skb_push(skb, skb->data - skb->nh.raw);
10808
10809@@ -307,7 +308,7 @@
10810 }
10811
10812 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
10813- dst_output);
10814+ ip_dst_output);
10815 if (err > 0)
10816 err = inet->recverr ? net_xmit_errno(err) : 0;
10817 if (err)
10818diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c
10819--- linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c 2004-04-28 03:35:40.000000000 +0200
10820+++ linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c 2004-04-29 11:19:32.000000000 +0200
10821@@ -1785,6 +1785,7 @@
10822
10823 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
10824 goto discard_and_relse;
10825+ nf_reset(skb);
10826
10827 if (sk_filter(sk, skb, 0))
10828 goto discard_and_relse;
10829@@ -2670,6 +2671,7 @@
10830 EXPORT_SYMBOL(tcp_v4_connect);
10831 EXPORT_SYMBOL(tcp_v4_do_rcv);
10832 EXPORT_SYMBOL(tcp_v4_lookup_listener);
10833+EXPORT_SYMBOL(tcp_v4_lookup);
10834 EXPORT_SYMBOL(tcp_v4_rebuild_header);
10835 EXPORT_SYMBOL(tcp_v4_remember_stamp);
10836 EXPORT_SYMBOL(tcp_v4_send_check);
10837diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/udp.c linux-2.6.6-rc3/net/ipv4/udp.c
10838--- linux-2.6.6-rc3.org/net/ipv4/udp.c 2004-04-28 03:35:19.000000000 +0200
10839+++ linux-2.6.6-rc3/net/ipv4/udp.c 2004-04-29 11:19:32.000000000 +0200
10840@@ -1045,6 +1045,7 @@
10841 kfree_skb(skb);
10842 return -1;
10843 }
10844+ nf_reset(skb);
10845
10846 if (up->encap_type) {
10847 /*
10848@@ -1210,6 +1211,7 @@
10849
10850 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
10851 goto drop;
10852+ nf_reset(skb);
10853
10854 /* No socket. Drop packet silently, if checksum is wrong */
10855 if (udp_checksum_complete(skb))
10856@@ -1558,6 +1560,7 @@
10857 EXPORT_SYMBOL(udp_port_rover);
10858 EXPORT_SYMBOL(udp_prot);
10859 EXPORT_SYMBOL(udp_sendmsg);
10860+EXPORT_SYMBOL(udp_v4_lookup);
10861
10862 #ifdef CONFIG_PROC_FS
10863 EXPORT_SYMBOL(udp_proc_register);
10864diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c
10865--- linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-04-28 03:35:08.000000000 +0200
10866+++ linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c 2004-04-29 11:18:03.000000000 +0200
10867@@ -76,6 +76,7 @@
10868 err = -EHOSTUNREACH;
10869 goto error_nolock;
10870 }
10871+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
10872 return NET_XMIT_BYPASS;
10873
10874 error_nolock:
10875@@ -170,6 +171,7 @@
10876 .handler = ipip_rcv,
10877 .err_handler = ipip_err,
10878 .no_policy = 1,
10879+ .xfrm_prot = 1,
10880 };
10881
10882 static int __init ipip_init(void)
10883diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig
10884--- linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig 2004-04-29 11:24:39.000000000 +0200
10885+++ linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig 2004-04-29 11:19:41.000000000 +0200
10886@@ -255,5 +255,29 @@
10887 depends on IP6_NF_IPTABLES
10888 help
10889
10890+config IP6_NF_TARGET_TRACE
10891+ tristate 'TRACE target support'
10892+ depends on IP6_NF_RAW
10893+ help
10894+ The TRACE target allows packets to be traced as those
10895+ matches any subsequent rule in any table/rule. The matched
10896+ rule and the packet is logged with the prefix
10897+
10898+ TRACE: tablename/chainname/rulenum
10899+
10900+ If you want to compile it as a module, say M here and read
10901+ <file:Documentation/modules.txt>. If unsure, say `N'.
10902+ help
10903+
10904+config IP6_NF_MATCH_POLICY
10905+ tristate "IPsec policy match support"
10906+ depends on IP6_NF_IPTABLES && XFRM
10907+ help
10908+ Policy matching allows you to match packets based on the
10909+ IPsec policy that was used during decapsulation/will
10910+ be used during encapsulation.
10911+
10912+ To compile it as a module, choose M here. If unsure, say N.
10913+
10914 endmenu
10915
10916diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc3/net/ipv6/netfilter/Makefile
10917--- linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile 2004-04-29 11:24:39.000000000 +0200
10918+++ linux-2.6.6-rc3/net/ipv6/netfilter/Makefile 2004-04-29 11:19:41.000000000 +0200
10919@@ -29,4 +29,6 @@
10920 obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
10921 obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
10922 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
10923+obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
10924 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
10925+obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
10926diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c
10927--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-04-28 03:36:34.000000000 +0200
10928+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c 2004-04-29 11:17:15.000000000 +0200
10929@@ -38,6 +38,14 @@
10930 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
10931 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
10932
10933+static const char *hook6names[] = {
10934+ [NF_IP6_PRE_ROUTING] "PREROUTING",
10935+ [NF_IP6_LOCAL_IN] "INPUT",
10936+ [NF_IP6_FORWARD] "FORWARD",
10937+ [NF_IP6_LOCAL_OUT] "OUTPUT",
10938+ [NF_IP6_POST_ROUTING] "POSTROUTING",
10939+};
10940+
10941 /*#define DEBUG_IP_FIREWALL*/
10942 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
10943 /*#define DEBUG_IP_FIREWALL_USER*/
10944@@ -408,6 +416,12 @@
10945
10946 t = ip6t_get_target(e);
10947 IP_NF_ASSERT(t->u.kernel.target);
10948+
10949+ /* The packet traced and the rule isn't an unconditional return/END. */
10950+ if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
10951+ nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
10952+ table->name, e->chainname, e->rulenum);
10953+ }
10954 /* Standard target? */
10955 if (!t->u.kernel.target->target) {
10956 int v;
10957@@ -561,6 +575,29 @@
10958 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
10959 }
10960
10961+static inline int
10962+find_error_target(struct ip6t_entry *s,
10963+ struct ip6t_entry *e,
10964+ char **chainname)
10965+{
10966+ struct ip6t_entry_target *t;
10967+ static struct ip6t_entry *found = NULL;
10968+
10969+ if (s == e) {
10970+ if (!found)
10971+ return 0;
10972+ t = ip6t_get_target(found);
10973+ if (strcmp(t->u.user.name,
10974+ IP6T_ERROR_TARGET) == 0) {
10975+ *chainname = t->data;
10976+ return 1;
10977+ }
10978+ } else
10979+ found = s;
10980+
10981+ return 0;
10982+}
10983+
10984 /* All zeroes == unconditional rule. */
10985 static inline int
10986 unconditional(const struct ip6t_ip6 *ipv6)
10987@@ -580,6 +617,8 @@
10988 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
10989 {
10990 unsigned int hook;
10991+ char *chainname = NULL;
10992+ u_int32_t rulenum;
10993
10994 /* No recursion; use packet counter to save back ptrs (reset
10995 to 0 as we leave), and comefrom to save source hook bitmask */
10996@@ -593,6 +632,8 @@
10997
10998 /* Set initial back pointer. */
10999 e->counters.pcnt = pos;
11000+ rulenum = 1;
11001+ chainname = (char *) hook6names[hook];
11002
11003 for (;;) {
11004 struct ip6t_standard_target *t
11005@@ -605,6 +646,8 @@
11006 }
11007 e->comefrom
11008 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
11009+ e->rulenum = rulenum++;
11010+ e->chainname = chainname;
11011
11012 /* Unconditional return/END. */
11013 if (e->target_offset == sizeof(struct ip6t_entry)
11014@@ -614,6 +657,10 @@
11015 && unconditional(&e->ipv6)) {
11016 unsigned int oldpos, size;
11017
11018+ /* Set unconditional rulenum to zero. */
11019+ e->rulenum = 0;
11020+ e->counters.bcnt = 0;
11021+
11022 /* Return: backtrack through the last
11023 big jump. */
11024 do {
11025@@ -639,6 +686,11 @@
11026 (newinfo->entries + pos);
11027 } while (oldpos == pos + e->next_offset);
11028
11029+ /* Restore chainname, rulenum. */
11030+ chainname = e->chainname;
11031+ rulenum = e->counters.bcnt;
11032+ e->counters.bcnt = 0;
11033+
11034 /* Move along one */
11035 size = e->next_offset;
11036 e = (struct ip6t_entry *)
11037@@ -654,6 +706,17 @@
11038 /* This a jump; chase it. */
11039 duprintf("Jump rule %u -> %u\n",
11040 pos, newpos);
11041+ e->counters.bcnt = rulenum++;
11042+ rulenum = 1;
11043+ e = (struct ip6t_entry *)
11044+ (newinfo->entries + newpos);
11045+ if (IP6T_ENTRY_ITERATE(newinfo->entries,
11046+ newinfo->size,
11047+ find_error_target,
11048+ e, &chainname) == 0) {
11049+ printk("ip6_tables: table screwed up!\n");
11050+ return 0;
11051+ }
11052 } else {
11053 /* ... this is a fallthru */
11054 newpos = pos + e->next_offset;
11055diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c
11056--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
11057+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c 2004-04-29 11:17:15.000000000 +0200
11058@@ -0,0 +1,65 @@
11059+/* This is a module which is used for setting
11060+ * the NFC_TRACE flag in the nfcache field of an skb.
11061+ */
11062+#include <linux/module.h>
11063+#include <linux/skbuff.h>
11064+
11065+#include <linux/netfilter_ipv6/ip6_tables.h>
11066+
11067+MODULE_LICENSE("GPL");
11068+
11069+static unsigned int
11070+target(struct sk_buff **pskb,
11071+ unsigned int hooknum,
11072+ const struct net_device *in,
11073+ const struct net_device *out,
11074+ const void *targinfo,
11075+ void *userinfo)
11076+{
11077+ (*pskb)->nfcache |= NFC_TRACE;
11078+ return IP6T_CONTINUE;
11079+}
11080+
11081+static int
11082+checkentry(const char *tablename,
11083+ const struct ip6t_entry *e,
11084+ void *targinfo,
11085+ unsigned int targinfosize,
11086+ unsigned int hook_mask)
11087+{
11088+ if (targinfosize != 0) {
11089+ printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
11090+ targinfosize);
11091+ return 0;
11092+ }
11093+
11094+ if (strcmp(tablename, "raw") != 0) {
11095+ printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
11096+ return 0;
11097+ }
11098+
11099+ return 1;
11100+}
11101+
11102+static struct ip6t_target ip6t_trace_reg = {
11103+ .name = "TRACE",
11104+ .target = target,
11105+ .checkentry = checkentry,
11106+ .me = THIS_MODULE
11107+};
11108+
11109+static int __init init(void)
11110+{
11111+ if (ip6t_register_target(&ip6t_trace_reg))
11112+ return -EINVAL;
11113+
11114+ return 0;
11115+}
11116+
11117+static void __exit fini(void)
11118+{
11119+ ip6t_unregister_target(&ip6t_trace_reg);
11120+}
11121+
11122+module_init(init);
11123+module_exit(fini);
11124diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c
11125--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-28 03:36:30.000000000 +0200
11126+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c 2004-04-29 11:19:40.000000000 +0200
11127@@ -21,6 +21,39 @@
11128 MODULE_LICENSE("GPL");
11129
11130 static int
11131+match_comm(const struct sk_buff *skb, const char *comm)
11132+{
11133+ struct task_struct *p, *g;
11134+ struct files_struct *files;
11135+ int i;
11136+
11137+ read_lock(&tasklist_lock);
11138+ do_each_thread(g, p) {
11139+ if(strncmp(p->comm, comm, sizeof(p->comm)))
11140+ continue;
11141+
11142+ task_lock(p);
11143+ files = p->files;
11144+ if(files) {
11145+ read_lock(&files->file_lock);
11146+ for (i=0; i < files->max_fds; i++) {
11147+ if (fcheck_files(files, i) ==
11148+ skb->sk->sk_socket->file) {
11149+ read_unlock(&files->file_lock);
11150+ task_unlock(p);
11151+ read_unlock(&tasklist_lock);
11152+ return 1;
11153+ }
11154+ }
11155+ read_unlock(&files->file_lock);
11156+ }
11157+ task_unlock(p);
11158+ } while_each_thread(g, p);
11159+ read_unlock(&tasklist_lock);
11160+ return 0;
11161+}
11162+
11163+static int
11164 match_pid(const struct sk_buff *skb, pid_t pid)
11165 {
11166 struct task_struct *p;
11167@@ -125,6 +158,12 @@
11168 return 0;
11169 }
11170
11171+ if(info->match & IP6T_OWNER_COMM) {
11172+ if (!match_comm(skb, info->comm) ^
11173+ !!(info->invert & IP6T_OWNER_COMM))
11174+ return 0;
11175+ }
11176+
11177 return 1;
11178 }
11179
11180diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c
11181--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c 1970-01-01 01:00:00.000000000 +0100
11182+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c 2004-04-29 11:19:41.000000000 +0200
11183@@ -0,0 +1,200 @@
11184+/* IP tables module for matching IPsec policy\r
11185+ *\r
11186+ * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>\r
11187+ *\r
11188+ * This program is free software; you can redistribute it and/or modify\r
11189+ * it under the terms of the GNU General Public License version 2 as\r
11190+ * published by the Free Software Foundation.\r
11191+ */\r
11192+\r
11193+#include <linux/kernel.h>\r
11194+#include <linux/config.h>\r
11195+#include <linux/module.h>\r
11196+#include <linux/skbuff.h>\r
11197+#include <linux/init.h>\r
11198+#include <net/xfrm.h>\r
11199+\r
11200+#include <linux/netfilter_ipv6.h>\r
11201+#include <linux/netfilter_ipv6/ip6t_policy.h>\r
11202+#include <linux/netfilter_ipv6/ip6_tables.h>\r
11203+\r
11204+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");\r
11205+MODULE_DESCRIPTION("IPtables IPsec policy matching module");\r
11206+MODULE_LICENSE("GPL");\r
11207+\r
11208+\r
11209+static inline int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,\r
11210+ struct in6_addr addr2)\r
11211+{\r
11212+ int i;\r
11213+\r
11214+ for (i = 0; i < 16; i++) {\r
11215+ if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=\r
11216+ (addr2.s6_addr[i] & mask.s6_addr[i]))\r
11217+ return 1;\r
11218+ }\r
11219+ return 0;\r
11220+}\r
11221+\r
11222+\r
11223+static inline int\r
11224+match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)\r
11225+{\r
11226+#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))\r
11227+ \r
11228+ struct in6_addr xfrm_saddr, xfrm_daddr;\r
11229+ \r
11230+ if ((e->match.saddr\r
11231+ && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))\r
11232+ ^ e->invert.saddr ) ||\r
11233+ (e->match.daddr\r
11234+ && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))\r
11235+ ^ e->invert.daddr ) ||\r
11236+ MISMATCH(proto, x->id.proto) ||\r
11237+ MISMATCH(mode, x->props.mode) ||\r
11238+ MISMATCH(spi, x->id.spi) ||\r
11239+ MISMATCH(reqid, x->props.reqid))\r
11240+ return 0;\r
11241+ return 1;\r
11242+}\r
11243+\r
11244+static int\r
11245+match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
11246+{\r
11247+ const struct ip6t_policy_elem *e;\r
11248+ struct sec_path *sp = skb->sp;\r
11249+ int strict = info->flags & POLICY_MATCH_STRICT;\r
11250+ int i, pos;\r
11251+\r
11252+ if (sp == NULL)\r
11253+ return -1;\r
11254+ if (strict && info->len != sp->len)\r
11255+ return 0;\r
11256+\r
11257+ for (i = sp->len - 1; i >= 0; i--) {\r
11258+ pos = strict ? i - sp->len + 1 : 0;\r
11259+ if (pos >= info->len)\r
11260+ return 0;\r
11261+ e = &info->pol[pos];\r
11262+\r
11263+ if (match_xfrm_state(sp->x[i].xvec, e)) {\r
11264+ if (!strict)\r
11265+ return 1;\r
11266+ } else if (strict)\r
11267+ return 0;\r
11268+ }\r
11269+\r
11270+ return strict ? 1 : 0;\r
11271+}\r
11272+\r
11273+static int\r
11274+match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
11275+{\r
11276+ const struct ip6t_policy_elem *e;\r
11277+ struct dst_entry *dst = skb->dst;\r
11278+ int strict = info->flags & POLICY_MATCH_STRICT;\r
11279+ int i, pos;\r
11280+\r
11281+ if (dst->xfrm == NULL)\r
11282+ return -1;\r
11283+\r
11284+ for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {\r
11285+ pos = strict ? i : 0;\r
11286+ if (pos >= info->len)\r
11287+ return 0;\r
11288+ e = &info->pol[pos];\r
11289+\r
11290+ if (match_xfrm_state(dst->xfrm, e)) {\r
11291+ if (!strict)\r
11292+ return 1;\r
11293+ } else if (strict)\r
11294+ return 0;\r
11295+ }\r
11296+\r
11297+ return strict ? 1 : 0;\r
11298+}\r
11299+\r
11300+static int match(const struct sk_buff *skb,\r
11301+ const struct net_device *in,\r
11302+ const struct net_device *out,\r
11303+ const void *matchinfo,\r
11304+ int offset,\r
11305+ const void *hdr,\r
11306+ u_int16_t datalen,\r
11307+ int *hotdrop)\r
11308+{\r
11309+ const struct ip6t_policy_info *info = matchinfo;\r
11310+ int ret;\r
11311+\r
11312+ if (info->flags & POLICY_MATCH_IN)\r
11313+ ret = match_policy_in(skb, info);\r
11314+ else\r
11315+ ret = match_policy_out(skb, info);\r
11316+\r
11317+ if (ret < 0) {\r
11318+ if (info->flags & POLICY_MATCH_NONE)\r
11319+ ret = 1;\r
11320+ else\r
11321+ ret = 0;\r
11322+ } else if (info->flags & POLICY_MATCH_NONE)\r
11323+ ret = 0;\r
11324+\r
11325+ return ret;\r
11326+}\r
11327+\r
11328+static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,\r
11329+ void *matchinfo, unsigned int matchsize,\r
11330+ unsigned int hook_mask)\r
11331+{\r
11332+ struct ip6t_policy_info *info = matchinfo;\r
11333+\r
11334+ if (matchsize != IP6T_ALIGN(sizeof(*info))) {\r
11335+ printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",\r
11336+ matchsize, IP6T_ALIGN(sizeof(*info)));\r
11337+ return 0;\r
11338+ }\r
11339+ if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {\r
11340+ printk(KERN_ERR "ip6t_policy: neither incoming nor "\r
11341+ "outgoing policy selected\n");\r
11342+ return 0;\r
11343+ }\r
11344+ if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)\r
11345+ && info->flags & POLICY_MATCH_OUT) {\r
11346+ printk(KERN_ERR "ip6t_policy: output policy not valid in "\r
11347+ "PRE_ROUTING and INPUT\n");\r
11348+ return 0;\r
11349+ }\r
11350+ if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)\r
11351+ && info->flags & POLICY_MATCH_IN) {\r
11352+ printk(KERN_ERR "ip6t_policy: input policy not valid in "\r
11353+ "POST_ROUTING and OUTPUT\n");\r
11354+ return 0;\r
11355+ }\r
11356+ if (info->len > POLICY_MAX_ELEM) {\r
11357+ printk(KERN_ERR "ip6t_policy: too many policy elements\n");\r
11358+ return 0;\r
11359+ }\r
11360+\r
11361+ return 1;\r
11362+}\r
11363+\r
11364+static struct ip6t_match policy_match =\r
11365+{\r
11366+ .name = "policy",\r
11367+ .match = match,\r
11368+ .checkentry = checkentry,\r
11369+ .me = THIS_MODULE,\r
11370+};\r
11371+\r
11372+static int __init init(void)\r
11373+{\r
11374+ return ip6t_register_match(&policy_match);\r
11375+}\r
11376+\r
11377+static void __exit fini(void)\r
11378+{\r
11379+ ip6t_unregister_match(&policy_match);\r
11380+}\r
11381+\r
11382+module_init(init);\r
11383+module_exit(fini);\r
11384diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c
11385--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c 2004-04-28 03:35:07.000000000 +0200
11386+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c 2004-04-29 11:17:15.000000000 +0200
11387@@ -58,7 +58,7 @@
11388 0,
11389 sizeof(struct ip6t_entry),
11390 sizeof(struct ip6t_standard),
11391- 0, { 0, 0 }, { } },
11392+ 0, NULL, 0, { 0, 0 }, { } },
11393 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11394 -NF_ACCEPT - 1 } },
11395 /* FORWARD */
11396@@ -66,7 +66,7 @@
11397 0,
11398 sizeof(struct ip6t_entry),
11399 sizeof(struct ip6t_standard),
11400- 0, { 0, 0 }, { } },
11401+ 0, NULL, 0, { 0, 0 }, { } },
11402 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11403 -NF_ACCEPT - 1 } },
11404 /* LOCAL_OUT */
11405@@ -74,7 +74,7 @@
11406 0,
11407 sizeof(struct ip6t_entry),
11408 sizeof(struct ip6t_standard),
11409- 0, { 0, 0 }, { } },
11410+ 0, NULL, 0, { 0, 0 }, { } },
11411 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11412 -NF_ACCEPT - 1 } }
11413 },
11414@@ -83,7 +83,7 @@
11415 0,
11416 sizeof(struct ip6t_entry),
11417 sizeof(struct ip6t_error),
11418- 0, { 0, 0 }, { } },
11419+ 0, NULL, 0, { 0, 0 }, { } },
11420 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11421 { } },
11422 "ERROR"
11423diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c
11424--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c 2004-04-28 03:35:43.000000000 +0200
11425+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c 2004-04-29 11:17:15.000000000 +0200
11426@@ -73,7 +73,7 @@
11427 0,
11428 sizeof(struct ip6t_entry),
11429 sizeof(struct ip6t_standard),
11430- 0, { 0, 0 }, { } },
11431+ 0, NULL, 0, { 0, 0 }, { } },
11432 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11433 -NF_ACCEPT - 1 } },
11434 /* LOCAL_IN */
11435@@ -81,7 +81,7 @@
11436 0,
11437 sizeof(struct ip6t_entry),
11438 sizeof(struct ip6t_standard),
11439- 0, { 0, 0 }, { } },
11440+ 0, NULL, 0, { 0, 0 }, { } },
11441 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11442 -NF_ACCEPT - 1 } },
11443 /* FORWARD */
11444@@ -89,7 +89,7 @@
11445 0,
11446 sizeof(struct ip6t_entry),
11447 sizeof(struct ip6t_standard),
11448- 0, { 0, 0 }, { } },
11449+ 0, NULL, 0, { 0, 0 }, { } },
11450 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11451 -NF_ACCEPT - 1 } },
11452 /* LOCAL_OUT */
11453@@ -97,7 +97,7 @@
11454 0,
11455 sizeof(struct ip6t_entry),
11456 sizeof(struct ip6t_standard),
11457- 0, { 0, 0 }, { } },
11458+ 0, NULL, 0, { 0, 0 }, { } },
11459 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11460 -NF_ACCEPT - 1 } },
11461 /* POST_ROUTING */
11462@@ -105,7 +105,7 @@
11463 0,
11464 sizeof(struct ip6t_entry),
11465 sizeof(struct ip6t_standard),
11466- 0, { 0, 0 }, { } },
11467+ 0, NULL, 0, { 0, 0 }, { } },
11468 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11469 -NF_ACCEPT - 1 } }
11470 },
11471@@ -114,7 +114,7 @@
11472 0,
11473 sizeof(struct ip6t_entry),
11474 sizeof(struct ip6t_error),
11475- 0, { 0, 0 }, { } },
11476+ 0, NULL, 0, { 0, 0 }, { } },
11477 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11478 { } },
11479 "ERROR"
11480diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c
11481--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c 2004-04-28 03:36:19.000000000 +0200
11482+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c 2004-04-29 11:17:15.000000000 +0200
11483@@ -52,7 +52,7 @@
11484 0,
11485 sizeof(struct ip6t_entry),
11486 sizeof(struct ip6t_standard),
11487- 0, { 0, 0 }, { } },
11488+ 0, NULL, 0, { 0, 0 }, { } },
11489 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11490 -NF_ACCEPT - 1 } },
11491 /* LOCAL_OUT */
11492@@ -60,7 +60,7 @@
11493 0,
11494 sizeof(struct ip6t_entry),
11495 sizeof(struct ip6t_standard),
11496- 0, { 0, 0 }, { } },
11497+ 0, NULL, 0, { 0, 0 }, { } },
11498 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11499 -NF_ACCEPT - 1 } },
11500 },
11501@@ -69,7 +69,7 @@
11502 0,
11503 sizeof(struct ip6t_entry),
11504 sizeof(struct ip6t_error),
11505- 0, { 0, 0 }, { } },
11506+ 0, NULL, 0, { 0, 0 }, { } },
11507 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11508 { } },
11509 "ERROR"
11510diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c linux-2.6.6-rc3/net/xfrm/xfrm_input.c
11511--- linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c 2004-04-28 03:35:05.000000000 +0200
11512+++ linux-2.6.6-rc3/net/xfrm/xfrm_input.c 2004-04-29 11:18:03.000000000 +0200
11513@@ -29,6 +29,9 @@
11514 if (!sp)
11515 return NULL;
11516
11517+#ifdef CONFIG_NETFILTER
11518+ sp->decap_done = 0;
11519+#endif
11520 sp->len = 0;
11521 if (src) {
11522 int i;
11523diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc3/net/xfrm/xfrm_policy.c
11524--- linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c 2004-04-28 03:35:48.000000000 +0200
11525+++ linux-2.6.6-rc3/net/xfrm/xfrm_policy.c 2004-04-29 11:18:06.000000000 +0200
11526@@ -21,6 +21,7 @@
11527 #include <linux/workqueue.h>
11528 #include <linux/notifier.h>
11529 #include <linux/netdevice.h>
11530+#include <linux/netfilter.h>
11531 #include <net/xfrm.h>
11532 #include <net/ip.h>
11533
11534@@ -908,6 +909,7 @@
11535
11536 if (_decode_session(skb, &fl, family) < 0)
11537 return 0;
11538+ nf_nat_decode_session(skb, &fl, family);
11539
11540 /* First, check used SA against their selectors. */
11541 if (skb->sp) {
This page took 1.434103 seconds and 4 git commands to generate.