]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.6-rc3-patch-o-matic-ng-extra-20040429.patch
- missing prototype on sparc64
[packages/kernel.git] / 2.6.6-rc3-patch-o-matic-ng-extra-20040429.patch
CommitLineData
e7db1826 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 */
265diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
266--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 1970-01-01 01:00:00.000000000 +0100
267+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 2004-04-29 11:17:55.000000000 +0200
268@@ -0,0 +1,70 @@
269+#ifndef _IP_CT_CUSEEME
270+#define _IP_CT_CUSEEME
271+
272+#define CUSEEME_PORT 7648
273+
274+/* These structs come from the 2.2 ip_masq_cuseeme code... */
275+
276+#pragma pack(1)
277+/* CuSeeMe data header */
278+struct cu_header {
279+ u_int16_t dest_family;
280+ u_int16_t dest_port;
281+ u_int32_t dest_addr;
282+ int16_t family;
283+ u_int16_t port;
284+ u_int32_t addr;
285+ u_int32_t seq;
286+ u_int16_t msg;
287+ u_int16_t data_type;
288+ /* possible values:
289+ * 1 small video
290+ * 2 big video
291+ * 3 audio
292+ * 100 acknowledge connectivity when there
293+ * is nothing else to send
294+ * 101 OpenContinue packet
295+ * 104 display a text message and
296+ * disconnect (used by reflector to
297+ * kick clients off)
298+ * 105 display a text message (welcome
299+ * message from reflector)
300+ * 106 exchanged among reflectors for
301+ * reflector interoperation
302+ * 107 carry aux stream data when there is
303+ * no video to piggy-back on
304+ * 108 obsolete (used in Mac alpha version)
305+ * 109 obsolete (used in Mac alpha version)
306+ * 110 used for data rate control
307+ * 111 used for data rate control
308+ * 256 aux data control messages
309+ * 257 aux data packets
310+ * */
311+ u_int16_t packet_len;
312+};
313+
314+/* Open Continue Header */
315+struct oc_header {
316+ struct cu_header cu_head;
317+ u_int16_t client_count; /* Number of client info structs */
318+ u_int32_t seq_no;
319+ char user_name[20];
320+ char stuff[4]; /* Flags, version stuff, etc */
321+};
322+
323+/* Client info structures */
324+struct client_info {
325+ u_int32_t address; /* Client address */
326+ char stuff[8]; /* Flags, pruning bitfield, packet counts, etc */
327+};
328+#pragma pack()
329+
330+/* This structure is per expected connection */
331+struct ip_ct_cuseeme_expect {
332+};
333+
334+/* This structure exists only once per master */
335+struct ip_ct_cuseeme_master {
336+};
337+
338+#endif /* _IP_CT_CUSEEME */
339diff -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
340--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h 1970-01-01 01:00:00.000000000 +0100
341+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2004-04-29 11:18:00.000000000 +0200
342@@ -0,0 +1,31 @@
343+#ifndef _IP_CONNTRACK_H323_H
344+#define _IP_CONNTRACK_H323_H
345+/* H.323 connection tracking. */
346+
347+#ifdef __KERNEL__
348+/* Protects H.323 related data */
349+#include <linux/netfilter_ipv4/lockhelp.h>
350+DECLARE_LOCK_EXTERN(ip_h323_lock);
351+#endif
352+
353+/* Default H.225 port */
354+#define H225_PORT 1720
355+
356+/* This structure is per expected connection */
357+struct ip_ct_h225_expect {
358+ u_int16_t port; /* Port of the H.225 helper/RTCP/RTP channel */
359+ enum ip_conntrack_dir dir; /* Direction of the original connection */
360+ unsigned int offset; /* offset of the address in the payload */
361+};
362+
363+/* This structure exists only once per master */
364+struct ip_ct_h225_master {
365+ int is_h225; /* H.225 or H.245 connection */
366+#ifdef CONFIG_IP_NF_NAT_NEEDED
367+ enum ip_conntrack_dir dir; /* Direction of the original connection */
368+ u_int32_t seq[IP_CT_DIR_MAX]; /* Exceptional packet mangling for signal addressess... */
369+ unsigned int offset[IP_CT_DIR_MAX]; /* ...and the offset of the addresses in the payload */
370+#endif
371+};
372+
373+#endif /* _IP_CONNTRACK_H323_H */
374diff -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
375--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
376+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h 2004-04-29 11:19:01.000000000 +0200
377@@ -0,0 +1,31 @@
378+#ifndef _IP_CONNTRACK_MMS_H
379+#define _IP_CONNTRACK_MMS_H
380+/* MMS tracking. */
381+
382+#ifdef __KERNEL__
383+#include <linux/netfilter_ipv4/lockhelp.h>
384+
385+DECLARE_LOCK_EXTERN(ip_mms_lock);
386+
387+#define MMS_PORT 1755
388+#define MMS_SRV_MSG_ID 196610
389+
390+#define MMS_SRV_MSG_OFFSET 36
391+#define MMS_SRV_UNICODE_STRING_OFFSET 60
392+#define MMS_SRV_CHUNKLENLV_OFFSET 16
393+#define MMS_SRV_CHUNKLENLM_OFFSET 32
394+#define MMS_SRV_MESSAGELENGTH_OFFSET 8
395+#endif
396+
397+/* This structure is per expected connection */
398+struct ip_ct_mms_expect {
399+ u_int32_t len;
400+ u_int32_t padding;
401+ u_int16_t port;
402+};
403+
404+/* This structure exists only once per master */
405+struct ip_ct_mms_master {
406+};
407+
408+#endif /* _IP_CONNTRACK_MMS_H */
409diff -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
410--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 1970-01-01 01:00:00.000000000 +0100
411+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h 2004-04-29 11:19:53.000000000 +0200
412@@ -0,0 +1,21 @@
413+#ifndef _IP_CT_QUAKE3
414+#define _IP_CT_QUAKE3
415+
416+/* Don't confuse with 27960, often used as the Server Port */
417+#define QUAKE3_MASTER_PORT 27950
418+
419+struct quake3_search {
420+ const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
421+ const char *pattern;
422+ size_t plen;
423+};
424+
425+/* This structure is per expected connection */
426+struct ip_ct_quake3_expect {
427+};
428+
429+/* This structure exists only once per master */
430+struct ip_ct_quake3_master {
431+};
432+
433+#endif /* _IP_CT_QUAKE3 */
434diff -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
435--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
436+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2004-04-29 11:20:02.000000000 +0200
437@@ -0,0 +1,68 @@
438+/* RPC extension for IP connection tracking, Version 2.2
439+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
440+ * - original rpc tracking module
441+ * - "recent" connection handling for kernel 2.3+ netfilter
442+ *
443+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
444+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
445+ *
446+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
447+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
448+ * - extended matching to support filtering on procedures
449+ *
450+ * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
451+ *
452+ * This program is free software; you can redistribute it and/or
453+ * modify it under the terms of the GNU General Public License
454+ * as published by the Free Software Foundation; either version
455+ * 2 of the License, or (at your option) any later version.
456+ **
457+ */
458+
459+#include <asm/param.h>
460+#include <linux/sched.h>
461+#include <linux/timer.h>
462+#include <linux/stddef.h>
463+#include <linux/list.h>
464+
465+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
466+
467+#ifndef _IP_CONNTRACK_RPC_H
468+#define _IP_CONNTRACK_RPC_H
469+
470+#define RPC_PORT 111
471+
472+
473+/* Datum in RPC packets are encoded in XDR */
474+#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
475+
476+/* Fast timeout, to deny DoS atacks */
477+#define EXP (60 * HZ)
478+
479+/* Normal timeouts */
480+#define EXPIRES (180 * HZ)
481+
482+/* For future conections RPC, using client's cache bindings
483+ * I'll use ip_conntrack_lock to lock these lists */
484+
485+/* This identifies each request and stores protocol */
486+struct request_p {
487+ struct list_head list;
488+
489+ u_int32_t xid;
490+ u_int32_t ip;
491+ u_int16_t port;
492+
493+ /* Protocol */
494+ u_int16_t proto;
495+
496+ struct timer_list timeout;
497+};
498+
499+static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
500+ u_int32_t ip, u_int32_t port) {
501+ return (p->xid == xid && p->ip == ip && p->port);
502+
503+}
504+
505+#endif /* _IP_CONNTRACK_RPC_H */
506diff -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
507--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
508+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 2004-04-29 11:20:06.000000000 +0200
509@@ -0,0 +1,35 @@
510+/* RSH extension for IP connection tracking, Version 1.0
511+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
512+ * based on HW's ip_conntrack_irc.c
513+ *
514+ * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
515+ *
516+ * This program is free software; you can redistribute it and/or
517+ * modify it under the terms of the GNU General Public License
518+ * as published by the Free Software Foundation; either version
519+ * 2 of the License, or (at your option) any later version.
520+ */
521+#ifndef _IP_CONNTRACK_RSH_H
522+#define _IP_CONNTRACK_RSH_H
523+
524+#ifdef __KERNEL__
525+#include <linux/netfilter_ipv4/lockhelp.h>
526+
527+DECLARE_LOCK_EXTERN(ip_rsh_lock);
528+#endif
529+
530+
531+#define RSH_PORT 514
532+
533+/* This structure is per expected connection */
534+struct ip_ct_rsh_expect
535+{
536+ u_int16_t port;
537+};
538+
539+/* This structure exists only once per master */
540+struct ip_ct_rsh_master {
541+};
542+
543+#endif /* _IP_CONNTRACK_RSH_H */
544+
545diff -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
546--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 1970-01-01 01:00:00.000000000 +0100
547+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2004-04-29 11:20:13.000000000 +0200
548@@ -0,0 +1,68 @@
549+/*
550+ * RTSP extension for IP connection tracking.
551+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
552+ * based on ip_conntrack_irc.h
553+ *
554+ * This program is free software; you can redistribute it and/or
555+ * modify it under the terms of the GNU General Public License
556+ * as published by the Free Software Foundation; either version
557+ * 2 of the License, or (at your option) any later version.
558+ */
559+#ifndef _IP_CONNTRACK_RTSP_H
560+#define _IP_CONNTRACK_RTSP_H
561+
562+/* #define IP_NF_RTSP_DEBUG */
563+#define IP_NF_RTSP_VERSION "0.01"
564+
565+/* port block types */
566+typedef enum {
567+ pb_single, /* client_port=x */
568+ pb_range, /* client_port=x-y */
569+ pb_discon /* client_port=x/y (rtspbis) */
570+} portblock_t;
571+
572+/* We record seq number and length of rtsp headers here, all in host order. */
573+
574+/*
575+ * This structure is per expected connection. It is a member of struct
576+ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored
577+ * there and we are expected to only store the length of the data which
578+ * needs replaced. If a packet contains multiple RTSP messages, we create
579+ * one expected connection per message.
580+ *
581+ * We use these variables to mark the entire header block. This may seem
582+ * like overkill, but the nature of RTSP requires it. A header may appear
583+ * multiple times in a message. We must treat two Transport headers the
584+ * same as one Transport header with two entries.
585+ */
586+struct ip_ct_rtsp_expect
587+{
588+ u_int32_t len; /* length of header block */
589+ portblock_t pbtype; /* Type of port block that was requested */
590+ u_int16_t loport; /* Port that was requested, low or first */
591+ u_int16_t hiport; /* Port that was requested, high or second */
592+#if 0
593+ uint method; /* RTSP method */
594+ uint cseq; /* CSeq from request */
595+#endif
596+};
597+
598+/* This structure exists only once per master */
599+struct ip_ct_rtsp_master
600+{
601+ /* Empty (?) */
602+};
603+
604+
605+#ifdef __KERNEL__
606+
607+#include <linux/netfilter_ipv4/lockhelp.h>
608+
609+#define RTSP_PORT 554
610+
611+/* Protects rtsp part of conntracks */
612+DECLARE_LOCK_EXTERN(ip_rtsp_lock);
613+
614+#endif /* __KERNEL__ */
615+
616+#endif /* _IP_CONNTRACK_RTSP_H */
617diff -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
618--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 1970-01-01 01:00:00.000000000 +0100
619+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h 2004-04-29 11:20:17.000000000 +0200
620@@ -0,0 +1,25 @@
621+#ifndef _IP_CONNTRACK_SCTP_H
622+#define _IP_CONNTRACK_SCTP_H
623+/* SCTP tracking. */
624+
625+enum sctp_conntrack {
626+ SCTP_CONNTRACK_NONE,
627+ SCTP_CONNTRACK_CLOSED,
628+ SCTP_CONNTRACK_COOKIE_WAIT,
629+ SCTP_CONNTRACK_COOKIE_ECHOED,
630+ SCTP_CONNTRACK_ESTABLISHED,
631+ SCTP_CONNTRACK_SHUTDOWN_SENT,
632+ SCTP_CONNTRACK_SHUTDOWN_RECD,
633+ SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
634+ SCTP_CONNTRACK_MAX
635+};
636+
637+struct ip_ct_sctp
638+{
639+ enum sctp_conntrack state;
640+
641+ u_int32_t vtag[IP_CT_DIR_MAX];
642+ u_int32_t ttag[IP_CT_DIR_MAX];
643+};
644+
645+#endif /* _IP_CONNTRACK_SCTP_H */
646diff -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
647--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h 1970-01-01 01:00:00.000000000 +0100
648+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2004-04-29 11:21:43.000000000 +0200
649@@ -0,0 +1,152 @@
650+#ifndef _IP_CONNTRACK_TALK_H
651+#define _IP_CONNTRACK_TALK_H
652+/* TALK tracking. */
653+
654+#ifdef __KERNEL__
655+#include <linux/in.h>
656+#include <linux/netfilter_ipv4/lockhelp.h>
657+
658+/* Protects talk part of conntracks */
659+DECLARE_LOCK_EXTERN(ip_talk_lock);
660+#endif
661+
662+
663+#define TALK_PORT 517
664+#define NTALK_PORT 518
665+
666+/* talk structures and constants from <protocols/talkd.h> */
667+
668+/*
669+ * 4.3BSD struct sockaddr
670+ */
671+struct talk_addr {
672+ u_int16_t ta_family;
673+ u_int16_t ta_port;
674+ u_int32_t ta_addr;
675+ u_int32_t ta_junk1;
676+ u_int32_t ta_junk2;
677+};
678+
679+#define TALK_OLD_NSIZE 9
680+#define TALK_NSIZE 12
681+#define TALK_TTY_NSIZE 16
682+
683+/*
684+ * Client->server request message formats.
685+ */
686+struct talk_msg {
687+ u_char type; /* request type, see below */
688+ char l_name[TALK_OLD_NSIZE];/* caller's name */
689+ char r_name[TALK_OLD_NSIZE];/* callee's name */
690+ u_char pad;
691+ u_int32_t id_num; /* message id */
692+ int32_t pid; /* caller's process id */
693+ char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
694+ struct talk_addr addr; /* old (4.3) style */
695+ struct talk_addr ctl_addr; /* old (4.3) style */
696+};
697+
698+struct ntalk_msg {
699+ u_char vers; /* protocol version */
700+ u_char type; /* request type, see below */
701+ u_char answer; /* not used */
702+ u_char pad;
703+ u_int32_t id_num; /* message id */
704+ struct talk_addr addr; /* old (4.3) style */
705+ struct talk_addr ctl_addr; /* old (4.3) style */
706+ int32_t pid; /* caller's process id */
707+ char l_name[TALK_NSIZE];/* caller's name */
708+ char r_name[TALK_NSIZE];/* callee's name */
709+ char r_tty[TALK_TTY_NSIZE];/* callee's tty name */
710+};
711+
712+struct ntalk2_msg {
713+ u_char vers; /* talk protocol version */
714+ u_char type; /* request type */
715+ u_char answer; /* */
716+ u_char extended; /* !0 if additional parts */
717+ u_int32_t id_num; /* message id number (dels) */
718+ struct talk_addr addr; /* target address */
719+ struct talk_addr ctl_addr; /* reply to address */
720+ int32_t pid; /* caller's process id */
721+ char l_name[TALK_NSIZE]; /* caller's name */
722+ char r_name[TALK_NSIZE]; /* callee's name */
723+ char r_tty[TALK_TTY_NSIZE]; /* callee's tty */
724+};
725+
726+/*
727+ * Server->client response message formats.
728+ */
729+struct talk_response {
730+ u_char type; /* type of request message, see below */
731+ u_char answer; /* response to request message, see below */
732+ u_char pad[2];
733+ u_int32_t id_num; /* message id */
734+ struct talk_addr addr; /* address for establishing conversation */
735+};
736+
737+struct ntalk_response {
738+ u_char vers; /* protocol version */
739+ u_char type; /* type of request message, see below */
740+ u_char answer; /* response to request message, see below */
741+ u_char pad;
742+ u_int32_t id_num; /* message id */
743+ struct talk_addr addr; /* address for establishing conversation */
744+};
745+
746+struct ntalk2_response {
747+ u_char vers; /* protocol version */
748+ u_char type; /* type of request message */
749+ u_char answer; /* response to request */
750+ u_char rvers; /* Version of answering vers*/
751+ u_int32_t id_num; /* message id number */
752+ struct talk_addr addr; /* address for connection */
753+ /* This is at the end to compatiblize this with NTALK version. */
754+ char r_name[TALK_NSIZE]; /* callee's name */
755+};
756+
757+#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
758+#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
759+#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
760+
761+#define TALK_VERSION 0 /* protocol versions */
762+#define NTALK_VERSION 1
763+#define NTALK2_VERSION 2
764+
765+/* message type values */
766+#define LEAVE_INVITE 0 /* leave invitation with server */
767+#define LOOK_UP 1 /* check for invitation by callee */
768+#define DELETE 2 /* delete invitation by caller */
769+#define ANNOUNCE 3 /* announce invitation by caller */
770+/* NTALK2 */
771+#define REPLY_QUERY 4 /* request reply data from local daemon */
772+
773+/* answer values */
774+#define SUCCESS 0 /* operation completed properly */
775+#define NOT_HERE 1 /* callee not logged in */
776+#define FAILED 2 /* operation failed for unexplained reason */
777+#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */
778+#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */
779+#define UNKNOWN_REQUEST 5 /* request has invalid type value */
780+#define BADVERSION 6 /* request has invalid protocol version */
781+#define BADADDR 7 /* request has invalid addr value */
782+#define BADCTLADDR 8 /* request has invalid ctl_addr value */
783+/* NTALK2 */
784+#define NO_CALLER 9 /* no-one calling answer from REPLY */
785+#define TRY_HERE 10 /* Not on this machine, try this */
786+#define SELECTIVE_REFUSAL 11 /* User Filter refusal. */
787+#define MAX_RESPONSE_TYPE 11 /* Make sure this is updated */
788+
789+/* We don't really need much for talk */
790+struct ip_ct_talk_expect
791+{
792+ /* Port that was to be used */
793+ u_int16_t port;
794+};
795+
796+/* This structure exists only once per master */
797+struct ip_ct_talk_master
798+{
799+};
800+
801+#endif /* _IP_CONNTRACK_TALK_H */
802diff -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
803--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-28 03:36:22.000000000 +0200
804+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-29 11:20:17.000000000 +0200
805@@ -25,6 +25,9 @@
806 struct {
807 u_int16_t id;
808 } icmp;
809+ struct {
810+ u_int16_t port;
811+ } sctp;
812 };
813
814 /* The manipulable part of the tuple. */
815@@ -55,6 +58,9 @@
816 struct {
817 u_int8_t type, code;
818 } icmp;
819+ struct {
820+ u_int16_t port;
821+ } sctp;
822 } u;
823
824 /* The protocol. */
825diff -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
826--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h 2004-04-28 03:35:48.000000000 +0200
827+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h 2004-04-29 11:17:15.000000000 +0200
828@@ -134,6 +134,12 @@
829 /* Back pointer */
830 unsigned int comefrom;
831
832+ /* Name of the chain */
833+ char *chainname;
834+
835+ /* Rule number in the chain. */
836+ u_int32_t rulenum;
837+
838 /* Packet and byte counters. */
839 struct ipt_counters counters;
840
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,25 @@
845+#ifndef _IPT_CONNMARK_H_target
846+#define _IPT_CONNMARK_H_target
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+enum {
858+ IPT_CONNMARK_SET = 0,
859+ IPT_CONNMARK_SAVE,
860+ IPT_CONNMARK_RESTORE
861+};
862+
863+struct ipt_connmark_target_info {
864+ unsigned long mark;
865+ unsigned long mask;
866+ u_int8_t mode;
867+};
868+
869+#endif /*_IPT_CONNMARK_H_target*/
870diff -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
871--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
872+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-04-29 11:17:03.000000000 +0200
873@@ -0,0 +1,13 @@
874+#ifndef _IPT_IPMARK_H_target
875+#define _IPT_IPMARK_H_target
876+
877+struct ipt_ipmark_target_info {
878+ unsigned long andmask;
879+ unsigned long ormask;
880+ unsigned int addr;
881+};
882+
883+#define IPT_IPMARK_SRC 0
884+#define IPT_IPMARK_DST 1
885+
886+#endif /*_IPT_IPMARK_H_target*/
887diff -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
888--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
889+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h 2004-04-29 11:17:18.000000000 +0200
890@@ -0,0 +1,9 @@
891+#ifndef _IPT_XOR_H
892+#define _IPT_XOR_H
893+
894+struct ipt_XOR_info {
895+ char key[30];
896+ u_int8_t block_size;
897+};
898+
899+#endif /* _IPT_XOR_H */
900diff -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
901--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
902+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-29 11:17:23.000000000 +0200
903@@ -0,0 +1,11 @@
904+#ifndef _IPT_ADDRTYPE_H
905+#define _IPT_ADDRTYPE_H
906+
907+struct ipt_addrtype_info {
908+ u_int16_t source; /* source-type mask */
909+ u_int16_t dest; /* dest-type mask */
910+ int invert_source;
911+ int invert_dest;
912+};
913+
914+#endif
915diff -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
916--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
917+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-29 11:10:59.000000000 +0200
918@@ -0,0 +1,18 @@
919+#ifndef _IPT_CONNMARK_H
920+#define _IPT_CONNMARK_H
921+
922+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
923+ * by Henrik Nordstrom <hno@marasystems.com>
924+ *
925+ * This program is free software; you can redistribute it and/or modify
926+ * it under the terms of the GNU General Public License as published by
927+ * the Free Software Foundation; either version 2 of the License, or
928+ * (at your option) any later version.
929+ */
930+
931+struct ipt_connmark_info {
932+ unsigned long mark, mask;
933+ u_int8_t invert;
934+};
935+
936+#endif /*_IPT_CONNMARK_H*/
937diff -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
938--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
939+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h 2004-04-29 11:19:41.000000000 +0200
940@@ -0,0 +1,52 @@
941+#ifndef _IPT_POLICY_H
942+#define _IPT_POLICY_H
943+
944+#define POLICY_MAX_ELEM 4
945+
946+enum ipt_policy_flags
947+{
948+ POLICY_MATCH_IN = 0x1,
949+ POLICY_MATCH_OUT = 0x2,
950+ POLICY_MATCH_NONE = 0x4,
951+ POLICY_MATCH_STRICT = 0x8,
952+};
953+
954+enum ipt_policy_modes
955+{
956+ POLICY_MODE_TRANSPORT,
957+ POLICY_MODE_TUNNEL
958+};
959+
960+struct ipt_policy_spec
961+{
962+ u_int8_t saddr:1,
963+ daddr:1,
964+ proto:1,
965+ mode:1,
966+ spi:1,
967+ reqid:1;
968+};
969+
970+struct ipt_policy_elem
971+{
972+ u_int32_t saddr;
973+ u_int32_t smask;
974+ u_int32_t daddr;
975+ u_int32_t dmask;
976+ u_int32_t spi;
977+ u_int32_t reqid;
978+ u_int8_t proto;
979+ u_int8_t mode;
980+
981+ struct ipt_policy_spec match;
982+ struct ipt_policy_spec invert;
983+};
984+
985+struct ipt_policy_info
986+{
987+ struct ipt_policy_elem pol[POLICY_MAX_ELEM];
988+ u_int16_t flags;
989+ u_int16_t len;
990+};
991+
992+#endif /* _IPT_POLICY_H */
993diff -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
994--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
995+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_rpc.h 2004-04-29 11:20:02.000000000 +0200
996@@ -0,0 +1,35 @@
997+/* RPC extension for IP netfilter matching, Version 2.2
998+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
999+ * - original rpc tracking module
1000+ * - "recent" connection handling for kernel 2.3+ netfilter
1001+ *
1002+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1003+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1004+ *
1005+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1006+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
1007+ * - extended matching to support filtering on procedures
1008+ *
1009+ * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
1010+ *
1011+ * This program is free software; you can redistribute it and/or
1012+ * modify it under the terms of the GNU General Public License
1013+ * as published by the Free Software Foundation; either version
1014+ * 2 of the License, or (at your option) any later version.
1015+ **
1016+ */
1017+
1018+#ifndef _IPT_RPC_H
1019+#define _IPT_RPC_H
1020+
1021+struct ipt_rpc_data;
1022+
1023+struct ipt_rpc_info {
1024+ int inverse;
1025+ int strict;
1026+ const char c_procs[1408];
1027+ int i_procs;
1028+ struct ipt_rpc_data *data;
1029+};
1030+
1031+#endif /* _IPT_RPC_H */
1032diff -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
1033--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
1034+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h 2004-04-29 11:21:38.000000000 +0200
1035@@ -0,0 +1,21 @@
1036+#ifndef _IPT_STRING_H
1037+#define _IPT_STRING_H
1038+
1039+/* *** PERFORMANCE TWEAK ***
1040+ * Packet size and search string threshold,
1041+ * above which sublinear searches is used. */
1042+#define IPT_STRING_HAYSTACK_THRESH 100
1043+#define IPT_STRING_NEEDLE_THRESH 20
1044+
1045+#define BM_MAX_NLEN 256
1046+#define BM_MAX_HLEN 1024
1047+
1048+typedef char *(*proc_ipt_search) (char *, char *, int, int);
1049+
1050+struct ipt_string_info {
1051+ char string[BM_MAX_NLEN];
1052+ u_int16_t invert;
1053+ u_int16_t len;
1054+};
1055+
1056+#endif /* _IPT_STRING_H */
1057diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc3/include/linux/netfilter_ipv4.h
1058--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h 2004-04-28 03:36:31.000000000 +0200
1059+++ linux-2.6.6-rc3/include/linux/netfilter_ipv4.h 2004-04-29 11:18:03.000000000 +0200
1060@@ -7,6 +7,8 @@
1061
1062 #include <linux/config.h>
1063 #include <linux/netfilter.h>
1064+#include <linux/netdevice.h>
1065+#include <net/protocol.h>
1066
1067 /* IP Cache bits. */
1068 /* Src IP address. */
1069@@ -85,6 +87,58 @@
1070 Returns true or false. */
1071 extern int skb_ip_make_writable(struct sk_buff **pskb,
1072 unsigned int writable_len);
1073+
1074+#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1075+#include <net/route.h>
1076+#include <net/xfrm.h>
1077+
1078+static inline int nf_hook_input_cond(struct sk_buff *skb)
1079+{
1080+ return !skb->sp || skb->sp->decap_done;
1081+}
1082+
1083+static inline int
1084+nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1085+{
1086+ return skb->sp && !skb->sp->decap_done
1087+ && (!ipprot || !ipprot->xfrm_prot);
1088+}
1089+
1090+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1091+{
1092+ return skb->sp && !skb->sp->decap_done
1093+ && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1094+}
1095+
1096+extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1097+extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1098+#else /* CONFIG_XFRM */
1099+static inline int nf_hook_input_cond(struct sk_buff *skb)
1100+{
1101+ return 1;
1102+}
1103+
1104+static inline int
1105+nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1106+{
1107+ return 0;
1108+}
1109+
1110+static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1111+{
1112+ return 0;
1113+}
1114+
1115+static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1116+{
1117+ return 0;
1118+}
1119+
1120+static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1121+{
1122+ return 0;
1123+}
1124+#endif /* CONFIG_XFRM */
1125 #endif /*__KERNEL__*/
1126
1127 #endif /*__LINUX_IP_NETFILTER_H*/
1128diff -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
1129--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-28 03:36:37.000000000 +0200
1130+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h 2004-04-29 11:17:15.000000000 +0200
1131@@ -140,6 +140,12 @@
1132 /* Back pointer */
1133 unsigned int comefrom;
1134
1135+ /* Name of the chain */
1136+ char *chainname;
1137+
1138+ /* Rule number in the chain. */
1139+ u_int32_t rulenum;
1140+
1141 /* Packet and byte counters. */
1142 struct ip6t_counters counters;
1143
1144diff -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
1145--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-28 03:36:03.000000000 +0200
1146+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h 2004-04-29 11:19:40.000000000 +0200
1147@@ -6,12 +6,14 @@
1148 #define IP6T_OWNER_GID 0x02
1149 #define IP6T_OWNER_PID 0x04
1150 #define IP6T_OWNER_SID 0x08
1151+#define IP6T_OWNER_COMM 0x10
1152
1153 struct ip6t_owner_info {
1154 uid_t uid;
1155 gid_t gid;
1156 pid_t pid;
1157 pid_t sid;
1158+ char comm[16];
1159 u_int8_t match, invert; /* flags */
1160 };
1161
1162diff -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
1163--- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h 1970-01-01 01:00:00.000000000 +0100
1164+++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h 2004-04-29 11:19:41.000000000 +0200
1165@@ -0,0 +1,52 @@
1166+#ifndef _IP6T_POLICY_H\r
1167+#define _IP6T_POLICY_H\r
1168+\r
1169+#define POLICY_MAX_ELEM 4\r
1170+\r
1171+enum ip6t_policy_flags\r
1172+{\r
1173+ POLICY_MATCH_IN = 0x1,\r
1174+ POLICY_MATCH_OUT = 0x2,\r
1175+ POLICY_MATCH_NONE = 0x4,\r
1176+ POLICY_MATCH_STRICT = 0x8,\r
1177+};\r
1178+\r
1179+enum ip6t_policy_modes\r
1180+{\r
1181+ POLICY_MODE_TRANSPORT,\r
1182+ POLICY_MODE_TUNNEL\r
1183+};\r
1184+\r
1185+struct ip6t_policy_spec\r
1186+{\r
1187+ u_int8_t saddr:1,\r
1188+ daddr:1,\r
1189+ proto:1,\r
1190+ mode:1,\r
1191+ spi:1,\r
1192+ reqid:1;\r
1193+};\r
1194+\r
1195+struct ip6t_policy_elem\r
1196+{\r
1197+ struct in6_addr saddr;\r
1198+ struct in6_addr smask;\r
1199+ struct in6_addr daddr;\r
1200+ struct in6_addr dmask;\r
1201+ u_int32_t spi;\r
1202+ u_int32_t reqid;\r
1203+ u_int8_t proto;\r
1204+ u_int8_t mode;\r
1205+\r
1206+ struct ip6t_policy_spec match;\r
1207+ struct ip6t_policy_spec invert;\r
1208+};\r
1209+\r
1210+struct ip6t_policy_info\r
1211+{\r
1212+ struct ip6t_policy_elem pol[POLICY_MAX_ELEM];\r
1213+ u_int16_t flags;\r
1214+ u_int16_t len;\r
1215+};\r
1216+\r
1217+#endif /* _IP6T_POLICY_H */\r
1218diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_mime.h linux-2.6.6-rc3/include/linux/netfilter_mime.h
1219--- linux-2.6.6-rc3.org/include/linux/netfilter_mime.h 1970-01-01 01:00:00.000000000 +0100
1220+++ linux-2.6.6-rc3/include/linux/netfilter_mime.h 2004-04-29 11:20:13.000000000 +0200
1221@@ -0,0 +1,89 @@
1222+/*
1223+ * MIME functions for netfilter modules. This file provides implementations
1224+ * for basic MIME parsing. MIME headers are used in many protocols, such as
1225+ * HTTP, RTSP, SIP, etc.
1226+ *
1227+ * gcc will warn for defined but unused functions, so we only include the
1228+ * functions requested. The following macros are used:
1229+ * NF_NEED_MIME_NEXTLINE nf_mime_nextline()
1230+ */
1231+#ifndef _NETFILTER_MIME_H
1232+#define _NETFILTER_MIME_H
1233+
1234+/* Only include these functions for kernel code. */
1235+#ifdef __KERNEL__
1236+
1237+#include <linux/ctype.h>
1238+
1239+/*
1240+ * Given a buffer and length, advance to the next line and mark the current
1241+ * line. If the current line is empty, *plinelen will be set to zero. If
1242+ * not, it will be set to the actual line length (including CRLF).
1243+ *
1244+ * 'line' in this context means logical line (includes LWS continuations).
1245+ * Returns 1 on success, 0 on failure.
1246+ */
1247+#ifdef NF_NEED_MIME_NEXTLINE
1248+static int
1249+nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1250+{
1251+ uint off = *poff;
1252+ uint physlen = 0;
1253+ int is_first_line = 1;
1254+
1255+ if (off >= len)
1256+ {
1257+ return 0;
1258+ }
1259+
1260+ do
1261+ {
1262+ while (p[off] != '\n')
1263+ {
1264+ if (len-off <= 1)
1265+ {
1266+ return 0;
1267+ }
1268+
1269+ physlen++;
1270+ off++;
1271+ }
1272+
1273+ /* if we saw a crlf, physlen needs adjusted */
1274+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1275+ {
1276+ physlen--;
1277+ }
1278+
1279+ /* advance past the newline */
1280+ off++;
1281+
1282+ /* check for an empty line */
1283+ if (physlen == 0)
1284+ {
1285+ break;
1286+ }
1287+
1288+ /* check for colon on the first physical line */
1289+ if (is_first_line)
1290+ {
1291+ is_first_line = 0;
1292+ if (memchr(p+(*poff), ':', physlen) == NULL)
1293+ {
1294+ return 0;
1295+ }
1296+ }
1297+ }
1298+ while (p[off] == ' ' || p[off] == '\t');
1299+
1300+ *plineoff = *poff;
1301+ *plinelen = (physlen == 0) ? 0 : (off - *poff);
1302+ *poff = off;
1303+
1304+ return 1;
1305+}
1306+#endif /* NF_NEED_MIME_NEXTLINE */
1307+
1308+#endif /* __KERNEL__ */
1309+
1310+#endif /* _NETFILTER_MIME_H */
1311diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/ip.h linux-2.6.6-rc3/include/net/ip.h
1312--- linux-2.6.6-rc3.org/include/net/ip.h 2004-04-28 03:36:16.000000000 +0200
1313+++ linux-2.6.6-rc3/include/net/ip.h 2004-04-29 11:18:02.000000000 +0200
1314@@ -30,6 +30,8 @@
1315 #include <linux/netdevice.h>
1316 #include <linux/inetdevice.h>
1317 #include <linux/in_route.h>
1318+#include <linux/netfilter.h>
1319+#include <linux/netfilter_ipv4.h>
1320 #include <net/route.h>
1321 #include <net/arp.h>
1322
1323@@ -48,6 +50,7 @@
1324 #define IPSKB_TRANSLATED 2
1325 #define IPSKB_FORWARDED 4
1326 #define IPSKB_XFRM_TUNNEL_SIZE 8
1327+#define IPSKB_XFRM_TRANSFORMED 16
1328 };
1329
1330 struct ipcm_cookie
1331@@ -212,6 +215,12 @@
1332 __ip_select_ident(iph, dst, more);
1333 }
1334
1335+extern inline int ip_dst_output(struct sk_buff *skb)
1336+{
1337+ return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1338+ skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1339+}
1340+
1341 /*
1342 * Map a multicast IP onto multicast MAC for type ethernet.
1343 */
1344diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/protocol.h linux-2.6.6-rc3/include/net/protocol.h
1345--- linux-2.6.6-rc3.org/include/net/protocol.h 2004-04-28 03:35:44.000000000 +0200
1346+++ linux-2.6.6-rc3/include/net/protocol.h 2004-04-29 11:18:03.000000000 +0200
1347@@ -39,6 +39,7 @@
1348 int (*handler)(struct sk_buff *skb);
1349 void (*err_handler)(struct sk_buff *skb, u32 info);
1350 int no_policy;
1351+ int xfrm_prot;
1352 };
1353
1354 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
1355diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/tcp.h linux-2.6.6-rc3/include/net/tcp.h
1356--- linux-2.6.6-rc3.org/include/net/tcp.h 2004-04-29 11:24:38.000000000 +0200
1357+++ linux-2.6.6-rc3/include/net/tcp.h 2004-04-29 11:19:32.000000000 +0200
1358@@ -162,6 +162,7 @@
1359 extern void tcp_bucket_unlock(struct sock *sk);
1360 extern int tcp_port_rover;
1361 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
1362+extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
1363
1364 /* These are AF independent. */
1365 static __inline__ int tcp_bhashfn(__u16 lport)
1366diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/udp.h linux-2.6.6-rc3/include/net/udp.h
1367--- linux-2.6.6-rc3.org/include/net/udp.h 2004-04-28 03:36:29.000000000 +0200
1368+++ linux-2.6.6-rc3/include/net/udp.h 2004-04-29 11:19:32.000000000 +0200
1369@@ -74,6 +74,8 @@
1370 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
1371 extern int udp_disconnect(struct sock *sk, int flags);
1372
1373+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
1374+
1375 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
1376 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
1377 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
1378diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/xfrm.h linux-2.6.6-rc3/include/net/xfrm.h
1379--- linux-2.6.6-rc3.org/include/net/xfrm.h 2004-04-28 03:36:31.000000000 +0200
1380+++ linux-2.6.6-rc3/include/net/xfrm.h 2004-04-29 11:18:03.000000000 +0200
1381@@ -540,6 +540,9 @@
1382 {
1383 atomic_t refcnt;
1384 int len;
1385+#ifdef CONFIG_NETFILTER
1386+ int decap_done;
1387+#endif
1388 struct sec_decap_state x[XFRM_MAX_DEPTH];
1389 };
1390
1391diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/core/netfilter.c linux-2.6.6-rc3/net/core/netfilter.c
1392--- linux-2.6.6-rc3.org/net/core/netfilter.c 2004-04-28 03:35:46.000000000 +0200
1393+++ linux-2.6.6-rc3/net/core/netfilter.c 2004-04-29 11:18:06.000000000 +0200
1394@@ -27,6 +27,8 @@
1395 #include <linux/icmp.h>
1396 #include <net/sock.h>
1397 #include <net/route.h>
1398+#include <net/xfrm.h>
1399+#include <net/ip.h>
1400 #include <linux/ip.h>
1401
1402 /* In this code, we can be waiting indefinitely for userspace to
1403@@ -638,7 +640,6 @@
1404 #ifdef CONFIG_IP_ROUTE_FWMARK
1405 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
1406 #endif
1407- fl.proto = iph->protocol;
1408 if (ip_route_output_key(&rt, &fl) != 0)
1409 return -1;
1410
1411@@ -665,6 +666,20 @@
1412 if ((*pskb)->dst->error)
1413 return -1;
1414
1415+#ifdef CONFIG_XFRM
1416+ if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
1417+ struct xfrm_policy_afinfo *afinfo;
1418+
1419+ afinfo = xfrm_policy_get_afinfo(AF_INET);
1420+ if (afinfo != NULL) {
1421+ afinfo->decode_session(*pskb, &fl);
1422+ xfrm_policy_put_afinfo(afinfo);
1423+ if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
1424+ return -1;
1425+ }
1426+ }
1427+#endif
1428+
1429 /* Change in oif may mean change in hh_len. */
1430 hh_len = (*pskb)->dst->dev->hard_header_len;
1431 if (skb_headroom(*pskb) < hh_len) {
1432@@ -682,6 +697,71 @@
1433 return 0;
1434 }
1435
1436+#ifdef CONFIG_XFRM
1437+inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1438+{
1439+ skb->sp->decap_done = 1;
1440+ dst_release(skb->dst);
1441+ skb->dst = NULL;
1442+ nf_reset(skb);
1443+ return netif_rx(skb);
1444+}
1445+
1446+int nf_rcv_postxfrm_local(struct sk_buff *skb)
1447+{
1448+ __skb_push(skb, skb->data - skb->nh.raw);
1449+ /* Fix header len and checksum if last xfrm was transport mode */
1450+ if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
1451+ skb->nh.iph->tot_len = htons(skb->len);
1452+ ip_send_check(skb->nh.iph);
1453+ }
1454+ return nf_rcv_postxfrm_nonlocal(skb);
1455+}
1456+
1457+#ifdef CONFIG_IP_NF_NAT_NEEDED
1458+#include <linux/netfilter_ipv4/ip_conntrack.h>
1459+#include <linux/netfilter_ipv4/ip_nat.h>
1460+
1461+void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
1462+{
1463+ struct ip_conntrack *ct;
1464+ struct ip_conntrack_tuple *t;
1465+ struct ip_nat_info_manip *m;
1466+ unsigned int i;
1467+
1468+ if (skb->nfct == NULL)
1469+ return;
1470+ ct = (struct ip_conntrack *)skb->nfct->master;
1471+
1472+ for (i = 0; i < ct->nat.info.num_manips; i++) {
1473+ m = &ct->nat.info.manips[i];
1474+ t = &ct->tuplehash[m->direction].tuple;
1475+
1476+ switch (m->hooknum) {
1477+ case NF_IP_PRE_ROUTING:
1478+ if (m->maniptype != IP_NAT_MANIP_DST)
1479+ break;
1480+ fl->fl4_dst = t->dst.ip;
1481+ if (t->dst.protonum == IPPROTO_TCP ||
1482+ t->dst.protonum == IPPROTO_UDP)
1483+ fl->fl_ip_dport = t->dst.u.tcp.port;
1484+ break;
1485+#ifdef CONFIG_IP_NF_NAT_LOCAL
1486+ case NF_IP_LOCAL_IN:
1487+ if (m->maniptype != IP_NAT_MANIP_SRC)
1488+ break;
1489+ fl->fl4_src = t->src.ip;
1490+ if (t->dst.protonum == IPPROTO_TCP ||
1491+ t->dst.protonum == IPPROTO_UDP)
1492+ fl->fl_ip_sport = t->src.u.tcp.port;
1493+ break;
1494+#endif
1495+ }
1496+ }
1497+}
1498+#endif /* CONFIG_IP_NF_NAT_NEEDED */
1499+#endif
1500+
1501 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
1502 {
1503 struct sk_buff *nskb;
1504@@ -839,3 +919,4 @@
1505 EXPORT_SYMBOL(nf_unregister_hook);
1506 EXPORT_SYMBOL(nf_unregister_queue_handler);
1507 EXPORT_SYMBOL(nf_unregister_sockopt);
1508+EXPORT_SYMBOL(nf_rcv_postxfrm_local);
1509diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ah4.c linux-2.6.6-rc3/net/ipv4/ah4.c
1510--- linux-2.6.6-rc3.org/net/ipv4/ah4.c 2004-04-28 03:36:34.000000000 +0200
1511+++ linux-2.6.6-rc3/net/ipv4/ah4.c 2004-04-29 11:18:03.000000000 +0200
1512@@ -145,6 +145,7 @@
1513 err = -EHOSTUNREACH;
1514 goto error_nolock;
1515 }
1516+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1517 return NET_XMIT_BYPASS;
1518
1519 error:
1520@@ -343,6 +344,7 @@
1521 .handler = xfrm4_rcv,
1522 .err_handler = ah4_err,
1523 .no_policy = 1,
1524+ .xfrm_prot = 1,
1525 };
1526
1527 static int __init ah4_init(void)
1528diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/esp4.c linux-2.6.6-rc3/net/ipv4/esp4.c
1529--- linux-2.6.6-rc3.org/net/ipv4/esp4.c 2004-04-28 03:36:01.000000000 +0200
1530+++ linux-2.6.6-rc3/net/ipv4/esp4.c 2004-04-29 11:18:03.000000000 +0200
1531@@ -216,6 +216,7 @@
1532 err = -EHOSTUNREACH;
1533 goto error_nolock;
1534 }
1535+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1536 return NET_XMIT_BYPASS;
1537
1538 error:
1539@@ -598,6 +599,7 @@
1540 .handler = xfrm4_rcv,
1541 .err_handler = esp4_err,
1542 .no_policy = 1,
1543+ .xfrm_prot = 1,
1544 };
1545
1546 static int __init esp4_init(void)
1547diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/igmp.c linux-2.6.6-rc3/net/ipv4/igmp.c
1548--- linux-2.6.6-rc3.org/net/ipv4/igmp.c 2004-04-28 03:36:55.000000000 +0200
1549+++ linux-2.6.6-rc3/net/ipv4/igmp.c 2004-04-29 11:18:02.000000000 +0200
1550@@ -342,7 +342,7 @@
1551 pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
1552
1553 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
1554- dst_output);
1555+ ip_dst_output);
1556 }
1557
1558 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
1559@@ -672,7 +672,7 @@
1560 ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
1561
1562 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1563- dst_output);
1564+ ip_dst_output);
1565 }
1566
1567 static void igmp_gq_timer_expire(unsigned long data)
1568diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_forward.c linux-2.6.6-rc3/net/ipv4/ip_forward.c
1569--- linux-2.6.6-rc3.org/net/ipv4/ip_forward.c 2004-04-28 03:34:59.000000000 +0200
1570+++ linux-2.6.6-rc3/net/ipv4/ip_forward.c 2004-04-29 11:18:03.000000000 +0200
1571@@ -51,7 +51,7 @@
1572 if (unlikely(opt->optlen))
1573 ip_forward_options(skb);
1574
1575- return dst_output(skb);
1576+ return ip_dst_output(skb);
1577 }
1578
1579 int ip_forward(struct sk_buff *skb)
1580diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
1581--- linux-2.6.6-rc3.org/net/ipv4/ip_input.c 2004-04-29 11:24:39.000000000 +0200
1582+++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-29 11:18:06.000000000 +0200
1583@@ -206,10 +206,6 @@
1584
1585 __skb_pull(skb, ihl);
1586
1587- /* Free reference early: we don't need it any more, and it may
1588- hold ip_conntrack module loaded indefinitely. */
1589- nf_reset(skb);
1590-
1591 /* Point into the IP datagram, just past the header. */
1592 skb->h.raw = skb->data;
1593
1594@@ -224,6 +220,13 @@
1595 resubmit:
1596 hash = protocol & (MAX_INET_PROTOS - 1);
1597 raw_sk = sk_head(&raw_v4_htable[hash]);
1598+ ipprot = inet_protos[hash];
1599+ smp_read_barrier_depends();
1600+
1601+ if (nf_xfrm_local_done(skb, ipprot)) {
1602+ nf_rcv_postxfrm_local(skb);
1603+ goto out;
1604+ }
1605
1606 /* If there maybe a raw socket we must check - if not we
1607 * don't care less
1608@@ -231,14 +234,15 @@
1609 if (raw_sk)
1610 raw_v4_input(skb, skb->nh.iph, hash);
1611
1612- if ((ipprot = inet_protos[hash]) != NULL) {
1613+ if (ipprot != NULL) {
1614 int ret;
1615
1616- smp_read_barrier_depends();
1617- if (!ipprot->no_policy &&
1618- !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1619- kfree_skb(skb);
1620- goto out;
1621+ if (!ipprot->no_policy) {
1622+ if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1623+ kfree_skb(skb);
1624+ goto out;
1625+ }
1626+ nf_reset(skb);
1627 }
1628 ret = ipprot->handler(skb);
1629 if (ret < 0) {
1630@@ -279,8 +283,8 @@
1631 return 0;
1632 }
1633
1634- return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1635- ip_local_deliver_finish);
1636+ return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1637+ ip_local_deliver_finish, nf_hook_input_cond(skb));
1638 }
1639
1640 static inline int ip_rcv_finish(struct sk_buff *skb)
1641@@ -297,6 +301,9 @@
1642 goto drop;
1643 }
1644
1645+ if (nf_xfrm_nonlocal_done(skb))
1646+ return nf_rcv_postxfrm_nonlocal(skb);
1647+
1648 #ifdef CONFIG_NET_CLS_ROUTE
1649 if (skb->dst->tclassid) {
1650 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
1651@@ -418,8 +425,8 @@
1652 }
1653 }
1654
1655- return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1656- ip_rcv_finish);
1657+ return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1658+ ip_rcv_finish, nf_hook_input_cond(skb));
1659
1660 inhdr_error:
1661 IP_INC_STATS_BH(IpInHdrErrors);
1662diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_output.c linux-2.6.6-rc3/net/ipv4/ip_output.c
1663--- linux-2.6.6-rc3.org/net/ipv4/ip_output.c 2004-04-28 03:36:55.000000000 +0200
1664+++ linux-2.6.6-rc3/net/ipv4/ip_output.c 2004-04-29 11:18:03.000000000 +0200
1665@@ -123,6 +123,15 @@
1666 return ttl;
1667 }
1668
1669+#ifdef CONFIG_NETFILTER
1670+/* out-of-line copy is only required with netfilter */
1671+int ip_dst_output(struct sk_buff *skb)
1672+{
1673+ return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1674+ skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1675+}
1676+#endif
1677+
1678 /*
1679 * Add an ip header to a skbuff and send it out.
1680 *
1681@@ -165,7 +174,7 @@
1682
1683 /* Send it out. */
1684 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1685- dst_output);
1686+ ip_dst_output);
1687 }
1688
1689 static inline int ip_finish_output2(struct sk_buff *skb)
1690@@ -283,7 +292,7 @@
1691 return ip_finish_output(skb);
1692 }
1693
1694-int ip_output(struct sk_buff *skb)
1695+static inline int ip_output2(struct sk_buff *skb)
1696 {
1697 IP_INC_STATS(IpOutRequests);
1698
1699@@ -294,6 +303,16 @@
1700 return ip_finish_output(skb);
1701 }
1702
1703+int ip_output(struct sk_buff *skb)
1704+{
1705+ int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
1706+
1707+ if (transformed)
1708+ nf_reset(skb);
1709+ return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1710+ skb->dst->dev, ip_output2, transformed);
1711+}
1712+
1713 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
1714 {
1715 struct sock *sk = skb->sk;
1716@@ -387,7 +406,7 @@
1717 skb->priority = sk->sk_priority;
1718
1719 return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1720- dst_output);
1721+ ip_dst_output);
1722
1723 no_route:
1724 IP_INC_STATS(IpOutNoRoutes);
1725@@ -1177,7 +1196,7 @@
1726
1727 /* Netfilter gets whole the not fragmented skb. */
1728 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1729- skb->dst->dev, dst_output);
1730+ skb->dst->dev, ip_dst_output);
1731 if (err) {
1732 if (err > 0)
1733 err = inet->recverr ? net_xmit_errno(err) : 0;
1734diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipcomp.c linux-2.6.6-rc3/net/ipv4/ipcomp.c
1735--- linux-2.6.6-rc3.org/net/ipv4/ipcomp.c 2004-04-28 03:36:33.000000000 +0200
1736+++ linux-2.6.6-rc3/net/ipv4/ipcomp.c 2004-04-29 11:18:03.000000000 +0200
1737@@ -231,6 +231,7 @@
1738 err = -EHOSTUNREACH;
1739 goto error_nolock;
1740 }
1741+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1742 err = NET_XMIT_BYPASS;
1743
1744 out_exit:
1745@@ -407,6 +408,7 @@
1746 .handler = xfrm4_rcv,
1747 .err_handler = ipcomp4_err,
1748 .no_policy = 1,
1749+ .xfrm_prot = 1,
1750 };
1751
1752 static int __init ipcomp4_init(void)
1753diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
1754--- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-29 11:24:39.000000000 +0200
1755+++ linux-2.6.6-rc3/net/ipv4/ipip.c 2004-04-29 11:18:03.000000000 +0200
1756@@ -478,6 +478,11 @@
1757
1758 read_lock(&ipip_lock);
1759 if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
1760+ /* IPIP packets decapsulated by IPsec missed netfilter hooks */
1761+ if (nf_xfrm_local_done(skb, NULL)) {
1762+ nf_rcv_postxfrm_local(skb);
1763+ return 0;
1764+ }
1765 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1766 kfree_skb(skb);
1767 return 0;
1768diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipmr.c linux-2.6.6-rc3/net/ipv4/ipmr.c
1769--- linux-2.6.6-rc3.org/net/ipv4/ipmr.c 2004-04-28 03:35:47.000000000 +0200
1770+++ linux-2.6.6-rc3/net/ipv4/ipmr.c 2004-04-29 11:18:03.000000000 +0200
1771@@ -1120,7 +1120,7 @@
1772 if (unlikely(opt->optlen))
1773 ip_forward_options(skb);
1774
1775- return dst_output(skb);
1776+ return ip_dst_output(skb);
1777 }
1778
1779 /*
1780diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
1781--- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig 2004-04-29 11:24:40.000000000 +0200
1782+++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig 2004-04-29 11:21:43.000000000 +0200
1783@@ -206,6 +206,11 @@
1784
1785 To compile it as a module, choose M here. If unsure, say N.
1786
1787+config IP_NF_MATCH_UNCLEAN
1788+ tristate 'unclean match support (EXPERIMENTAL)'
1789+ depends on EXPERIMENTAL && IP_NF_IPTABLES
1790+ help
1791+
1792 config IP_NF_MATCH_TTL
1793 tristate "TTL match support"
1794 depends on IP_NF_IPTABLES
1795@@ -706,5 +711,149 @@
1796 depends on IP_NF_IPTABLES
1797 help
1798
1799+config IP_NF_CONNTRACK_MARK
1800+ bool 'Connection mark tracking support'
1801+config IP_NF_TARGET_CONNMARK
1802+ tristate 'CONNMARK target support'
1803+ depends on IP_NF_MANGLE
1804+config IP_NF_MATCH_CONNMARK
1805+ tristate ' Connection mark match support'
1806+ depends on IP_NF_IPTABLES
1807+ help
1808+
1809+config IP_NF_TARGET_IPMARK
1810+ tristate 'IPMARK target support'
1811+ depends on IP_NF_MANGLE
1812+ help
1813+
1814+config IP_NF_TARGET_TARPIT
1815+ tristate 'TARPIT target support'
1816+ depends on IP_NF_FILTER
1817+ help
1818+
1819+config IP_NF_TARGET_TRACE
1820+ tristate 'TRACE target support'
1821+ depends on IP_NF_RAW
1822+ help
1823+ The TRACE target allows packets to be traced as those
1824+ matches any subsequent rule in any table/rule. The matched
1825+ rule and the packet is logged with the prefix
1826+
1827+ TRACE: tablename/chainname/rulenum
1828+
1829+ If you want to compile it as a module, say M here and read
1830+ <file:Documentation/modules.txt>. If unsure, say `N'.
1831+ help
1832+
1833+config IP_NF_TARGET_XOR
1834+ tristate 'XOR target support'
1835+ depends on IP_NF_MANGLE
1836+ help
1837+
1838+config IP_NF_MATCH_ADDRTYPE
1839+ tristate 'address type match support'
1840+ depends on IP_NF_IPTABLES
1841+ help
1842+
1843+config IP_NF_NAT_CUSEEME
1844+ tristate
1845+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1846+ default IP_NF_NAT if IP_NF_CUSEEME=y
1847+ default m if IP_NF_CUSEEME=m
1848+
1849+config IP_NF_CUSEEME
1850+ tristate 'CuSeeMe protocol support'
1851+ depends on IP_NF_CONNTRACK
1852+ help
1853+
1854+config IP_NF_EGG
1855+ tristate 'Eggdrop bot support'
1856+ depends on IP_NF_CONNTRACK
1857+ help
1858+
1859+config IP_NF_NAT_H323
1860+ tristate
1861+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1862+ default IP_NF_NAT if IP_NF_H323=y
1863+ default m if IP_NF_H323=m
1864+
1865+config IP_NF_H323
1866+ tristate 'H.323 (netmeeting) support'
1867+ depends on IP_NF_CONNTRACK
1868+ help
1869+
1870+config IP_NF_NAT_MMS
1871+ tristate
1872+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1873+ default IP_NF_NAT if IP_NF_MMS=y
1874+ default m if IP_NF_MMS=m
1875+
1876+config IP_NF_MMS
1877+ tristate 'MMS protocol support'
1878+ depends on IP_NF_CONNTRACK
1879+ help
1880+
1881+config IP_NF_MATCH_POLICY
1882+ tristate "IPsec policy match support"
1883+ depends on IP_NF_IPTABLES && XFRM
1884+ help
1885+ Policy matching allows you to match packets based on the
1886+ IPsec policy that was used during decapsulation/will
1887+ be used during encapsulation.
1888+
1889+ To compile it as a module, choose M here. If unsure, say N.
1890+ help
1891+
1892+config IP_NF_NAT_QUAKE3
1893+ tristate
1894+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1895+ default IP_NF_NAT if IP_NF_QUAKE3=y
1896+ default m if IP_NF_QUAKE3=m
1897+
1898+config IP_NF_QUAKE3
1899+ tristate "Quake3 protocol support"
1900+ depends on IP_NF_CONNTRACK
1901+ help
1902+
1903+config IP_NF_MATCH_RPC
1904+ tristate 'RPC match support'
1905+ depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1906+ help
1907+
1908+config IP_NF_RSH
1909+ tristate 'RSH protocol support'
1910+ depends on IP_NF_CONNTRACK
1911+ help
1912+
1913+config IP_NF_NAT_RTSP
1914+ tristate
1915+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1916+ default IP_NF_NAT if IP_NF_RTSP=y
1917+ default m if IP_NF_RTSP=m
1918+config IP_NF_RTSP
1919+ tristate ' RTSP protocol support'
1920+ depends on IP_NF_CONNTRACK
1921+ help
1922+
1923+config IP_NF_CT_PROTO_SCTP
1924+ tristate 'SCTP protocol connection tracking support'
1925+ depends on IP_NF_CONNTRACK
1926+ help
1927+
1928+config IP_NF_MATCH_STRING
1929+ tristate 'String match support'
1930+ depends on IP_NF_IPTABLES
1931+ help
1932+
1933+config IP_NF_NAT_TALK
1934+ tristate
1935+ depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1936+ default IP_NF_NAT if IP_NF_TALK=y
1937+ default m if IP_NF_TALK=m
1938+config IP_NF_TALK
1939+ tristate 'talk protocol support'
1940+ depends on IP_NF_CONNTRACK
1941+ help
1942+
1943 endmenu
1944
1945diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
1946--- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile 2004-04-29 11:24:40.000000000 +0200
1947+++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-29 11:21:43.000000000 +0200
1948@@ -19,17 +19,44 @@
1949 # connection tracking
1950 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1951
1952+# talk protocol support
1953+obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1954+obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1955+
1956+
1957+# SCTP protocol connection tracking
1958+obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
1959+
1960+# H.323 support
1961+obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1962+obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1963+
1964+
1965 # connection tracking helpers
1966+
1967+# rtsp protocol support
1968+obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
1969+obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
1970+
1971+obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1972+obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1973 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1974 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1975 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1976+obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1977+
1978+obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
1979+
1980 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1981
1982 # NAT helpers
1983+obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
1984 obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
1985 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1986 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1987 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1988+obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1989+obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1990
1991 # generic IP tables
1992 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1993@@ -41,6 +83,8 @@
1994 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1995
1996 # matches
1997+obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1998+
1999 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
2000 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
2001 obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
2002@@ -87,14 +132,19 @@
2003 obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
2004
2005
2006+obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
2007+obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
2008 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
2009 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
2010+obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
2011 obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
2012 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
2013 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
2014+obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
2015 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
2016
2017 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
2018+obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
2019
2020 # targets
2021 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
2022@@ -102,6 +152,8 @@
2023 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
2024 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
2025 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
2026+obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
2027+obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
2028 obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
2029 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
2030 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
2031@@ -110,11 +162,14 @@
2032 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
2033 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
2034 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
2035+obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
2036+obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
2037 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
2038 obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
2039 obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
2040 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
2041 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
2042+obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
2043 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
2044
2045 # generic ARP tables
2046diff -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
2047--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-29 11:24:39.000000000 +0200
2048+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-29 11:11:00.000000000 +0200
2049@@ -718,6 +718,9 @@
2050 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
2051 conntrack->master = expected;
2052 expected->sibling = conntrack;
2053+#if CONFIG_IP_NF_CONNTRACK_MARK
2054+ conntrack->mark = expected->expectant->mark;
2055+#endif
2056 LIST_DELETE(&ip_conntrack_expect_list, expected);
2057 expected->expectant->expecting--;
2058 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
2059diff -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
2060--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c 1970-01-01 01:00:00.000000000 +0100
2061+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c 2004-04-29 11:17:59.000000000 +0200
2062@@ -0,0 +1,237 @@
2063+/* Eggdrop extension for IP connection tracking, Version 0.0.5
2064+ * based on ip_conntrack_irc.c
2065+ *
2066+ * This module only supports the share userfile-send command,
2067+ * used by eggdrops to share it's userfile.
2068+ *
2069+ * There are no support for NAT at the moment.
2070+ *
2071+ * This program is free software; you can redistribute it and/or
2072+ * modify it under the terms of the GNU General Public License
2073+ * as published by the Free Software Foundation; either version
2074+ * 2 of the License, or (at your option) any later version.
2075+ *
2076+ * Module load syntax:
2077+ *
2078+ * please give the ports of all Eggdrops You have running
2079+ * on your system, the default port is 3333.
2080+ *
2081+ * 2001-04-19: Security update. IP addresses are now compared
2082+ * to prevent unauthorized "related" access.
2083+ *
2084+ * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
2085+ * Port to netfilter 'newnat' API.
2086+ */
2087+
2088+#include <linux/module.h>
2089+#include <linux/netfilter.h>
2090+#include <linux/ip.h>
2091+#include <net/checksum.h>
2092+#include <net/tcp.h>
2093+
2094+#include <linux/netfilter_ipv4/lockhelp.h>
2095+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2096+
2097+#define MAX_PORTS 8
2098+static int ports[MAX_PORTS];
2099+static int ports_c = 0;
2100+static unsigned int egg_timeout = 300;
2101+
2102+MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
2103+MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
2104+MODULE_LICENSE("GPL");
2105+#ifdef MODULE_PARM
2106+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2107+MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
2108+#endif
2109+
2110+DECLARE_LOCK(ip_egg_lock);
2111+struct module *ip_conntrack_egg = THIS_MODULE;
2112+
2113+#if 0
2114+#define DEBUGP printk
2115+#else
2116+#define DEBUGP(format, args...)
2117+#endif
2118+
2119+int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
2120+/* tries to get the ip_addr and port out of a eggdrop command
2121+ return value: -1 on failure, 0 on success
2122+ data pointer to first byte of DCC command data
2123+ data_end pointer to last byte of dcc command data
2124+ ip returns parsed ip of dcc command
2125+ port returns parsed port of dcc command */
2126+{
2127+ if (data > data_end)
2128+ return -1;
2129+
2130+ *ip = simple_strtoul(data, &data, 10);
2131+
2132+ /* skip blanks between ip and port */
2133+ while (*data == ' ' && data < data_end)
2134+ data++;
2135+
2136+ *port = simple_strtoul(data, &data, 10);
2137+ return 0;
2138+}
2139+
2140+
2141+static int help(const struct iphdr *iph, size_t len,
2142+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
2143+{
2144+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
2145+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
2146+ char *data = (char *) tcph + tcph->doff * 4;
2147+ char *data_limit;
2148+ u_int32_t tcplen = len - iph->ihl * 4;
2149+ u_int32_t datalen = tcplen - tcph->doff * 4;
2150+ int dir = CTINFO2DIR(ctinfo);
2151+ int bytes_scanned = 0;
2152+ struct ip_conntrack_expect exp;
2153+
2154+ u_int32_t egg_ip;
2155+ u_int16_t egg_port;
2156+
2157+ DEBUGP("entered\n");
2158+
2159+ /* If packet is coming from IRC server */
2160+ if (dir != IP_CT_DIR_REPLY)
2161+ return NF_ACCEPT;
2162+
2163+ /* Until there's been traffic both ways, don't look in packets. */
2164+ if (ctinfo != IP_CT_ESTABLISHED
2165+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2166+ DEBUGP("Conntrackinfo = %u\n", ctinfo);
2167+ return NF_ACCEPT;
2168+ }
2169+
2170+ /* Not whole TCP header? */
2171+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
2172+ DEBUGP("tcplen = %u\n", (unsigned) tcplen);
2173+ return NF_ACCEPT;
2174+ }
2175+
2176+ /* Checksum invalid? Ignore. */
2177+ /* FIXME: Source route IP option packets --RR */
2178+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2179+ csum_partial((char *) tcph, tcplen, 0))) {
2180+ DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
2181+ tcph, tcplen, NIPQUAD(iph->saddr),
2182+ NIPQUAD(iph->daddr));
2183+ return NF_ACCEPT;
2184+ }
2185+
2186+ data_limit = (char *) data + datalen;
2187+ while (datalen > 5 && bytes_scanned < 128) {
2188+ if (memcmp(data, "s us ", 5)) {
2189+ data++;
2190+ datalen--;
2191+ bytes_scanned++;
2192+ continue;
2193+ }
2194+
2195+ data += 5;
2196+
2197+ DEBUGP("Userfile-share found in connection "
2198+ "%u.%u.%u.%u -> %u.%u.%u.%u\n",
2199+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
2200+
2201+ if (parse_command((char *) data, data_limit, &egg_ip,
2202+ &egg_port)) {
2203+ DEBUGP("no data in userfile-share pkt\n");
2204+ return NF_ACCEPT;
2205+ }
2206+
2207+ memset(&exp, 0, sizeof(exp));
2208+
2209+ if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
2210+ if (net_ratelimit())
2211+ printk("Forged Eggdrop command from "
2212+ "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
2213+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
2214+ HIPQUAD(egg_ip), egg_port);
2215+ return NF_ACCEPT;
2216+ }
2217+
2218+ exp.tuple.src.ip = iph->daddr;
2219+ exp.tuple.src.u.tcp.port = 0;
2220+ exp.tuple.dst.ip = htonl(egg_ip);
2221+ exp.tuple.dst.u.tcp.port = htons(egg_port);
2222+ exp.tuple.dst.protonum = IPPROTO_TCP;
2223+
2224+ exp.mask.dst.u.tcp.port = 0xffff;
2225+ exp.mask.dst.protonum = 0xffff;
2226+
2227+ DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
2228+ NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
2229+ NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
2230+
2231+ ip_conntrack_expect_related(ct, &exp);
2232+ break;
2233+ }
2234+ return NF_ACCEPT;
2235+}
2236+
2237+static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
2238+static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
2239+
2240+static void deregister_helpers(void) {
2241+ int i;
2242+
2243+ for (i = 0; i < ports_c; i++) {
2244+ DEBUGP("unregistering helper for port %d\n", ports[i]);
2245+ ip_conntrack_helper_unregister(&egg_helpers[i]);
2246+ }
2247+}
2248+
2249+static int __init init(void)
2250+{
2251+ int i, ret;
2252+ char *tmpname;
2253+
2254+ /* If no port given, default to standard eggdrop port */
2255+ if (ports[0] == 0)
2256+ ports[0] = 3333;
2257+
2258+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2259+ memset(&egg_helpers[i], 0,
2260+ sizeof(struct ip_conntrack_helper));
2261+ egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
2262+ egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
2263+ egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
2264+ egg_helpers[i].mask.dst.protonum = 0xFFFF;
2265+ egg_helpers[i].max_expected = 1;
2266+ egg_helpers[i].timeout = egg_timeout;
2267+ egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2268+ egg_helpers[i].me = THIS_MODULE;
2269+ egg_helpers[i].help = help;
2270+
2271+ tmpname = &egg_names[i][0];
2272+ if (ports[i] == 3333)
2273+ sprintf(tmpname, "eggdrop");
2274+ else
2275+ sprintf(tmpname, "eggdrop-%d", ports[i]);
2276+ egg_helpers[i].name = tmpname;
2277+
2278+ DEBUGP("port #%d: %d\n", i, ports[i]);
2279+
2280+ ret = ip_conntrack_helper_register(&egg_helpers[i]);
2281+
2282+ if (ret) {
2283+ printk("ip_conntrack_egg: ERROR registering helper "
2284+ "for port %d\n", ports[i]);
2285+ deregister_helpers();
2286+ return 1;
2287+ }
2288+ ports_c++;
2289+ }
2290+ return 0;
2291+}
2292+
2293+static void __exit fini(void)
2294+{
2295+ deregister_helpers();
2296+}
2297+
2298+module_init(init);
2299+module_exit(fini);
2300diff -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
2301--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c 1970-01-01 01:00:00.000000000 +0100
2302+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c 2004-04-29 11:18:00.000000000 +0200
2303@@ -0,0 +1,308 @@
2304+/*
2305+ * H.323 'brute force' extension for H.323 connection tracking.
2306+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2307+ *
2308+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
2309+ * (http://www.coritel.it/projects/sofia/nat/)
2310+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
2311+ * the unregistered helpers to the conntrack entries.
2312+ */
2313+
2314+
2315+#include <linux/module.h>
2316+#include <linux/netfilter.h>
2317+#include <linux/ip.h>
2318+#include <net/checksum.h>
2319+#include <net/tcp.h>
2320+
2321+#include <linux/netfilter_ipv4/lockhelp.h>
2322+#include <linux/netfilter_ipv4/ip_conntrack.h>
2323+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2324+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2325+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
2326+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
2327+
2328+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
2329+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
2330+MODULE_LICENSE("GPL");
2331+
2332+DECLARE_LOCK(ip_h323_lock);
2333+struct module *ip_conntrack_h323 = THIS_MODULE;
2334+
2335+#if 0
2336+#define DEBUGP printk
2337+#else
2338+#define DEBUGP(format, args...)
2339+#endif
2340+
2341+/* FIXME: This should be in userspace. Later. */
2342+static int h245_help(const struct iphdr *iph, size_t len,
2343+ struct ip_conntrack *ct,
2344+ enum ip_conntrack_info ctinfo)
2345+{
2346+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2347+ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2348+ unsigned char *data_limit;
2349+ u_int32_t tcplen = len - iph->ihl * 4;
2350+ u_int32_t datalen = tcplen - tcph->doff * 4;
2351+ int dir = CTINFO2DIR(ctinfo);
2352+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2353+ struct ip_conntrack_expect expect, *exp = &expect;
2354+ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2355+ u_int16_t data_port;
2356+ u_int32_t data_ip;
2357+ unsigned int i;
2358+
2359+ DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2360+ NIPQUAD(iph->saddr), ntohs(tcph->source),
2361+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
2362+
2363+ /* Can't track connections formed before we registered */
2364+ if (!info)
2365+ return NF_ACCEPT;
2366+
2367+ /* Until there's been traffic both ways, don't look in packets. */
2368+ if (ctinfo != IP_CT_ESTABLISHED
2369+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2370+ DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
2371+ return NF_ACCEPT;
2372+ }
2373+
2374+ /* Not whole TCP header or too short packet? */
2375+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2376+ DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
2377+ return NF_ACCEPT;
2378+ }
2379+
2380+ /* Checksum invalid? Ignore. */
2381+ /* FIXME: Source route IP option packets --RR */
2382+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2383+ csum_partial((char *)tcph, tcplen, 0))) {
2384+ DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2385+ tcph, tcplen, NIPQUAD(iph->saddr),
2386+ NIPQUAD(iph->daddr));
2387+ return NF_ACCEPT;
2388+ }
2389+
2390+ data_limit = (unsigned char *) data + datalen;
2391+ /* bytes: 0123 45
2392+ ipadrr port */
2393+ for (i = 0; data < (data_limit - 5); data++, i++) {
2394+ data_ip = *((u_int32_t *)data);
2395+ if (data_ip == iph->saddr) {
2396+ data_port = *((u_int16_t *)(data + 4));
2397+ memset(&expect, 0, sizeof(expect));
2398+ /* update the H.225 info */
2399+ DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
2400+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2401+ NIPQUAD(iph->saddr), ntohs(data_port));
2402+ LOCK_BH(&ip_h323_lock);
2403+ info->is_h225 = H225_PORT + 1;
2404+ exp_info->port = data_port;
2405+ exp_info->dir = dir;
2406+ exp_info->offset = i;
2407+
2408+ exp->seq = ntohl(tcph->seq) + i;
2409+
2410+ exp->tuple = ((struct ip_conntrack_tuple)
2411+ { { ct->tuplehash[!dir].tuple.src.ip,
2412+ { 0 } },
2413+ { data_ip,
2414+ { .tcp = { data_port } },
2415+ IPPROTO_UDP }});
2416+ exp->mask = ((struct ip_conntrack_tuple)
2417+ { { 0xFFFFFFFF, { 0 } },
2418+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2419+
2420+ exp->expectfn = NULL;
2421+
2422+ /* Ignore failure; should only happen with NAT */
2423+ ip_conntrack_expect_related(ct, exp);
2424+
2425+ UNLOCK_BH(&ip_h323_lock);
2426+ }
2427+ }
2428+
2429+ return NF_ACCEPT;
2430+
2431+}
2432+
2433+/* H.245 helper is not registered! */
2434+static struct ip_conntrack_helper h245 =
2435+ { { NULL, NULL },
2436+ "H.245", /* name */
2437+ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2438+ NULL, /* module */
2439+ 8, /* max_ expected */
2440+ 240, /* timeout */
2441+ { { 0, { 0 } }, /* tuple */
2442+ { 0, { 0 }, IPPROTO_TCP } },
2443+ { { 0, { 0xFFFF } }, /* mask */
2444+ { 0, { 0 }, 0xFFFF } },
2445+ h245_help /* helper */
2446+ };
2447+
2448+static int h225_expect(struct ip_conntrack *ct)
2449+{
2450+ WRITE_LOCK(&ip_conntrack_lock);
2451+ ct->helper = &h245;
2452+ DEBUGP("h225_expect: helper for %p added\n", ct);
2453+ WRITE_UNLOCK(&ip_conntrack_lock);
2454+
2455+ return NF_ACCEPT; /* unused */
2456+}
2457+
2458+/* FIXME: This should be in userspace. Later. */
2459+static int h225_help(const struct iphdr *iph, size_t len,
2460+ struct ip_conntrack *ct,
2461+ enum ip_conntrack_info ctinfo)
2462+{
2463+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2464+ unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2465+ unsigned char *data_limit;
2466+ u_int32_t tcplen = len - iph->ihl * 4;
2467+ u_int32_t datalen = tcplen - tcph->doff * 4;
2468+ int dir = CTINFO2DIR(ctinfo);
2469+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2470+ struct ip_conntrack_expect expect, *exp = &expect;
2471+ struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2472+ u_int16_t data_port;
2473+ u_int32_t data_ip;
2474+ unsigned int i;
2475+
2476+ DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2477+ NIPQUAD(iph->saddr), ntohs(tcph->source),
2478+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
2479+
2480+ /* Can't track connections formed before we registered */
2481+ if (!info)
2482+ return NF_ACCEPT;
2483+
2484+ /* Until there's been traffic both ways, don't look in packets. */
2485+ if (ctinfo != IP_CT_ESTABLISHED
2486+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2487+ DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
2488+ return NF_ACCEPT;
2489+ }
2490+
2491+ /* Not whole TCP header or too short packet? */
2492+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2493+ DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
2494+ return NF_ACCEPT;
2495+ }
2496+
2497+ /* Checksum invalid? Ignore. */
2498+ /* FIXME: Source route IP option packets --RR */
2499+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2500+ csum_partial((char *)tcph, tcplen, 0))) {
2501+ DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2502+ tcph, tcplen, NIPQUAD(iph->saddr),
2503+ NIPQUAD(iph->daddr));
2504+ return NF_ACCEPT;
2505+ }
2506+
2507+ data_limit = (unsigned char *) data + datalen;
2508+ /* bytes: 0123 45
2509+ ipadrr port */
2510+ for (i = 0; data < (data_limit - 5); data++, i++) {
2511+ data_ip = *((u_int32_t *)data);
2512+ if (data_ip == iph->saddr) {
2513+ data_port = *((u_int16_t *)(data + 4));
2514+ if (data_port == tcph->source) {
2515+ /* Signal address */
2516+ DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
2517+ NIPQUAD(iph->saddr));
2518+ /* Update the H.225 info so that NAT can mangle the address/port
2519+ even when we have no expected connection! */
2520+#ifdef CONFIG_IP_NF_NAT_NEEDED
2521+ LOCK_BH(&ip_h323_lock);
2522+ info->dir = dir;
2523+ info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
2524+ info->offset[IP_CT_DIR_ORIGINAL] = i;
2525+ UNLOCK_BH(&ip_h323_lock);
2526+#endif
2527+ } else {
2528+ memset(&expect, 0, sizeof(expect));
2529+
2530+ /* update the H.225 info */
2531+ LOCK_BH(&ip_h323_lock);
2532+ info->is_h225 = H225_PORT;
2533+ exp_info->port = data_port;
2534+ exp_info->dir = dir;
2535+ exp_info->offset = i;
2536+
2537+ exp->seq = ntohl(tcph->seq) + i;
2538+
2539+ exp->tuple = ((struct ip_conntrack_tuple)
2540+ { { ct->tuplehash[!dir].tuple.src.ip,
2541+ { 0 } },
2542+ { data_ip,
2543+ { .tcp = { data_port } },
2544+ IPPROTO_TCP }});
2545+ exp->mask = ((struct ip_conntrack_tuple)
2546+ { { 0xFFFFFFFF, { 0 } },
2547+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2548+
2549+ exp->expectfn = h225_expect;
2550+
2551+ /* Ignore failure */
2552+ ip_conntrack_expect_related(ct, exp);
2553+
2554+ DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
2555+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2556+ NIPQUAD(iph->saddr), ntohs(data_port));
2557+
2558+ UNLOCK_BH(&ip_h323_lock);
2559+ }
2560+#ifdef CONFIG_IP_NF_NAT_NEEDED
2561+ } else if (data_ip == iph->daddr) {
2562+ data_port = *((u_int16_t *)(data + 4));
2563+ if (data_port == tcph->dest) {
2564+ /* Signal address */
2565+ DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
2566+ NIPQUAD(iph->daddr));
2567+ /* Update the H.225 info so that NAT can mangle the address/port
2568+ even when we have no expected connection! */
2569+ LOCK_BH(&ip_h323_lock);
2570+ info->dir = dir;
2571+ info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
2572+ info->offset[IP_CT_DIR_REPLY] = i;
2573+ UNLOCK_BH(&ip_h323_lock);
2574+ }
2575+#endif
2576+ }
2577+ }
2578+
2579+ return NF_ACCEPT;
2580+
2581+}
2582+
2583+static struct ip_conntrack_helper h225 =
2584+ { { NULL, NULL },
2585+ "H.225", /* name */
2586+ IP_CT_HELPER_F_REUSE_EXPECT, /* flags */
2587+ THIS_MODULE, /* module */
2588+ 2, /* max_expected */
2589+ 240, /* timeout */
2590+ { { 0, { __constant_htons(H225_PORT) } }, /* tuple */
2591+ { 0, { 0 }, IPPROTO_TCP } },
2592+ { { 0, { 0xFFFF } }, /* mask */
2593+ { 0, { 0 }, 0xFFFF } },
2594+ h225_help /* helper */
2595+ };
2596+
2597+static int __init init(void)
2598+{
2599+ return ip_conntrack_helper_register(&h225);
2600+}
2601+
2602+static void __exit fini(void)
2603+{
2604+ /* Unregister H.225 helper */
2605+ ip_conntrack_helper_unregister(&h225);
2606+}
2607+
2608+EXPORT_SYMBOL(ip_h323_lock);
2609+
2610+module_init(init);
2611+module_exit(fini);
2612diff -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
2613--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c 1970-01-01 01:00:00.000000000 +0100
2614+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c 2004-04-29 11:19:01.000000000 +0200
2615@@ -0,0 +1,308 @@
2616+/* MMS extension for IP connection tracking
2617+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2618+ * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
2619+ *
2620+ * ip_conntrack_mms.c v0.3 2002-09-22
2621+ *
2622+ * This program is free software; you can redistribute it and/or
2623+ * modify it under the terms of the GNU General Public License
2624+ * as published by the Free Software Foundation; either version
2625+ * 2 of the License, or (at your option) any later version.
2626+ *
2627+ * Module load syntax:
2628+ * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
2629+ *
2630+ * Please give the ports of all MMS servers You wish to connect to.
2631+ * If you don't specify ports, the default will be TCP port 1755.
2632+ *
2633+ * More info on MMS protocol, firewalls and NAT:
2634+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
2635+ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
2636+ *
2637+ * The SDP project people are reverse-engineering MMS:
2638+ * http://get.to/sdp
2639+ */
2640+
2641+#include <linux/config.h>
2642+#include <linux/module.h>
2643+#include <linux/netfilter.h>
2644+#include <linux/ip.h>
2645+#include <linux/ctype.h>
2646+#include <net/checksum.h>
2647+#include <net/tcp.h>
2648+
2649+#include <linux/netfilter_ipv4/lockhelp.h>
2650+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2651+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
2652+
2653+DECLARE_LOCK(ip_mms_lock);
2654+struct module *ip_conntrack_mms = THIS_MODULE;
2655+
2656+#define MAX_PORTS 8
2657+static int ports[MAX_PORTS];
2658+static int ports_c;
2659+#ifdef MODULE_PARM
2660+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2661+#endif
2662+
2663+#if 0
2664+#define DEBUGP printk
2665+#else
2666+#define DEBUGP(format, args...)
2667+#endif
2668+
2669+EXPORT_SYMBOL(ip_mms_lock);
2670+
2671+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2672+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
2673+MODULE_LICENSE("GPL");
2674+
2675+/* #define isdigit(c) (c >= '0' && c <= '9') */
2676+
2677+/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
2678+static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
2679+{
2680+ int i;
2681+ for (i = 0; i < unicode_size; ++i) {
2682+ string[i] = (char)(unicode[i]);
2683+ }
2684+ string[unicode_size] = 0x00;
2685+}
2686+
2687+__inline static int atoi(char *s)
2688+{
2689+ int i=0;
2690+ while (isdigit(*s)) {
2691+ i = i*10 + *(s++) - '0';
2692+ }
2693+ return i;
2694+}
2695+
2696+/* convert ip address string like "192.168.0.10" to unsigned int */
2697+__inline static u_int32_t asciiiptoi(char *s)
2698+{
2699+ unsigned int i, j, k;
2700+
2701+ for(i=k=0; k<3; ++k, ++s, i<<=8) {
2702+ i+=atoi(s);
2703+ for(j=0; (*(++s) != '.') && (j<3); ++j)
2704+ ;
2705+ }
2706+ i+=atoi(s);
2707+ return ntohl(i);
2708+}
2709+
2710+int parse_mms(const char *data,
2711+ const unsigned int datalen,
2712+ u_int32_t *mms_ip,
2713+ u_int16_t *mms_proto,
2714+ u_int16_t *mms_port,
2715+ char **mms_string_b,
2716+ char **mms_string_e,
2717+ char **mms_padding_e)
2718+{
2719+ int unicode_size, i;
2720+ char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
2721+ char getlengthstring[28];
2722+
2723+ for(unicode_size=0;
2724+ (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2725+ unicode_size++)
2726+ if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
2727+ return -1; /* out of bounds - incomplete packet */
2728+
2729+ unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2730+ DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2731+
2732+ /* IP address ? */
2733+ *mms_ip = asciiiptoi(tempstring+2);
2734+
2735+ i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2736+
2737+ /* protocol ? */
2738+ if(strncmp(tempstring+3+i, "TCP", 3)==0)
2739+ *mms_proto = IPPROTO_TCP;
2740+ else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2741+ *mms_proto = IPPROTO_UDP;
2742+
2743+ /* port ? */
2744+ *mms_port = atoi(tempstring+7+i);
2745+
2746+ /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port"
2747+ unicode string, one to the end of the string, and one to the end
2748+ of the packet, since we must keep track of the number of bytes
2749+ between end of the unicode string and the end of packet (padding) */
2750+ *mms_string_b = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2751+ *mms_string_e = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2752+ *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2753+ return 0;
2754+}
2755+
2756+
2757+/* FIXME: This should be in userspace. Later. */
2758+static int help(const struct iphdr *iph, size_t len,
2759+ struct ip_conntrack *ct,
2760+ enum ip_conntrack_info ctinfo)
2761+{
2762+ /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2763+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2764+ const char *data = (const char *)tcph + tcph->doff * 4;
2765+ unsigned int tcplen = len - iph->ihl * 4;
2766+ unsigned int datalen = tcplen - tcph->doff * 4;
2767+ int dir = CTINFO2DIR(ctinfo);
2768+ struct ip_conntrack_expect expect, *exp = &expect;
2769+ struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2770+
2771+ u_int32_t mms_ip;
2772+ u_int16_t mms_proto;
2773+ char mms_proto_string[8];
2774+ u_int16_t mms_port;
2775+ char *mms_string_b, *mms_string_e, *mms_padding_e;
2776+
2777+ /* Until there's been traffic both ways, don't look in packets. */
2778+ if (ctinfo != IP_CT_ESTABLISHED
2779+ && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2780+ DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2781+ return NF_ACCEPT;
2782+ }
2783+
2784+ /* Not whole TCP header? */
2785+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2786+ DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2787+ return NF_ACCEPT;
2788+ }
2789+
2790+ /* Checksum invalid? Ignore. */
2791+ /* FIXME: Source route IP option packets --RR */
2792+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2793+ csum_partial((char *)tcph, tcplen, 0))) {
2794+ DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2795+ tcph, tcplen, NIPQUAD(iph->saddr),
2796+ NIPQUAD(iph->daddr));
2797+ return NF_ACCEPT;
2798+ }
2799+
2800+ /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2801+ /* FIXME: There is an issue with only looking at this packet: before this packet,
2802+ the client has already sent a packet to the server with the server's hostname
2803+ according to the client (think of it as the "Host: " header in HTTP/1.1). The
2804+ server will break the connection if this doesn't correspond to its own host
2805+ header. The client can also connect to an IP address; if it's the server's IP
2806+ address, it will not break the connection. When doing DNAT on a connection
2807+ where the client uses a server's IP address, the nat module should detect
2808+ this and change this string accordingly to the DNATed address. This should
2809+ probably be done by checking for an IP address, then storing it as a member
2810+ of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2811+ */
2812+ if( (MMS_SRV_MSG_OFFSET < datalen) &&
2813+ ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2814+ DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n",
2815+ (u8)*(data+36), (u8)*(data+37),
2816+ (u8)*(data+38), (u8)*(data+39),
2817+ datalen);
2818+ if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2819+ &mms_string_b, &mms_string_e, &mms_padding_e))
2820+ if(net_ratelimit())
2821+ /* FIXME: more verbose debugging ? */
2822+ printk(KERN_WARNING
2823+ "ip_conntrack_mms: Unable to parse data payload\n");
2824+
2825+ memset(&expect, 0, sizeof(expect));
2826+
2827+ sprintf(mms_proto_string, "(%u)", mms_proto);
2828+ DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2829+ mms_proto == IPPROTO_TCP ? "TCP"
2830+ : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2831+ NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2832+ NIPQUAD(mms_ip),
2833+ mms_port);
2834+
2835+ /* it's possible that the client will just ask the server to tunnel
2836+ the stream over the same TCP session (from port 1755): there's
2837+ shouldn't be a need to add an expectation in that case, but it
2838+ makes NAT packet mangling so much easier */
2839+ LOCK_BH(&ip_mms_lock);
2840+
2841+ DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2842+
2843+ exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2844+ exp_mms_info->len = (mms_string_e - mms_string_b);
2845+ exp_mms_info->padding = (mms_padding_e - mms_string_e);
2846+ exp_mms_info->port = mms_port;
2847+
2848+ DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2849+ exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2850+
2851+ exp->tuple = ((struct ip_conntrack_tuple)
2852+ { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2853+ { mms_ip,
2854+ { .tcp = { (__u16) ntohs(mms_port) } },
2855+ mms_proto } }
2856+ );
2857+ exp->mask = ((struct ip_conntrack_tuple)
2858+ { { 0xFFFFFFFF, { 0 } },
2859+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2860+ exp->expectfn = NULL;
2861+ ip_conntrack_expect_related(ct, &expect);
2862+ UNLOCK_BH(&ip_mms_lock);
2863+ }
2864+
2865+ return NF_ACCEPT;
2866+}
2867+
2868+static struct ip_conntrack_helper mms[MAX_PORTS];
2869+static char mms_names[MAX_PORTS][10];
2870+
2871+/* Not __exit: called from init() */
2872+static void fini(void)
2873+{
2874+ int i;
2875+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2876+ DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2877+ ports[i]);
2878+ ip_conntrack_helper_unregister(&mms[i]);
2879+ }
2880+}
2881+
2882+static int __init init(void)
2883+{
2884+ int i, ret;
2885+ char *tmpname;
2886+
2887+ if (ports[0] == 0)
2888+ ports[0] = MMS_PORT;
2889+
2890+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2891+ memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2892+ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2893+ mms[i].tuple.dst.protonum = IPPROTO_TCP;
2894+ mms[i].mask.src.u.tcp.port = 0xFFFF;
2895+ mms[i].mask.dst.protonum = 0xFFFF;
2896+ mms[i].max_expected = 1;
2897+ mms[i].timeout = 0;
2898+ mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2899+ mms[i].me = THIS_MODULE;
2900+ mms[i].help = help;
2901+
2902+ tmpname = &mms_names[i][0];
2903+ if (ports[i] == MMS_PORT)
2904+ sprintf(tmpname, "mms");
2905+ else
2906+ sprintf(tmpname, "mms-%d", ports[i]);
2907+ mms[i].name = tmpname;
2908+
2909+ DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
2910+ ports[i]);
2911+ ret = ip_conntrack_helper_register(&mms[i]);
2912+
2913+ if (ret) {
2914+ fini();
2915+ return ret;
2916+ }
2917+ ports_c++;
2918+ }
2919+ return 0;
2920+}
2921+
2922+module_init(init);
2923+module_exit(fini);
2924diff -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
2925--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
2926+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-04-29 11:20:17.000000000 +0200
2927@@ -0,0 +1,529 @@
2928+/*
2929+ * Connection tracking protocol helper module for SCTP.
2930+ *
2931+ * SCTP is defined in RFC 2960. References to various sections in this code
2932+ * are to this RFC.
2933+ *
2934+ * This program is free software; you can redistribute it and/or modify
2935+ * it under the terms of the GNU General Public License version 2 as
2936+ * published by the Free Software Foundation.
2937+ */
2938+
2939+#include <linux/types.h>
2940+#include <linux/sched.h>
2941+#include <linux/timer.h>
2942+#include <linux/netfilter.h>
2943+#include <linux/module.h>
2944+#include <linux/in.h>
2945+#include <linux/ip.h>
2946+#include <linux/sctp.h>
2947+#include <linux/string.h>
2948+
2949+#include <linux/netfilter_ipv4/ip_conntrack.h>
2950+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2951+#include <linux/netfilter_ipv4/lockhelp.h>
2952+
2953+#if 0
2954+#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
2955+#else
2956+#define DEBUGP(format, args...)
2957+#endif
2958+
2959+/* Protects conntrack->proto.sctp */
2960+static DECLARE_RWLOCK(sctp_lock);
2961+
2962+/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
2963+ closely. They're more complex. --RR
2964+
2965+ And so for me for SCTP :D -Kiran */
2966+
2967+static const char *sctp_conntrack_names[] = {
2968+ "NONE",
2969+ "CLOSED",
2970+ "COOKIE_WAIT",
2971+ "COOKIE_ECHOED",
2972+ "ESTABLISHED",
2973+ "SHUTDOWN_SENT",
2974+ "SHUTDOWN_RECD",
2975+ "SHUTDOWN_ACK_SENT",
2976+};
2977+
2978+#define SECS * HZ
2979+#define MINS * 60 SECS
2980+#define HOURS * 60 MINS
2981+#define DAYS * 24 HOURS
2982+
2983+unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
2984+unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
2985+unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
2986+unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
2987+unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
2988+unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
2989+unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
2990+
2991+static unsigned long * sctp_timeouts[]
2992+= { 0, /* SCTP_CONNTRACK_NONE */
2993+ &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
2994+ &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
2995+ &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
2996+ &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
2997+ &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
2998+ &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
2999+ &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
3000+ };
3001+
3002+#define sNO SCTP_CONNTRACK_NONE
3003+#define sCL SCTP_CONNTRACK_CLOSED
3004+#define sCW SCTP_CONNTRACK_COOKIE_WAIT
3005+#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
3006+#define sES SCTP_CONNTRACK_ESTABLISHED
3007+#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
3008+#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
3009+#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
3010+#define sIV SCTP_CONNTRACK_MAX
3011+
3012+/*
3013+ These are the descriptions of the states:
3014+
3015+NOTE: These state names are tantalizingly similar to the states of an
3016+SCTP endpoint. But the interpretation of the states is a little different,
3017+considering that these are the states of the connection and not of an end
3018+point. Please note the subtleties. -Kiran
3019+
3020+NONE - Nothing so far.
3021+COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
3022+ an INIT_ACK chunk in the reply direction.
3023+COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
3024+ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
3025+SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
3026+SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
3027+SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
3028+ to that of the SHUTDOWN chunk.
3029+CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
3030+ the SHUTDOWN chunk. Connection is closed.
3031+*/
3032+
3033+/* TODO
3034+ - I have assumed that the first INIT is in the original direction.
3035+ This messes things when an INIT comes in the reply direction in CLOSED
3036+ state.
3037+ - Check the error type in the reply dir before transitioning from
3038+cookie echoed to closed.
3039+ - Sec 5.2.4 of RFC 2960
3040+ - Multi Homing support.
3041+*/
3042+
3043+/* SCTP conntrack state transitions */
3044+static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
3045+ {
3046+/* ORIGINAL */
3047+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
3048+/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
3049+/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
3050+/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
3051+/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
3052+/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
3053+/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
3054+/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
3055+/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
3056+/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
3057+ },
3058+ {
3059+/* REPLY */
3060+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
3061+/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
3062+/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
3063+/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
3064+/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
3065+/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
3066+/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
3067+/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
3068+/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
3069+/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
3070+ }
3071+};
3072+
3073+static int sctp_pkt_to_tuple(const struct sk_buff *skb,
3074+ unsigned int dataoff,
3075+ struct ip_conntrack_tuple *tuple)
3076+{
3077+ sctp_sctphdr_t hdr;
3078+
3079+ DEBUGP(__FUNCTION__);
3080+ DEBUGP("\n");
3081+
3082+ /* Actually only need first 8 bytes. */
3083+ if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
3084+ return 0;
3085+
3086+ tuple->src.u.sctp.port = hdr.source;
3087+ tuple->dst.u.sctp.port = hdr.dest;
3088+
3089+ return 1;
3090+}
3091+
3092+static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
3093+ const struct ip_conntrack_tuple *orig)
3094+{
3095+ DEBUGP(__FUNCTION__);
3096+ DEBUGP("\n");
3097+
3098+ tuple->src.u.sctp.port = orig->dst.u.sctp.port;
3099+ tuple->dst.u.sctp.port = orig->src.u.sctp.port;
3100+ return 1;
3101+}
3102+
3103+/* Print out the per-protocol part of the tuple. */
3104+static unsigned int sctp_print_tuple(char *buffer,
3105+ const struct ip_conntrack_tuple *tuple)
3106+{
3107+ DEBUGP(__FUNCTION__);
3108+ DEBUGP("\n");
3109+
3110+ return sprintf(buffer, "sport=%hu dport=%hu ",
3111+ ntohs(tuple->src.u.sctp.port),
3112+ ntohs(tuple->dst.u.sctp.port));
3113+}
3114+
3115+/* Print out the private part of the conntrack. */
3116+static unsigned int sctp_print_conntrack(char *buffer,
3117+ const struct ip_conntrack *conntrack)
3118+{
3119+ enum sctp_conntrack state;
3120+
3121+ DEBUGP(__FUNCTION__);
3122+ DEBUGP("\n");
3123+
3124+ READ_LOCK(&sctp_lock);
3125+ state = conntrack->proto.sctp.state;
3126+ READ_UNLOCK(&sctp_lock);
3127+
3128+ return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
3129+}
3130+
3131+#define for_each_sctp_chunk(skb, sch, offset, count) \
3132+for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
3133+ offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
3134+ offset += (htons(sch.length) + 3) & ~3, count++)
3135+
3136+/* Some validity checks to make sure the chunks are fine */
3137+static int do_basic_checks(struct ip_conntrack *conntrack,
3138+ const struct sk_buff *skb,
3139+ char *map)
3140+{
3141+ u_int32_t offset, count;
3142+ sctp_chunkhdr_t sch;
3143+ int flag;
3144+
3145+ DEBUGP(__FUNCTION__);
3146+ DEBUGP("\n");
3147+
3148+ flag = 0;
3149+
3150+ for_each_sctp_chunk (skb, sch, offset, count) {
3151+ DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
3152+
3153+ if (sch.type == SCTP_CID_INIT
3154+ || sch.type == SCTP_CID_INIT_ACK
3155+ || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3156+ flag = 1;
3157+ }
3158+
3159+ /* Cookie Ack/Echo chunks not the first OR
3160+ Init / Init Ack / Shutdown compl chunks not the only chunks */
3161+ if ((sch.type == SCTP_CID_COOKIE_ACK
3162+ || sch.type == SCTP_CID_COOKIE_ECHO
3163+ || flag)
3164+ && count !=0 ) {
3165+ DEBUGP("Basic checks failed\n");
3166+ return 1;
3167+ }
3168+
3169+ if (map) {
3170+ set_bit (sch.type, (void *)map);
3171+ }
3172+ }
3173+
3174+ DEBUGP("Basic checks passed\n");
3175+ return 0;
3176+}
3177+
3178+static int new_state(enum ip_conntrack_dir dir,
3179+ enum sctp_conntrack cur_state,
3180+ int chunk_type)
3181+{
3182+ int i;
3183+
3184+ DEBUGP(__FUNCTION__);
3185+ DEBUGP("\n");
3186+
3187+ DEBUGP("Chunk type: %d\n", chunk_type);
3188+
3189+ switch (chunk_type) {
3190+ case SCTP_CID_INIT:
3191+ DEBUGP("SCTP_CID_INIT\n");
3192+ i = 0; break;
3193+ case SCTP_CID_INIT_ACK:
3194+ DEBUGP("SCTP_CID_INIT_ACK\n");
3195+ i = 1; break;
3196+ case SCTP_CID_ABORT:
3197+ DEBUGP("SCTP_CID_ABORT\n");
3198+ i = 2; break;
3199+ case SCTP_CID_SHUTDOWN:
3200+ DEBUGP("SCTP_CID_SHUTDOWN\n");
3201+ i = 3; break;
3202+ case SCTP_CID_SHUTDOWN_ACK:
3203+ DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
3204+ i = 4; break;
3205+ case SCTP_CID_ERROR:
3206+ DEBUGP("SCTP_CID_ERROR\n");
3207+ i = 5; break;
3208+ case SCTP_CID_COOKIE_ECHO:
3209+ DEBUGP("SCTP_CID_COOKIE_ECHO\n");
3210+ i = 6; break;
3211+ case SCTP_CID_COOKIE_ACK:
3212+ DEBUGP("SCTP_CID_COOKIE_ACK\n");
3213+ i = 7; break;
3214+ case SCTP_CID_SHUTDOWN_COMPLETE:
3215+ DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
3216+ i = 8; break;
3217+ default:
3218+ /* Other chunks like DATA, SACK, HEARTBEAT and
3219+ its ACK do not cause a change in state */
3220+ DEBUGP("Unknown chunk type, Will stay in %s\n",
3221+ sctp_conntrack_names[cur_state]);
3222+ return cur_state;
3223+ }
3224+
3225+ DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
3226+ dir, sctp_conntrack_names[cur_state], chunk_type,
3227+ sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
3228+
3229+ return sctp_conntracks[dir][i][cur_state];
3230+}
3231+
3232+/* Returns verdict for packet, or -1 for invalid. */
3233+static int sctp_packet(struct ip_conntrack *conntrack,
3234+ const struct sk_buff *skb,
3235+ enum ip_conntrack_info ctinfo)
3236+{
3237+ enum sctp_conntrack newconntrack, oldsctpstate;
3238+ sctp_sctphdr_t sctph;
3239+ sctp_chunkhdr_t sch;
3240+ u_int32_t offset, count;
3241+ char map[256 / sizeof (char)] = {0};
3242+
3243+ DEBUGP(__FUNCTION__);
3244+ DEBUGP("\n");
3245+
3246+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3247+ return -1;
3248+
3249+ if (do_basic_checks(conntrack, skb, map) != 0)
3250+ return -1;
3251+
3252+ /* Check the verification tag (Sec 8.5) */
3253+ if (!test_bit(SCTP_CID_INIT, (void *)map)
3254+ && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
3255+ && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
3256+ && !test_bit(SCTP_CID_ABORT, (void *)map)
3257+ && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
3258+ && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3259+ DEBUGP("Verification tag check failed\n");
3260+ return -1;
3261+ }
3262+
3263+ oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
3264+ for_each_sctp_chunk (skb, sch, offset, count) {
3265+ WRITE_LOCK(&sctp_lock);
3266+
3267+ /* Special cases of Verification tag check (Sec 8.5.1) */
3268+ if (sch.type == SCTP_CID_INIT) {
3269+ /* Sec 8.5.1 (A) */
3270+ if (sctph.vtag != 0) {
3271+ WRITE_UNLOCK(&sctp_lock);
3272+ return -1;
3273+ }
3274+ } else if (sch.type == SCTP_CID_ABORT) {
3275+ /* Sec 8.5.1 (B) */
3276+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3277+ && !(sctph.vtag == conntrack->proto.sctp.vtag
3278+ [1 - CTINFO2DIR(ctinfo)])) {
3279+ WRITE_UNLOCK(&sctp_lock);
3280+ return -1;
3281+ }
3282+ } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3283+ /* Sec 8.5.1 (C) */
3284+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3285+ && !(sctph.vtag == conntrack->proto.sctp.vtag
3286+ [1 - CTINFO2DIR(ctinfo)]
3287+ && (sch.flags & 1))) {
3288+ WRITE_UNLOCK(&sctp_lock);
3289+ return -1;
3290+ }
3291+ } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
3292+ /* Sec 8.5.1 (D) */
3293+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3294+ WRITE_UNLOCK(&sctp_lock);
3295+ return -1;
3296+ }
3297+ }
3298+
3299+ oldsctpstate = conntrack->proto.sctp.state;
3300+ newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
3301+
3302+ /* Invalid */
3303+ if (newconntrack == SCTP_CONNTRACK_MAX) {
3304+ DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
3305+ CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
3306+ WRITE_UNLOCK(&sctp_lock);
3307+ return -1;
3308+ }
3309+
3310+ /* If it is an INIT or an INIT ACK note down the vtag */
3311+ if (sch.type == SCTP_CID_INIT
3312+ || sch.type == SCTP_CID_INIT_ACK) {
3313+ sctp_inithdr_t inithdr;
3314+
3315+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
3316+ &inithdr, sizeof(inithdr)) != 0) {
3317+ WRITE_UNLOCK(&sctp_lock);
3318+ return -1;
3319+ }
3320+ DEBUGP("Setting vtag %x for dir %d\n",
3321+ inithdr.init_tag, CTINFO2DIR(ctinfo));
3322+ conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
3323+ }
3324+
3325+ conntrack->proto.sctp.state = newconntrack;
3326+ WRITE_UNLOCK(&sctp_lock);
3327+ }
3328+
3329+ ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
3330+
3331+ if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
3332+ && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
3333+ && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
3334+ DEBUGP("Setting assured bit\n");
3335+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
3336+ }
3337+
3338+ return NF_ACCEPT;
3339+}
3340+
3341+/* Called when a new connection for this protocol found. */
3342+static int sctp_new(struct ip_conntrack *conntrack,
3343+ const struct sk_buff *skb)
3344+{
3345+ enum sctp_conntrack newconntrack;
3346+ sctp_sctphdr_t sctph;
3347+ sctp_chunkhdr_t sch;
3348+ u_int32_t offset, count;
3349+ char map[256 / sizeof (char)] = {0};
3350+
3351+ DEBUGP(__FUNCTION__);
3352+ DEBUGP("\n");
3353+
3354+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3355+ return -1;
3356+
3357+ if (do_basic_checks(conntrack, skb, map) != 0)
3358+ return -1;
3359+
3360+ /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
3361+ if ((test_bit (SCTP_CID_ABORT, (void *)map))
3362+ || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
3363+ || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
3364+ return -1;
3365+ }
3366+
3367+ newconntrack = SCTP_CONNTRACK_MAX;
3368+ for_each_sctp_chunk (skb, sch, offset, count) {
3369+ /* Don't need lock here: this conntrack not in circulation yet */
3370+ newconntrack = new_state (IP_CT_DIR_ORIGINAL,
3371+ SCTP_CONNTRACK_NONE, sch.type);
3372+
3373+ /* Invalid: delete conntrack */
3374+ if (newconntrack == SCTP_CONNTRACK_MAX) {
3375+ DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
3376+ return 0;
3377+ }
3378+
3379+ /* Copy the vtag into the state info */
3380+ if (sch.type == SCTP_CID_INIT) {
3381+ if (sctph.vtag == 0) {
3382+ sctp_inithdr_t inithdr;
3383+
3384+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
3385+ &inithdr, sizeof(inithdr)) != 0) {
3386+ return -1;
3387+ }
3388+
3389+ DEBUGP("Setting vtag %x for new conn\n",
3390+ inithdr.init_tag);
3391+
3392+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
3393+ inithdr.init_tag;
3394+ } else {
3395+ /* Sec 8.5.1 (A) */
3396+ return -1;
3397+ }
3398+ }
3399+ /* If it is a shutdown ack OOTB packet, we expect a return
3400+ shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
3401+ else {
3402+ DEBUGP("Setting vtag %x for new conn OOTB\n",
3403+ sctph.vtag);
3404+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
3405+ }
3406+
3407+ conntrack->proto.sctp.state = newconntrack;
3408+ }
3409+
3410+ return 1;
3411+}
3412+
3413+static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
3414+ const struct sk_buff *skb)
3415+{
3416+ /* To be implemented */
3417+ return 0;
3418+}
3419+
3420+struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
3421+ .list = { NULL, NULL },
3422+ .proto = IPPROTO_SCTP,
3423+ .name = "sctp",
3424+ .pkt_to_tuple = sctp_pkt_to_tuple,
3425+ .invert_tuple = sctp_invert_tuple,
3426+ .print_tuple = sctp_print_tuple,
3427+ .print_conntrack = sctp_print_conntrack,
3428+ .packet = sctp_packet,
3429+ .new = sctp_new,
3430+ .destroy = NULL,
3431+ .exp_matches_pkt = sctp_exp_matches_pkt,
3432+ .me = THIS_MODULE
3433+};
3434+
3435+int __init init(void)
3436+{
3437+ int ret;
3438+
3439+ ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
3440+ DEBUGP("SCTP conntrack module loading %s\n",
3441+ ret ? "failed": "succeeded");
3442+ return ret;
3443+}
3444+
3445+void __exit fini(void)
3446+{
3447+ ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
3448+ DEBUGP("SCTP conntrack module unloaded\n");
3449+}
3450+
3451+module_init(init);
3452+module_exit(fini);
3453+
3454+MODULE_LICENSE("GPL");
3455+MODULE_AUTHOR("Kiran Kumar Immidi");
3456+MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
3457diff -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
3458--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c 1970-01-01 01:00:00.000000000 +0100
3459+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c 2004-04-29 11:19:53.000000000 +0200
3460@@ -0,0 +1,156 @@
3461+/* Quake3 extension for IP connection tracking
3462+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3463+ * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
3464+ *
3465+ * ip_conntrack_quake3.c v0.04 2002-08-31
3466+ *
3467+ * This program is free software; you can redistribute it and/or
3468+ * modify it under the terms of the GNU General Public License
3469+ * as published by the Free Software Foundation; either version
3470+ * 2 of the License, or (at your option) any later version.
3471+ *
3472+ * Module load syntax:
3473+ * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
3474+ *
3475+ * please give the ports of all Quake3 master servers You wish to
3476+ * connect to. If you don't specify ports, the default will be UDP
3477+ * port 27950.
3478+ *
3479+ * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
3480+ */
3481+
3482+#include <linux/module.h>
3483+#include <linux/ip.h>
3484+#include <linux/udp.h>
3485+
3486+#include <linux/netfilter.h>
3487+#include <linux/netfilter_ipv4/ip_tables.h>
3488+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3489+#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
3490+
3491+struct module *ip_conntrack_quake3 = THIS_MODULE;
3492+
3493+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3494+MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
3495+MODULE_LICENSE("GPL");
3496+
3497+#define MAX_PORTS 8
3498+static int ports[MAX_PORTS];
3499+static int ports_c = 0;
3500+#ifdef MODULE_PARM
3501+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3502+MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
3503+#endif
3504+
3505+/* Quake3 master server reply will add > 100 expectations per reply packet; when
3506+ doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
3507+#if 0
3508+#define DEBUGP printk
3509+#else
3510+#define DEBUGP(format, args...)
3511+#endif
3512+
3513+struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
3514+
3515+static int quake3_help(const struct iphdr *iph, size_t len,
3516+ struct ip_conntrack *ct,
3517+ enum ip_conntrack_info ctinfo)
3518+{
3519+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
3520+ int dir = CTINFO2DIR(ctinfo);
3521+ struct ip_conntrack_expect exp;
3522+ int i;
3523+
3524+ /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
3525+ if (ctinfo != IP_CT_ESTABLISHED
3526+ && ctinfo != IP_CT_IS_REPLY) {
3527+ DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
3528+ return NF_ACCEPT;
3529+ } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
3530+
3531+ if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
3532+ for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
3533+ i+6 < ntohs(udph->len);
3534+ i+=7) {
3535+ DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
3536+ i, ntohs(udph->len),
3537+ NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
3538+ ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
3539+
3540+ memset(&exp, 0, sizeof(exp));
3541+
3542+ exp.tuple = ((struct ip_conntrack_tuple)
3543+ { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3544+ { (u_int32_t) *((u_int32_t *)((int)udph + i)),
3545+ { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } },
3546+ IPPROTO_UDP } }
3547+ );
3548+ exp.mask = ((struct ip_conntrack_tuple)
3549+ { { 0xFFFFFFFF, { 0 } },
3550+ { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
3551+ exp.expectfn = NULL;
3552+
3553+ ip_conntrack_expect_related(ct, &exp);
3554+ }
3555+
3556+ }
3557+
3558+ return(NF_ACCEPT);
3559+}
3560+
3561+static struct ip_conntrack_helper quake3[MAX_PORTS];
3562+static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
3563+
3564+static void fini(void)
3565+{
3566+ int i;
3567+
3568+ for(i = 0 ; (i < ports_c); i++) {
3569+ DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
3570+ ports[i]);
3571+ ip_conntrack_helper_unregister(&quake3[i]);
3572+ }
3573+}
3574+
3575+static int __init init(void)
3576+{
3577+ int i, ret;
3578+ char *tmpname;
3579+
3580+ if(!ports[0])
3581+ ports[0]=QUAKE3_MASTER_PORT;
3582+
3583+ for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
3584+ /* Create helper structure */
3585+ memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
3586+
3587+ quake3[i].tuple.dst.protonum = IPPROTO_UDP;
3588+ quake3[i].tuple.src.u.udp.port = htons(ports[i]);
3589+ quake3[i].mask.dst.protonum = 0xFFFF;
3590+ quake3[i].mask.src.u.udp.port = 0xFFFF;
3591+ quake3[i].help = quake3_help;
3592+ quake3[i].me = THIS_MODULE;
3593+
3594+ tmpname = &quake3_names[i][0];
3595+ if (ports[i] == QUAKE3_MASTER_PORT)
3596+ sprintf(tmpname, "quake3");
3597+ else
3598+ sprintf(tmpname, "quake3-%d", i);
3599+ quake3[i].name = tmpname;
3600+
3601+ DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
3602+ ports[i]);
3603+
3604+ ret=ip_conntrack_helper_register(&quake3[i]);
3605+ if(ret) {
3606+ fini();
3607+ return(ret);
3608+ }
3609+ ports_c++;
3610+ }
3611+
3612+ return(0);
3613+}
3614+
3615+module_init(init);
3616+module_exit(fini);
3617diff -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
3618--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
3619+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2004-04-29 11:20:02.000000000 +0200
3620@@ -0,0 +1,508 @@
3621+/* RPC extension for IP (TCP) connection tracking, Version 2.2
3622+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3623+ * - original rpc tracking module
3624+ * - "recent" connection handling for kernel 2.3+ netfilter
3625+ *
3626+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3627+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3628+ *
3629+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3630+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
3631+ * - extended matching to support filtering on procedures
3632+ *
3633+ * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
3634+ *
3635+ * This program is free software; you can redistribute it and/or
3636+ * modify it under the terms of the GNU General Public License
3637+ * as published by the Free Software Foundation; either version
3638+ * 2 of the License, or (at your option) any later version.
3639+ **
3640+ * Module load syntax:
3641+ * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
3642+ *
3643+ * Please give the ports of all RPC servers you wish to connect to.
3644+ * If you don't specify ports, the default will be port 111.
3645+ **
3646+ * Note to all:
3647+ *
3648+ * RPCs should not be exposed to the internet - ask the Pentagon;
3649+ *
3650+ * "The unidentified crackers pleaded guilty in July to charges
3651+ * of juvenile delinquency stemming from a string of Pentagon
3652+ * network intrusions in February.
3653+ *
3654+ * The youths, going by the names TooShort and Makaveli, used
3655+ * a common server security hole to break in, according to
3656+ * Dane Jasper, owner of the California Internet service
3657+ * provider, Sonic. They used the hole, known as the 'statd'
3658+ * exploit, to attempt more than 800 break-ins, Jasper said."
3659+ *
3660+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3661+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
3662+ **
3663+ */
3664+
3665+#include <linux/module.h>
3666+#include <linux/netfilter.h>
3667+#include <linux/ip.h>
3668+#include <net/checksum.h>
3669+#include <net/tcp.h>
3670+
3671+#include <asm/param.h>
3672+#include <linux/sched.h>
3673+#include <linux/timer.h>
3674+#include <linux/stddef.h>
3675+#include <linux/list.h>
3676+
3677+#include <linux/netfilter_ipv4/lockhelp.h>
3678+#include <linux/netfilter_ipv4/ip_tables.h>
3679+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3680+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3681+
3682+#define MAX_PORTS 8
3683+static int ports[MAX_PORTS];
3684+static int ports_n_c = 0;
3685+
3686+#ifdef MODULE_PARM
3687+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3688+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3689+#endif
3690+
3691+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3692+MODULE_DESCRIPTION("RPC TCP connection tracking module");
3693+MODULE_LICENSE("GPL");
3694+
3695+#if 0
3696+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
3697+ format, ## args)
3698+#else
3699+#define DEBUGP(format, args...)
3700+#endif
3701+
3702+DECLARE_RWLOCK(ipct_rpc_tcp_lock);
3703+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
3704+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
3705+#include <linux/netfilter_ipv4/listhelp.h>
3706+
3707+/* For future conections RPC, using client's cache bindings
3708+ * I'll use ip_conntrack_lock to lock these lists */
3709+
3710+LIST_HEAD(request_p_list_tcp);
3711+
3712+
3713+static void delete_request_p(unsigned long request_p_ul)
3714+{
3715+ struct request_p *p = (void *)request_p_ul;
3716+
3717+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3718+ LIST_DELETE(&request_p_list_tcp, p);
3719+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3720+ kfree(p);
3721+ return;
3722+}
3723+
3724+
3725+static void req_cl(struct request_p * r)
3726+{
3727+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3728+ del_timer(&r->timeout);
3729+ LIST_DELETE(&request_p_list_tcp, r);
3730+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3731+ kfree(r);
3732+ return;
3733+}
3734+
3735+
3736+static void clean_request(struct list_head *list)
3737+{
3738+ struct list_head *first = list->prev;
3739+ struct list_head *temp = list->next;
3740+ struct list_head *aux;
3741+
3742+ if (list_empty(list))
3743+ return;
3744+
3745+ while (first != temp) {
3746+ aux = temp->next;
3747+ req_cl((struct request_p *)temp);
3748+ temp = aux;
3749+ }
3750+ req_cl((struct request_p *)temp);
3751+ return;
3752+}
3753+
3754+
3755+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3756+ u_int16_t port)
3757+{
3758+ struct request_p *req_p;
3759+
3760+ /* Verifies if entry already exists */
3761+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3762+ req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3763+ struct request_p *, xid, ip, port);
3764+
3765+ if (req_p) {
3766+ /* Refresh timeout */
3767+ if (del_timer(&req_p->timeout)) {
3768+ req_p->timeout.expires = jiffies + EXP;
3769+ add_timer(&req_p->timeout);
3770+ }
3771+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3772+ return;
3773+
3774+ }
3775+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3776+
3777+ /* Allocate new request_p */
3778+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3779+ if (!req_p) {
3780+ DEBUGP("can't allocate request_p\n");
3781+ return;
3782+ }
3783+ *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
3784+ { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3785+ NULL }});
3786+
3787+ /* Initialize timer */
3788+ init_timer(&req_p->timeout);
3789+ req_p->timeout.function = delete_request_p;
3790+ add_timer(&req_p->timeout);
3791+
3792+ /* Put in list */
3793+ WRITE_LOCK(&ipct_rpc_tcp_lock);
3794+ list_prepend(&request_p_list_tcp, req_p);
3795+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3796+ return;
3797+
3798+}
3799+
3800+
3801+static int check_rpc_packet(const u_int32_t *data,
3802+ int dir, struct ip_conntrack *ct,
3803+ struct list_head request_p_list)
3804+{
3805+ struct request_p *req_p;
3806+ u_int32_t xid;
3807+ struct ip_conntrack_expect expect, *exp = &expect;
3808+
3809+ /* Translstion's buffer for XDR */
3810+ u_int16_t port_buf;
3811+
3812+
3813+ /* Get XID */
3814+ xid = *data;
3815+
3816+ /* This does sanity checking on RPC payloads,
3817+ * and permits only the RPC "get port" (3)
3818+ * in authorised procedures in client
3819+ * communications with the portmapper.
3820+ */
3821+
3822+ /* perform direction dependant RPC work */
3823+ if (dir == IP_CT_DIR_ORIGINAL) {
3824+
3825+ data += 5;
3826+
3827+ /* Get RPC requestor */
3828+ if (IXDR_GET_INT32(data) != 3) {
3829+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3830+ return NF_ACCEPT;
3831+ }
3832+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3833+
3834+ data++;
3835+
3836+ /* Jump Credentials and Verfifier */
3837+ data += IXDR_GET_INT32(data) + 2;
3838+ data += IXDR_GET_INT32(data) + 2;
3839+
3840+ /* Get RPC procedure */
3841+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3842+ (unsigned int)IXDR_GET_INT32(data));
3843+
3844+ /* Get RPC protocol and store against client parameters */
3845+ data = data + 2;
3846+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3847+ ct->tuplehash[dir].tuple.src.u.all);
3848+
3849+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3850+ xid, IXDR_GET_INT32(data),
3851+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3852+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
3853+
3854+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
3855+ (unsigned int)IXDR_GET_INT32(data));
3856+
3857+ } else {
3858+
3859+ /* Check for returning packet's stored counterpart */
3860+ req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3861+ struct request_p *, xid,
3862+ ct->tuplehash[!dir].tuple.src.ip,
3863+ ct->tuplehash[!dir].tuple.src.u.all);
3864+
3865+ /* Drop unexpected packets */
3866+ if (!req_p) {
3867+ DEBUGP("packet is not expected. [skip]\n");
3868+ return NF_ACCEPT;
3869+ }
3870+
3871+ /* Verifies if packet is really an RPC reply packet */
3872+ data = data++;
3873+ if (IXDR_GET_INT32(data) != 1) {
3874+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
3875+ return NF_ACCEPT;
3876+ }
3877+
3878+ /* Is status accept? */
3879+ data++;
3880+ if (IXDR_GET_INT32(data)) {
3881+ DEBUGP("packet is not an RPC accept. [skip]\n");
3882+ return NF_ACCEPT;
3883+ }
3884+
3885+ /* Get Verifier length. Jump verifier */
3886+ data++;
3887+ data = data + IXDR_GET_INT32(data) + 2;
3888+
3889+ /* Is accpet status "success"? */
3890+ if (IXDR_GET_INT32(data)) {
3891+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3892+ return NF_ACCEPT;
3893+ }
3894+
3895+ /* Get server port number */
3896+ data++;
3897+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
3898+
3899+ /* If a packet has made it this far then it deserves an
3900+ * expectation ... if port == 0, then this service is
3901+ * not going to be registered.
3902+ */
3903+ if (port_buf) {
3904+ DEBUGP("port found: %u\n", port_buf);
3905+
3906+ memset(&expect, 0, sizeof(expect));
3907+
3908+ /* Watch out, Radioactive-Man! */
3909+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3910+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3911+ exp->mask.src.ip = 0xffffffff;
3912+ exp->mask.dst.ip = 0xffffffff;
3913+
3914+ switch (req_p->proto) {
3915+ case IPPROTO_UDP:
3916+ exp->tuple.src.u.udp.port = 0;
3917+ exp->tuple.dst.u.udp.port = htons(port_buf);
3918+ exp->tuple.dst.protonum = IPPROTO_UDP;
3919+ exp->mask.src.u.udp.port = 0;
3920+ exp->mask.dst.u.udp.port = htons(0xffff);
3921+ exp->mask.dst.protonum = 0xffff;
3922+ break;
3923+
3924+ case IPPROTO_TCP:
3925+ exp->tuple.src.u.tcp.port = 0;
3926+ exp->tuple.dst.u.tcp.port = htons(port_buf);
3927+ exp->tuple.dst.protonum = IPPROTO_TCP;
3928+ exp->mask.src.u.tcp.port = 0;
3929+ exp->mask.dst.u.tcp.port = htons(0xffff);
3930+ exp->mask.dst.protonum = 0xffff;
3931+ break;
3932+ }
3933+ exp->expectfn = NULL;
3934+
3935+ ip_conntrack_expect_related(ct, &expect);
3936+
3937+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3938+ NIPQUAD(exp->tuple.src.ip),
3939+ NIPQUAD(exp->tuple.dst.ip),
3940+ port_buf, req_p->proto);
3941+
3942+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3943+ NIPQUAD(exp->mask.src.ip),
3944+ NIPQUAD(exp->mask.dst.ip),
3945+ exp->mask.dst.protonum);
3946+
3947+ }
3948+
3949+ req_cl(req_p);
3950+
3951+ DEBUGP("packet evaluated. [expect]\n");
3952+ return NF_ACCEPT;
3953+ }
3954+
3955+ return NF_ACCEPT;
3956+
3957+}
3958+
3959+
3960+/* RPC TCP helper */
3961+static int help(const struct iphdr *iph, size_t len,
3962+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3963+{
3964+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3965+ const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3966+ size_t tcplen = len - iph->ihl * 4;
3967+
3968+ int dir = CTINFO2DIR(ctinfo);
3969+ int crp_ret;
3970+
3971+
3972+ DEBUGP("new packet to evaluate ..\n");
3973+
3974+ /* This works for packets like handshake packets, ignore */
3975+ if (len == ((tcph->doff + iph->ihl) * 4)) {
3976+ DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3977+ return NF_ACCEPT;
3978+ }
3979+
3980+ /* Until there's been traffic both ways, don't look in packets. */
3981+ if (ctinfo != IP_CT_ESTABLISHED
3982+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3983+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3984+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3985+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3986+ return NF_ACCEPT;
3987+ }
3988+
3989+ /* Not whole TCP header? */
3990+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3991+ DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3992+ DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3993+ return NF_ACCEPT;
3994+ }
3995+
3996+ /* FIXME: Source route IP option packets --RR */
3997+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3998+ csum_partial((char *) tcph, tcplen, 0))) {
3999+ DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4000+ tcph, tcplen, NIPQUAD(iph->saddr),
4001+ NIPQUAD(iph->daddr));
4002+ DEBUGP("[note: failure to get past this error may indicate source routing]\n");
4003+ DEBUGP("packet contains a bad checksum. [skip]\n");
4004+ return NF_ACCEPT;
4005+ }
4006+
4007+ /* perform direction dependant protocol work */
4008+ if (dir == IP_CT_DIR_ORIGINAL) {
4009+
4010+ DEBUGP("packet is from the initiator. [cont]\n");
4011+
4012+ /* Tests if packet len is ok */
4013+ if ((tcplen - (tcph->doff * 4)) != 60) {
4014+ DEBUGP("packet length is not correct. [skip]\n");
4015+ return NF_ACCEPT;
4016+ }
4017+
4018+ } else {
4019+
4020+ DEBUGP("packet is from the receiver. [cont]\n");
4021+
4022+ /* Tests if packet len is ok */
4023+ if ((tcplen - (tcph->doff * 4)) != 32) {
4024+ DEBUGP("packet length is not correct. [skip]\n");
4025+ return NF_ACCEPT;
4026+ }
4027+ }
4028+
4029+ /* Get to the data */
4030+ data++;
4031+
4032+ /* Check the RPC data */
4033+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
4034+
4035+ return crp_ret;
4036+
4037+}
4038+
4039+
4040+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
4041+
4042+static void fini(void);
4043+
4044+
4045+static int __init init(void)
4046+{
4047+ int port, ret;
4048+ static char name[10];
4049+
4050+
4051+ /* If no port given, default to standard RPC port */
4052+ if (ports[0] == 0)
4053+ ports[0] = RPC_PORT;
4054+
4055+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4056+ memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4057+
4058+ if (ports[port] == RPC_PORT)
4059+ sprintf(name, "rpc");
4060+ else
4061+ sprintf(name, "rpc-%d", port);
4062+
4063+ rpc_helpers[port].name = name;
4064+ rpc_helpers[port].me = THIS_MODULE;
4065+ rpc_helpers[port].max_expected = 1;
4066+ rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4067+ rpc_helpers[port].timeout = 0;
4068+
4069+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4070+ rpc_helpers[port].mask.dst.protonum = 0xffff;
4071+
4072+ /* RPC can come from ports 0:65535 to ports[port] (111) */
4073+ rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
4074+ rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
4075+ rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
4076+
4077+ rpc_helpers[port].help = help;
4078+
4079+ DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4080+ DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4081+ NIPQUAD(rpc_helpers[port].tuple.dst.ip),
4082+ ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
4083+ NIPQUAD(rpc_helpers[port].tuple.src.ip),
4084+ ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
4085+ DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4086+ NIPQUAD(rpc_helpers[port].mask.dst.ip),
4087+ ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
4088+ NIPQUAD(rpc_helpers[port].mask.src.ip),
4089+ ntohs(rpc_helpers[port].mask.src.u.tcp.port));
4090+
4091+ ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4092+
4093+ if (ret) {
4094+ printk("ERROR registering port %d\n",
4095+ ports[port]);
4096+ fini();
4097+ return -EBUSY;
4098+ }
4099+ ports_n_c++;
4100+ }
4101+ return 0;
4102+}
4103+
4104+
4105+/* This function is intentionally _NOT_ defined as __exit, because
4106+ * it is needed by the init function */
4107+static void fini(void)
4108+{
4109+ int port;
4110+
4111+ DEBUGP("cleaning request list\n");
4112+ clean_request(&request_p_list_tcp);
4113+
4114+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4115+ DEBUGP("unregistering port %d\n", ports[port]);
4116+ ip_conntrack_helper_unregister(&rpc_helpers[port]);
4117+ }
4118+}
4119+
4120+
4121+module_init(init);
4122+module_exit(fini);
4123+
4124+struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
4125+EXPORT_SYMBOL(request_p_list_tcp);
4126+EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
4127+EXPORT_SYMBOL(ipct_rpc_tcp_lock);
4128+
4129diff -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
4130--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
4131+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2004-04-29 11:20:02.000000000 +0200
4132@@ -0,0 +1,503 @@
4133+/* RPC extension for IP (UDP) connection tracking, Version 2.2
4134+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
4135+ * - original rpc tracking module
4136+ * - "recent" connection handling for kernel 2.3+ netfilter
4137+ *
4138+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
4139+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
4140+ *
4141+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4142+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
4143+ * - extended matching to support filtering on procedures
4144+ *
4145+ * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
4146+ *
4147+ * This program is free software; you can redistribute it and/or
4148+ * modify it under the terms of the GNU General Public License
4149+ * as published by the Free Software Foundation; either version
4150+ * 2 of the License, or (at your option) any later version.
4151+ **
4152+ * Module load syntax:
4153+ * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
4154+ *
4155+ * Please give the ports of all RPC servers you wish to connect to.
4156+ * If you don't specify ports, the default will be port 111.
4157+ **
4158+ * Note to all:
4159+ *
4160+ * RPCs should not be exposed to the internet - ask the Pentagon;
4161+ *
4162+ * "The unidentified crackers pleaded guilty in July to charges
4163+ * of juvenile delinquency stemming from a string of Pentagon
4164+ * network intrusions in February.
4165+ *
4166+ * The youths, going by the names TooShort and Makaveli, used
4167+ * a common server security hole to break in, according to
4168+ * Dane Jasper, owner of the California Internet service
4169+ * provider, Sonic. They used the hole, known as the 'statd'
4170+ * exploit, to attempt more than 800 break-ins, Jasper said."
4171+ *
4172+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
4173+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
4174+ **
4175+ */
4176+
4177+#include <linux/module.h>
4178+#include <linux/netfilter.h>
4179+#include <linux/ip.h>
4180+#include <net/checksum.h>
4181+#include <net/udp.h>
4182+
4183+#include <asm/param.h>
4184+#include <linux/sched.h>
4185+#include <linux/timer.h>
4186+#include <linux/stddef.h>
4187+#include <linux/list.h>
4188+
4189+#include <linux/netfilter_ipv4/lockhelp.h>
4190+#include <linux/netfilter_ipv4/ip_tables.h>
4191+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4192+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
4193+
4194+#define MAX_PORTS 8
4195+static int ports[MAX_PORTS];
4196+static int ports_n_c = 0;
4197+
4198+#ifdef MODULE_PARM
4199+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4200+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
4201+#endif
4202+
4203+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
4204+MODULE_DESCRIPTION("RPC UDP connection tracking module");
4205+MODULE_LICENSE("GPL");
4206+
4207+#if 0
4208+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
4209+ format, ## args)
4210+#else
4211+#define DEBUGP(format, args...)
4212+#endif
4213+
4214+DECLARE_RWLOCK(ipct_rpc_udp_lock);
4215+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
4216+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
4217+#include <linux/netfilter_ipv4/listhelp.h>
4218+
4219+/* For future conections RPC, using client's cache bindings
4220+ * I'll use ip_conntrack_lock to lock these lists */
4221+
4222+LIST_HEAD(request_p_list_udp);
4223+
4224+
4225+static void delete_request_p(unsigned long request_p_ul)
4226+{
4227+ struct request_p *p = (void *)request_p_ul;
4228+
4229+ WRITE_LOCK(&ipct_rpc_udp_lock);
4230+ LIST_DELETE(&request_p_list_udp, p);
4231+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4232+ kfree(p);
4233+ return;
4234+}
4235+
4236+
4237+static void req_cl(struct request_p * r)
4238+{
4239+ WRITE_LOCK(&ipct_rpc_udp_lock);
4240+ del_timer(&r->timeout);
4241+ LIST_DELETE(&request_p_list_udp, r);
4242+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4243+ kfree(r);
4244+ return;
4245+}
4246+
4247+
4248+static void clean_request(struct list_head *list)
4249+{
4250+ struct list_head *first = list->prev;
4251+ struct list_head *temp = list->next;
4252+ struct list_head *aux;
4253+
4254+ if (list_empty(list))
4255+ return;
4256+
4257+ while (first != temp) {
4258+ aux = temp->next;
4259+ req_cl((struct request_p *)temp);
4260+ temp = aux;
4261+ }
4262+ req_cl((struct request_p *)temp);
4263+ return;
4264+}
4265+
4266+
4267+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
4268+ u_int16_t port)
4269+{
4270+ struct request_p *req_p;
4271+
4272+ /* Verifies if entry already exists */
4273+ WRITE_LOCK(&ipct_rpc_udp_lock);
4274+ req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4275+ struct request_p *, xid, ip, port);
4276+
4277+ if (req_p) {
4278+ /* Refresh timeout */
4279+ if (del_timer(&req_p->timeout)) {
4280+ req_p->timeout.expires = jiffies + EXP;
4281+ add_timer(&req_p->timeout);
4282+ }
4283+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4284+ return;
4285+
4286+ }
4287+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4288+
4289+ /* Allocate new request_p */
4290+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
4291+ if (!req_p) {
4292+ DEBUGP("can't allocate request_p\n");
4293+ return;
4294+ }
4295+ *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
4296+ { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
4297+ NULL }});
4298+
4299+ /* Initialize timer */
4300+ init_timer(&req_p->timeout);
4301+ req_p->timeout.function = delete_request_p;
4302+ add_timer(&req_p->timeout);
4303+
4304+ /* Put in list */
4305+ WRITE_LOCK(&ipct_rpc_udp_lock);
4306+ list_prepend(&request_p_list_udp, req_p);
4307+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
4308+ return;
4309+
4310+}
4311+
4312+
4313+static int check_rpc_packet(const u_int32_t *data,
4314+ int dir, struct ip_conntrack *ct,
4315+ struct list_head request_p_list)
4316+{
4317+ struct request_p *req_p;
4318+ u_int32_t xid;
4319+ struct ip_conntrack_expect expect, *exp = &expect;
4320+
4321+ /* Translstion's buffer for XDR */
4322+ u_int16_t port_buf;
4323+
4324+
4325+ /* Get XID */
4326+ xid = *data;
4327+
4328+ /* This does sanity checking on RPC payloads,
4329+ * and permits only the RPC "get port" (3)
4330+ * in authorised procedures in client
4331+ * communications with the portmapper.
4332+ */
4333+
4334+ /* perform direction dependant RPC work */
4335+ if (dir == IP_CT_DIR_ORIGINAL) {
4336+
4337+ data += 5;
4338+
4339+ /* Get RPC requestor */
4340+ if (IXDR_GET_INT32(data) != 3) {
4341+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
4342+ return NF_ACCEPT;
4343+ }
4344+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
4345+
4346+ data++;
4347+
4348+ /* Jump Credentials and Verfifier */
4349+ data = data + IXDR_GET_INT32(data) + 2;
4350+ data = data + IXDR_GET_INT32(data) + 2;
4351+
4352+ /* Get RPC procedure */
4353+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
4354+ (unsigned int)IXDR_GET_INT32(data));
4355+
4356+ /* Get RPC protocol and store against client parameters */
4357+ data = data + 2;
4358+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
4359+ ct->tuplehash[dir].tuple.src.u.all);
4360+
4361+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
4362+ xid, IXDR_GET_INT32(data),
4363+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
4364+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
4365+
4366+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
4367+ (unsigned int)IXDR_GET_INT32(data));
4368+
4369+ } else {
4370+
4371+ /* Check for returning packet's stored counterpart */
4372+ req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4373+ struct request_p *, xid,
4374+ ct->tuplehash[!dir].tuple.src.ip,
4375+ ct->tuplehash[!dir].tuple.src.u.all);
4376+
4377+ /* Drop unexpected packets */
4378+ if (!req_p) {
4379+ DEBUGP("packet is not expected. [skip]\n");
4380+ return NF_ACCEPT;
4381+ }
4382+
4383+ /* Verifies if packet is really an RPC reply packet */
4384+ data = data++;
4385+ if (IXDR_GET_INT32(data) != 1) {
4386+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
4387+ return NF_ACCEPT;
4388+ }
4389+
4390+ /* Is status accept? */
4391+ data++;
4392+ if (IXDR_GET_INT32(data)) {
4393+ DEBUGP("packet is not an RPC accept. [skip]\n");
4394+ return NF_ACCEPT;
4395+ }
4396+
4397+ /* Get Verifier length. Jump verifier */
4398+ data++;
4399+ data = data + IXDR_GET_INT32(data) + 2;
4400+
4401+ /* Is accpet status "success"? */
4402+ if (IXDR_GET_INT32(data)) {
4403+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
4404+ return NF_ACCEPT;
4405+ }
4406+
4407+ /* Get server port number */
4408+ data++;
4409+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
4410+
4411+ /* If a packet has made it this far then it deserves an
4412+ * expectation ... if port == 0, then this service is
4413+ * not going to be registered.
4414+ */
4415+ if (port_buf) {
4416+ DEBUGP("port found: %u\n", port_buf);
4417+
4418+ memset(&expect, 0, sizeof(expect));
4419+
4420+ /* Watch out, Radioactive-Man! */
4421+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4422+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4423+ exp->mask.src.ip = 0xffffffff;
4424+ exp->mask.dst.ip = 0xffffffff;
4425+
4426+ switch (req_p->proto) {
4427+ case IPPROTO_UDP:
4428+ exp->tuple.src.u.udp.port = 0;
4429+ exp->tuple.dst.u.udp.port = htons(port_buf);
4430+ exp->tuple.dst.protonum = IPPROTO_UDP;
4431+ exp->mask.src.u.udp.port = 0;
4432+ exp->mask.dst.u.udp.port = htons(0xffff);
4433+ exp->mask.dst.protonum = 0xffff;
4434+ break;
4435+
4436+ case IPPROTO_TCP:
4437+ exp->tuple.src.u.tcp.port = 0;
4438+ exp->tuple.dst.u.tcp.port = htons(port_buf);
4439+ exp->tuple.dst.protonum = IPPROTO_TCP;
4440+ exp->mask.src.u.tcp.port = 0;
4441+ exp->mask.dst.u.tcp.port = htons(0xffff);
4442+ exp->mask.dst.protonum = 0xffff;
4443+ break;
4444+ }
4445+ exp->expectfn = NULL;
4446+
4447+ ip_conntrack_expect_related(ct, &expect);
4448+
4449+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
4450+ NIPQUAD(exp->tuple.src.ip),
4451+ NIPQUAD(exp->tuple.dst.ip),
4452+ port_buf, req_p->proto);
4453+
4454+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
4455+ NIPQUAD(exp->mask.src.ip),
4456+ NIPQUAD(exp->mask.dst.ip),
4457+ exp->mask.dst.protonum);
4458+
4459+ }
4460+
4461+ req_cl(req_p);
4462+
4463+ DEBUGP("packet evaluated. [expect]\n");
4464+ return NF_ACCEPT;
4465+ }
4466+
4467+ return NF_ACCEPT;
4468+
4469+}
4470+
4471+
4472+/* RPC UDP helper */
4473+static int help(const struct iphdr *iph, size_t len,
4474+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4475+{
4476+ struct udphdr *udph = (void *) iph + iph->ihl * 4;
4477+ const u_int32_t *data = (const u_int32_t *)udph + 2;
4478+ size_t udplen = len - iph->ihl * 4;
4479+ int dir = CTINFO2DIR(ctinfo);
4480+ int crp_ret;
4481+
4482+ /* Checksum */
4483+ const u_int16_t *chsm = (const u_int16_t *)udph + 3;
4484+
4485+
4486+ DEBUGP("new packet to evaluate ..\n");
4487+
4488+ /* Not whole UDP header? */
4489+ if (udplen < sizeof(struct udphdr)) {
4490+ DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
4491+ DEBUGP("packet does not contain a complete UDP header. [skip]\n");
4492+ return NF_ACCEPT;
4493+ }
4494+
4495+ /* FIXME: Source route IP option packets --RR */
4496+ if (*chsm) {
4497+ if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4498+ csum_partial((char *)udph, udplen, 0))) {
4499+ DEBUGP("[note: failure to get past this error may indicate source routing]\n");
4500+ DEBUGP("packet contains a bad checksum. [skip]\n");
4501+ return NF_ACCEPT;
4502+ }
4503+ }
4504+
4505+ /* perform direction dependant protocol work */
4506+ if (dir == IP_CT_DIR_ORIGINAL) {
4507+
4508+ DEBUGP("packet is from the initiator. [cont]\n");
4509+
4510+ /* Tests if packet len is ok */
4511+ if ((udplen - sizeof(struct udphdr)) != 56) {
4512+ DEBUGP("packet length is not correct. [skip]\n");
4513+ return NF_ACCEPT;
4514+ }
4515+
4516+ } else {
4517+
4518+ DEBUGP("packet is from the receiver. [cont]\n");
4519+
4520+ /* Until there's been traffic both ways, don't look in packets. */
4521+ if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4522+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
4523+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
4524+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
4525+ return NF_ACCEPT;
4526+ }
4527+
4528+ /* Tests if packet len is ok */
4529+ if ((udplen - sizeof(struct udphdr)) != 28) {
4530+ DEBUGP("packet length is not correct. [skip]\n");
4531+ return NF_ACCEPT;
4532+ }
4533+
4534+ }
4535+
4536+ /* Get to the data */
4537+ /* udp *data == *correct */
4538+
4539+ /* Check the RPC data */
4540+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
4541+
4542+ return crp_ret;
4543+
4544+}
4545+
4546+
4547+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
4548+
4549+static void fini(void);
4550+
4551+
4552+static int __init init(void)
4553+{
4554+ int port, ret;
4555+ static char name[10];
4556+
4557+
4558+ /* If no port given, default to standard RPC port */
4559+ if (ports[0] == 0)
4560+ ports[0] = RPC_PORT;
4561+
4562+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4563+ memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4564+
4565+ if (ports[port] == RPC_PORT)
4566+ sprintf(name, "rpc");
4567+ else
4568+ sprintf(name, "rpc-%d", port);
4569+
4570+ rpc_helpers[port].name = name;
4571+ rpc_helpers[port].me = THIS_MODULE;
4572+ rpc_helpers[port].max_expected = 1;
4573+ rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4574+ rpc_helpers[port].timeout = 0;
4575+
4576+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
4577+ rpc_helpers[port].mask.dst.protonum = 0xffff;
4578+
4579+ /* RPC can come from ports 0:65535 to ports[port] (111) */
4580+ rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
4581+ rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
4582+ rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
4583+
4584+ rpc_helpers[port].help = help;
4585+
4586+ DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
4587+ DEBUGP("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4588+ NIPQUAD(rpc_helpers[port].tuple.dst.ip),
4589+ ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
4590+ NIPQUAD(rpc_helpers[port].tuple.src.ip),
4591+ ntohs(rpc_helpers[port].tuple.src.u.udp.port));
4592+ DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4593+ NIPQUAD(rpc_helpers[port].mask.dst.ip),
4594+ ntohs(rpc_helpers[port].mask.dst.u.udp.port),
4595+ NIPQUAD(rpc_helpers[port].mask.src.ip),
4596+ ntohs(rpc_helpers[port].mask.src.u.udp.port));
4597+
4598+ ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4599+
4600+ if (ret) {
4601+ printk("ERROR registering port %d\n",
4602+ ports[port]);
4603+ fini();
4604+ return -EBUSY;
4605+ }
4606+ ports_n_c++;
4607+ }
4608+ return 0;
4609+}
4610+
4611+
4612+/* This function is intentionally _NOT_ defined as __exit, because
4613+ * it is needed by the init function */
4614+static void fini(void)
4615+{
4616+ int port;
4617+
4618+ DEBUGP("cleaning request list\n");
4619+ clean_request(&request_p_list_udp);
4620+
4621+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4622+ DEBUGP("unregistering port %d\n", ports[port]);
4623+ ip_conntrack_helper_unregister(&rpc_helpers[port]);
4624+ }
4625+}
4626+
4627+
4628+module_init(init);
4629+module_exit(fini);
4630+
4631+struct module *ip_conntrack_rpc_udp = THIS_MODULE;
4632+EXPORT_SYMBOL(request_p_list_udp);
4633+EXPORT_SYMBOL(ip_conntrack_rpc_udp);
4634+EXPORT_SYMBOL(ipct_rpc_udp_lock);
4635+
4636diff -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
4637--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c 1970-01-01 01:00:00.000000000 +0100
4638+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c 2004-04-29 11:20:06.000000000 +0200
4639@@ -0,0 +1,331 @@
4640+/* RSH extension for IP connection tracking, Version 1.0
4641+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4642+ * based on HW's ip_conntrack_irc.c
4643+ *
4644+ * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
4645+ *
4646+ * This program is free software; you can redistribute it and/or
4647+ * modify it under the terms of the GNU General Public License
4648+ * as published by the Free Software Foundation; either version
4649+ * 2 of the License, or (at your option) any later version.
4650+ **
4651+ * Module load syntax:
4652+ * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
4653+ *
4654+ * please give the ports of all RSH servers You wish to connect to.
4655+ * If You don't specify ports, the default will be port 514
4656+ **
4657+ * Note to all:
4658+ * RSH blows ... you should use SSH (openssh.org) to replace it,
4659+ * unfortunately I babysit some sysadmins that won't migrate
4660+ * their legacy crap, in our second tier.
4661+ */
4662+
4663+
4664+/*
4665+ * Some docco ripped from the net to teach me all there is to know about
4666+ * RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
4667+ * this module).
4668+ *
4669+ * I have no idea what "unix rshd man pages" these guys have .. but that
4670+ * is some pretty detailed docco!
4671+ **
4672+ *
4673+ * 4. Of the rsh protocol.
4674+ * -----------------------
4675+ *
4676+ * The rshd listens on TCP port #514. The following info is from the unix
4677+ * rshd man pages :
4678+ *
4679+ * "Service Request Protocol
4680+ *
4681+ * When the rshd daemon receives a service request, it initiates the
4682+ * following protocol:
4683+ *
4684+ * 1. The rshd daemon checks the source port number for the request.
4685+ * If the port number is not in the range 0 through 1023, the rshd daemon
4686+ * terminates the connection.
4687+ *
4688+ * 2. The rshd daemon reads characters from the socket up to a null byte.
4689+ * The string read is interpreted as an ASCII number (base 10). If this
4690+ * number is nonzero, the rshd daemon interprets it as the port number
4691+ * of a secondary stream to be used as standard error. A second connection
4692+ * is created to the specified port on the client host. The source port
4693+ * on the local host is in the range 0 through 1023.
4694+ *
4695+ * 3. The rshd daemon uses the source address of the initial connection
4696+ * request to determine the name of the client host. If the name cannot
4697+ * be determined, the rshd daemon uses the dotted decimal representation
4698+ * of the client host's address.
4699+ *
4700+ * 4. The rshd daemon retrieves the following information from the initial
4701+ * socket:
4702+ *
4703+ * * A null-terminated string of at most 16 bytes interpreted as
4704+ * the user name of the user on the client host.
4705+ *
4706+ * * A null-terminated string of at most 16 bytes interpreted as
4707+ * the user name to be used on the local server host.
4708+ *
4709+ * * Another null-terminated string interpreted as a command line
4710+ * to be passed to a shell on the local server host.
4711+ *
4712+ * 5. The rshd daemon attempts to validate the user using the following steps:
4713+ *
4714+ * a. The rshd daemon looks up the local user name in the /etc/passwd
4715+ * file and tries to switch to the home directory (using the chdir
4716+ * subroutine). If either the lookup or the directory change fails,
4717+ * the rshd daemon terminates the connection.
4718+ *
4719+ * b. If the local user ID is a nonzero value, the rshd daemon searches
4720+ * the /etc/hosts.equiv file to see if the name of the client
4721+ * workstation is listed. If the client workstation is listed as an
4722+ * equivalent host, the rshd daemon validates the user.
4723+ *
4724+ * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4725+ * authenticate the user by checking the .rhosts file.
4726+ *
4727+ * d. If either the $HOME/.rhosts authentication fails or the
4728+ * client host is not an equivalent host, the rshd daemon
4729+ * terminates the connection.
4730+ *
4731+ * 6. Once rshd validates the user, the rshd daemon returns a null byte
4732+ * on the initial connection and passes the command line to the user's
4733+ * local login shell. The shell then inherits the network connections
4734+ * established by the rshd daemon."
4735+ *
4736+ */
4737+
4738+
4739+#include <linux/module.h>
4740+#include <linux/netfilter.h>
4741+#include <linux/ip.h>
4742+#include <net/checksum.h>
4743+#include <net/tcp.h>
4744+
4745+#include <linux/netfilter_ipv4/lockhelp.h>
4746+#include <linux/netfilter_ipv4/ip_tables.h>
4747+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4748+#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4749+
4750+#define MAX_PORTS 8
4751+static int ports[MAX_PORTS];
4752+static int ports_n_c = 0;
4753+
4754+MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4755+MODULE_DESCRIPTION("RSH connection tracking module");
4756+MODULE_LICENSE("GPL");
4757+#ifdef MODULE_PARM
4758+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4759+MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4760+#endif
4761+
4762+DECLARE_LOCK(ip_rsh_lock);
4763+struct module *ip_conntrack_rsh = THIS_MODULE;
4764+
4765+#if 0
4766+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4767+ format, ## args)
4768+#else
4769+#define DEBUGP(format, args...)
4770+#endif
4771+
4772+
4773+
4774+/* FIXME: This should be in userspace. Later. */
4775+static int help(const struct iphdr *iph, size_t len,
4776+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4777+{
4778+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4779+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4780+ const char *data = (const char *) tcph + tcph->doff * 4;
4781+ u_int32_t tcplen = len - iph->ihl * 4;
4782+ int dir = CTINFO2DIR(ctinfo);
4783+ struct ip_conntrack_expect expect, *exp = &expect;
4784+ struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4785+ u_int16_t port;
4786+ int maxoctet;
4787+
4788+ /* note that "maxoctet" is used to maintain sanity (8 was the
4789+ * original array size used in rshd/glibc) -- is there a
4790+ * vulnerability in rshd.c in the looped port *= 10?
4791+ */
4792+
4793+
4794+ DEBUGP("entered\n");
4795+
4796+ /* bail if packet is not from RSH client */
4797+ if (dir == IP_CT_DIR_REPLY)
4798+ return NF_ACCEPT;
4799+
4800+ /* Until there's been traffic both ways, don't look in packets. */
4801+ if (ctinfo != IP_CT_ESTABLISHED
4802+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4803+ DEBUGP("Conntrackinfo = %u\n", ctinfo);
4804+ return NF_ACCEPT;
4805+ }
4806+
4807+ /* Not whole TCP header? */
4808+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4809+ DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4810+ return NF_ACCEPT;
4811+ }
4812+
4813+ /* Checksum invalid? Ignore. */
4814+ /* FIXME: Source route IP option packets --RR */
4815+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4816+ csum_partial((char *) tcph, tcplen, 0))) {
4817+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4818+ tcph, tcplen, NIPQUAD(iph->saddr),
4819+ NIPQUAD(iph->daddr));
4820+ return NF_ACCEPT;
4821+ }
4822+
4823+ /* find the rsh stderr port */
4824+ maxoctet = 4;
4825+ port = 0;
4826+ for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4827+ if (*data < 0)
4828+ return(1);
4829+ if (*data == 0)
4830+ break;
4831+ if (*data < 48 || *data > 57) {
4832+ DEBUGP("these aren't the packets you're looking for ..\n");
4833+ return NF_ACCEPT;
4834+ }
4835+ port = port * 10 + ( *data - 48 );
4836+ }
4837+
4838+ /* dont relate sessions that try to expose the client */
4839+ DEBUGP("found port %u\n", port);
4840+ if (port > 1023) {
4841+ DEBUGP("skipping, expected port size is greater than 1023!\n");
4842+ return NF_ACCEPT;
4843+ }
4844+
4845+
4846+ LOCK_BH(&ip_rsh_lock);
4847+
4848+ /* new(,related) connection is;
4849+ * reply + dst (uint)port + src port (0:1023)
4850+ */
4851+ memset(&expect, 0, sizeof(expect));
4852+
4853+ /* save some discovered data, in case someone ever wants to write
4854+ * a NAT module for this bastard ..
4855+ */
4856+ exp_rsh_info->port = port;
4857+
4858+ DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4859+
4860+
4861+ /* Watch out, Radioactive-Man! */
4862+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4863+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4864+ exp->tuple.src.u.tcp.port = 0;
4865+ exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4866+ exp->tuple.dst.protonum = IPPROTO_TCP;
4867+
4868+ exp->mask.src.ip = 0xffffffff;
4869+ exp->mask.dst.ip = 0xffffffff;
4870+
4871+ exp->mask.src.u.tcp.port = htons(0xfc00);
4872+ exp->mask.dst.u.tcp.port = htons(0xfc00);
4873+ exp->mask.dst.protonum = 0xffff;
4874+
4875+ exp->expectfn = NULL;
4876+
4877+ ip_conntrack_expect_related(ct, &expect);
4878+
4879+ DEBUGP("expect related ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4880+ NIPQUAD(exp->tuple.src.ip),
4881+ ntohs(exp->tuple.src.u.tcp.port),
4882+ NIPQUAD(exp->tuple.dst.ip),
4883+ ntohs(exp->tuple.dst.u.tcp.port));
4884+
4885+ DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4886+ NIPQUAD(exp->mask.src.ip),
4887+ ntohs(exp->mask.src.u.tcp.port),
4888+ NIPQUAD(exp->mask.dst.ip),
4889+ ntohs(exp->mask.dst.u.tcp.port));
4890+ UNLOCK_BH(&ip_rsh_lock);
4891+
4892+ return NF_ACCEPT;
4893+}
4894+
4895+static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4896+
4897+static void fini(void);
4898+
4899+static int __init init(void)
4900+{
4901+ int port, ret;
4902+ static char name[10];
4903+
4904+
4905+ /* If no port given, default to standard RSH port */
4906+ if (ports[0] == 0)
4907+ ports[0] = RSH_PORT;
4908+
4909+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4910+ memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4911+
4912+ if (ports[port] == RSH_PORT)
4913+ sprintf(name, "rsh");
4914+ else
4915+ sprintf(name, "rsh-%d", port);
4916+
4917+ rsh_helpers[port].name = name;
4918+ rsh_helpers[port].me = THIS_MODULE;
4919+ rsh_helpers[port].max_expected = 1;
4920+ rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4921+ rsh_helpers[port].timeout = 0;
4922+
4923+ rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4924+ rsh_helpers[port].mask.dst.protonum = 0xffff;
4925+
4926+ /* RSH must come from ports 0:1023 to ports[port] (514) */
4927+ rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4928+ rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4929+ rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4930+
4931+ rsh_helpers[port].help = help;
4932+
4933+ DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4934+ DEBUGP("helper match ip %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4935+ NIPQUAD(rsh_helpers[port].tuple.src.ip),
4936+ ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4937+ NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4938+ ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4939+ DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4940+ NIPQUAD(rsh_helpers[port].mask.src.ip),
4941+ ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4942+ NIPQUAD(rsh_helpers[port].mask.dst.ip),
4943+ ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4944+
4945+ ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4946+
4947+ if (ret) {
4948+ printk("ERROR registering port %d\n",
4949+ ports[port]);
4950+ fini();
4951+ return -EBUSY;
4952+ }
4953+ ports_n_c++;
4954+ }
4955+ return 0;
4956+}
4957+
4958+/* This function is intentionally _NOT_ defined as __exit, because
4959+ * it is needed by the init function */
4960+static void fini(void)
4961+{
4962+ int port;
4963+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4964+ DEBUGP("unregistering port %d\n", ports[port]);
4965+ ip_conntrack_helper_unregister(&rsh_helpers[port]);
4966+ }
4967+}
4968+
4969+module_init(init);
4970+module_exit(fini);
4971diff -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
4972--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c 1970-01-01 01:00:00.000000000 +0100
4973+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c 2004-04-29 11:20:13.000000000 +0200
4974@@ -0,0 +1,507 @@
4975+/*
4976+ * RTSP extension for IP connection tracking
4977+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
4978+ * based on ip_conntrack_irc.c
4979+ *
4980+ * This program is free software; you can redistribute it and/or
4981+ * modify it under the terms of the GNU General Public License
4982+ * as published by the Free Software Foundation; either version
4983+ * 2 of the License, or (at your option) any later version.
4984+ *
4985+ * Module load syntax:
4986+ * insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
4987+ * max_outstanding=n setup_timeout=secs
4988+ *
4989+ * If no ports are specified, the default will be port 554.
4990+ *
4991+ * With max_outstanding you can define the maximum number of not yet
4992+ * answered SETUP requests per RTSP session (default 8).
4993+ * With setup_timeout you can specify how long the system waits for
4994+ * an expected data channel (default 300 seconds).
4995+ */
4996+
4997+#include <linux/config.h>
4998+#include <linux/module.h>
4999+#include <linux/netfilter.h>
5000+#include <linux/ip.h>
5001+#include <net/checksum.h>
5002+#include <net/tcp.h>
5003+
5004+#include <linux/netfilter_ipv4/lockhelp.h>
5005+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5006+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5007+
5008+#include <linux/ctype.h>
5009+#define NF_NEED_STRNCASECMP
5010+#define NF_NEED_STRTOU16
5011+#define NF_NEED_STRTOU32
5012+#define NF_NEED_NEXTLINE
5013+#include <linux/netfilter_helpers.h>
5014+#define NF_NEED_MIME_NEXTLINE
5015+#include <linux/netfilter_mime.h>
5016+
5017+#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5018+
5019+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5020+#ifdef IP_NF_RTSP_DEBUG
5021+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5022+#else
5023+#define DEBUGP(fmt, args...)
5024+#endif
5025+
5026+#define MAX_PORTS 8
5027+static int ports[MAX_PORTS];
5028+static int num_ports = 0;
5029+static int max_outstanding = 8;
5030+static unsigned int setup_timeout = 300;
5031+
5032+MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5033+MODULE_DESCRIPTION("RTSP connection tracking module");
5034+MODULE_LICENSE("GPL");
5035+#ifdef MODULE_PARM
5036+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5037+MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5038+MODULE_PARM(max_outstanding, "i");
5039+MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5040+MODULE_PARM(setup_timeout, "i");
5041+MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5042+#endif
5043+
5044+DECLARE_LOCK(ip_rtsp_lock);
5045+struct module* ip_conntrack_rtsp = THIS_MODULE;
5046+
5047+/*
5048+ * Max mappings we will allow for one RTSP connection (for RTP, the number
5049+ * of allocated ports is twice this value). Note that SMIL burns a lot of
5050+ * ports so keep this reasonably high. If this is too low, you will see a
5051+ * lot of "no free client map entries" messages.
5052+ */
5053+#define MAX_PORT_MAPS 16
5054+
5055+/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5056+
5057+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5058+
5059+/*
5060+ * Parse an RTSP packet.
5061+ *
5062+ * Returns zero if parsing failed.
5063+ *
5064+ * Parameters:
5065+ * IN ptcp tcp data pointer
5066+ * IN tcplen tcp data len
5067+ * IN/OUT ptcpoff points to current tcp offset
5068+ * OUT phdrsoff set to offset of rtsp headers
5069+ * OUT phdrslen set to length of rtsp headers
5070+ * OUT pcseqoff set to offset of CSeq header
5071+ * OUT pcseqlen set to length of CSeq header
5072+ */
5073+static int
5074+rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5075+ uint* phdrsoff, uint* phdrslen,
5076+ uint* pcseqoff, uint* pcseqlen)
5077+{
5078+ uint entitylen = 0;
5079+ uint lineoff;
5080+ uint linelen;
5081+
5082+ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5083+ {
5084+ return 0;
5085+ }
5086+
5087+ *phdrsoff = *ptcpoff;
5088+ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5089+ {
5090+ if (linelen == 0)
5091+ {
5092+ if (entitylen > 0)
5093+ {
5094+ *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5095+ }
5096+ break;
5097+ }
5098+ if (lineoff+linelen > tcplen)
5099+ {
5100+ INFOP("!! overrun !!\n");
5101+ break;
5102+ }
5103+
5104+ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5105+ {
5106+ *pcseqoff = lineoff;
5107+ *pcseqlen = linelen;
5108+ }
5109+ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5110+ {
5111+ uint off = lineoff+15;
5112+ SKIP_WSPACE(ptcp+lineoff, linelen, off);
5113+ nf_strtou32(ptcp+off, &entitylen);
5114+ }
5115+ }
5116+ *phdrslen = (*ptcpoff) - (*phdrsoff);
5117+
5118+ return 1;
5119+}
5120+
5121+/*
5122+ * Find lo/hi client ports (if any) in transport header
5123+ * In:
5124+ * ptcp, tcplen = packet
5125+ * tranoff, tranlen = buffer to search
5126+ *
5127+ * Out:
5128+ * pport_lo, pport_hi = lo/hi ports (host endian)
5129+ *
5130+ * Returns nonzero if any client ports found
5131+ *
5132+ * Note: it is valid (and expected) for the client to request multiple
5133+ * transports, so we need to parse the entire line.
5134+ */
5135+static int
5136+rtsp_parse_transport(char* ptran, uint tranlen,
5137+ struct ip_ct_rtsp_expect* prtspexp)
5138+{
5139+ int rc = 0;
5140+ uint off = 0;
5141+
5142+ if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5143+ nf_strncasecmp(ptran, "Transport:", 10) != 0)
5144+ {
5145+ INFOP("sanity check failed\n");
5146+ return 0;
5147+ }
5148+ DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5149+ off += 10;
5150+ SKIP_WSPACE(ptran, tranlen, off);
5151+
5152+ /* Transport: tran;field;field=val,tran;field;field=val,... */
5153+ while (off < tranlen)
5154+ {
5155+ const char* pparamend;
5156+ uint nextparamoff;
5157+
5158+ pparamend = memchr(ptran+off, ',', tranlen-off);
5159+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5160+ nextparamoff = pparamend-ptran;
5161+
5162+ while (off < nextparamoff)
5163+ {
5164+ const char* pfieldend;
5165+ uint nextfieldoff;
5166+
5167+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5168+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5169+
5170+ if (strncmp(ptran+off, "client_port=", 12) == 0)
5171+ {
5172+ u_int16_t port;
5173+ uint numlen;
5174+
5175+ off += 12;
5176+ numlen = nf_strtou16(ptran+off, &port);
5177+ off += numlen;
5178+ if (prtspexp->loport != 0 && prtspexp->loport != port)
5179+ {
5180+ DEBUGP("multiple ports found, port %hu ignored\n", port);
5181+ }
5182+ else
5183+ {
5184+ prtspexp->loport = prtspexp->hiport = port;
5185+ if (ptran[off] == '-')
5186+ {
5187+ off++;
5188+ numlen = nf_strtou16(ptran+off, &port);
5189+ off += numlen;
5190+ prtspexp->pbtype = pb_range;
5191+ prtspexp->hiport = port;
5192+
5193+ // If we have a range, assume rtp:
5194+ // loport must be even, hiport must be loport+1
5195+ if ((prtspexp->loport & 0x0001) != 0 ||
5196+ prtspexp->hiport != prtspexp->loport+1)
5197+ {
5198+ DEBUGP("incorrect range: %hu-%hu, correcting\n",
5199+ prtspexp->loport, prtspexp->hiport);
5200+ prtspexp->loport &= 0xfffe;
5201+ prtspexp->hiport = prtspexp->loport+1;
5202+ }
5203+ }
5204+ else if (ptran[off] == '/')
5205+ {
5206+ off++;
5207+ numlen = nf_strtou16(ptran+off, &port);
5208+ off += numlen;
5209+ prtspexp->pbtype = pb_discon;
5210+ prtspexp->hiport = port;
5211+ }
5212+ rc = 1;
5213+ }
5214+ }
5215+
5216+ /*
5217+ * Note we don't look for the destination parameter here.
5218+ * If we are using NAT, the NAT module will handle it. If not,
5219+ * and the client is sending packets elsewhere, the expectation
5220+ * will quietly time out.
5221+ */
5222+
5223+ off = nextfieldoff;
5224+ }
5225+
5226+ off = nextparamoff;
5227+ }
5228+
5229+ return rc;
5230+}
5231+
5232+/*** conntrack functions ***/
5233+
5234+/* outbound packet: client->server */
5235+static int
5236+help_out(const struct iphdr* iph, size_t pktlen,
5237+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5238+{
5239+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */
5240+ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5241+ uint tcplen = pktlen - iph->ihl * 4;
5242+ char* pdata = (char*)tcph + tcph->doff * 4;
5243+ uint datalen = tcplen - tcph->doff * 4;
5244+ uint dataoff = 0;
5245+
5246+ struct ip_conntrack_expect exp;
5247+
5248+ while (dataoff < datalen)
5249+ {
5250+ uint cmdoff = dataoff;
5251+ uint hdrsoff = 0;
5252+ uint hdrslen = 0;
5253+ uint cseqoff = 0;
5254+ uint cseqlen = 0;
5255+ uint lineoff = 0;
5256+ uint linelen = 0;
5257+ uint off;
5258+ int rc;
5259+
5260+ if (!rtsp_parse_message(pdata, datalen, &dataoff,
5261+ &hdrsoff, &hdrslen,
5262+ &cseqoff, &cseqlen))
5263+ {
5264+ break; /* not a valid message */
5265+ }
5266+
5267+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5268+ {
5269+ continue; /* not a SETUP message */
5270+ }
5271+ DEBUGP("found a setup message\n");
5272+
5273+ memset(&exp, 0, sizeof(exp));
5274+
5275+ off = 0;
5276+ while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5277+ &lineoff, &linelen))
5278+ {
5279+ if (linelen == 0)
5280+ {
5281+ break;
5282+ }
5283+ if (off > hdrsoff+hdrslen)
5284+ {
5285+ INFOP("!! overrun !!");
5286+ break;
5287+ }
5288+
5289+ if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5290+ {
5291+ rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5292+ &exp.help.exp_rtsp_info);
5293+ }
5294+ }
5295+
5296+ if (exp.help.exp_rtsp_info.loport == 0)
5297+ {
5298+ DEBUGP("no udp transports found\n");
5299+ continue; /* no udp transports found */
5300+ }
5301+
5302+ DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5303+ (int)exp.help.exp_rtsp_info.pbtype,
5304+ exp.help.exp_rtsp_info.loport,
5305+ exp.help.exp_rtsp_info.hiport);
5306+
5307+ LOCK_BH(&ip_rtsp_lock);
5308+ exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5309+ exp.help.exp_rtsp_info.len = hdrslen;
5310+
5311+ exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5312+ exp.mask.src.ip = 0xffffffff;
5313+ exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5314+ exp.mask.dst.ip = 0xffffffff;
5315+ exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5316+ exp.mask.dst.u.udp.port = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5317+ exp.tuple.dst.protonum = IPPROTO_UDP;
5318+ exp.mask.dst.protonum = 0xffff;
5319+
5320+ DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5321+ NIPQUAD(exp.tuple.src.ip),
5322+ ntohs(exp.tuple.src.u.tcp.port),
5323+ NIPQUAD(exp.tuple.dst.ip),
5324+ ntohs(exp.tuple.dst.u.tcp.port));
5325+
5326+ /* pass the request off to the nat helper */
5327+ rc = ip_conntrack_expect_related(ct, &exp);
5328+ UNLOCK_BH(&ip_rtsp_lock);
5329+ if (rc == 0)
5330+ {
5331+ DEBUGP("ip_conntrack_expect_related succeeded\n");
5332+ }
5333+ else
5334+ {
5335+ INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5336+ }
5337+ }
5338+
5339+ return NF_ACCEPT;
5340+}
5341+
5342+/* inbound packet: server->client */
5343+static int
5344+help_in(const struct iphdr* iph, size_t pktlen,
5345+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5346+{
5347+ return NF_ACCEPT;
5348+}
5349+
5350+static int
5351+help(const struct iphdr* iph, size_t pktlen,
5352+ struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5353+{
5354+ /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5355+ struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5356+ u_int32_t tcplen = pktlen - iph->ihl * 4;
5357+
5358+ /* Until there's been traffic both ways, don't look in packets. */
5359+ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5360+ {
5361+ DEBUGP("conntrackinfo = %u\n", ctinfo);
5362+ return NF_ACCEPT;
5363+ }
5364+
5365+ /* Not whole TCP header? */
5366+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5367+ {
5368+ DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5369+ return NF_ACCEPT;
5370+ }
5371+
5372+ /* Checksum invalid? Ignore. */
5373+ /* FIXME: Source route IP option packets --RR */
5374+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5375+ csum_partial((char*)tcph, tcplen, 0)))
5376+ {
5377+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5378+ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5379+ return NF_ACCEPT;
5380+ }
5381+
5382+ switch (CTINFO2DIR(ctinfo))
5383+ {
5384+ case IP_CT_DIR_ORIGINAL:
5385+ help_out(iph, pktlen, ct, ctinfo);
5386+ break;
5387+ case IP_CT_DIR_REPLY:
5388+ help_in(iph, pktlen, ct, ctinfo);
5389+ break;
5390+ }
5391+
5392+ return NF_ACCEPT;
5393+}
5394+
5395+static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5396+static char rtsp_names[MAX_PORTS][10];
5397+
5398+/* This function is intentionally _NOT_ defined as __exit */
5399+static void
5400+fini(void)
5401+{
5402+ int i;
5403+ for (i = 0; i < num_ports; i++)
5404+ {
5405+ DEBUGP("unregistering port %d\n", ports[i]);
5406+ ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5407+ }
5408+}
5409+
5410+static int __init
5411+init(void)
5412+{
5413+ int i, ret;
5414+ struct ip_conntrack_helper *hlpr;
5415+ char *tmpname;
5416+
5417+ printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5418+
5419+ if (max_outstanding < 1)
5420+ {
5421+ printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5422+ return -EBUSY;
5423+ }
5424+ if (setup_timeout < 0)
5425+ {
5426+ printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5427+ return -EBUSY;
5428+ }
5429+
5430+ /* If no port given, default to standard rtsp port */
5431+ if (ports[0] == 0)
5432+ {
5433+ ports[0] = RTSP_PORT;
5434+ }
5435+
5436+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5437+ {
5438+ hlpr = &rtsp_helpers[i];
5439+ memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5440+ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5441+ hlpr->tuple.dst.protonum = IPPROTO_TCP;
5442+ hlpr->mask.src.u.tcp.port = 0xFFFF;
5443+ hlpr->mask.dst.protonum = 0xFFFF;
5444+ hlpr->max_expected = max_outstanding;
5445+ hlpr->timeout = setup_timeout;
5446+ hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5447+ hlpr->me = ip_conntrack_rtsp;
5448+ hlpr->help = help;
5449+
5450+ tmpname = &rtsp_names[i][0];
5451+ if (ports[i] == RTSP_PORT)
5452+ {
5453+ sprintf(tmpname, "rtsp");
5454+ }
5455+ else
5456+ {
5457+ sprintf(tmpname, "rtsp-%d", i);
5458+ }
5459+ hlpr->name = tmpname;
5460+
5461+ DEBUGP("port #%d: %d\n", i, ports[i]);
5462+
5463+ ret = ip_conntrack_helper_register(hlpr);
5464+
5465+ if (ret)
5466+ {
5467+ printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5468+ fini();
5469+ return -EBUSY;
5470+ }
5471+ num_ports++;
5472+ }
5473+ return 0;
5474+}
5475+
5476+#ifdef CONFIG_IP_NF_NAT_NEEDED
5477+EXPORT_SYMBOL(ip_rtsp_lock);
5478+#endif
5479+
5480+module_init(init);
5481+module_exit(fini);
5482diff -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
5483--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-28 03:35:45.000000000 +0200
5484+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-29 11:18:04.000000000 +0200
5485@@ -110,6 +110,9 @@
5486 len += sprintf(buffer + len, "[ASSURED] ");
5487 len += sprintf(buffer + len, "use=%u ",
5488 atomic_read(&conntrack->ct_general.use));
5489+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5490+ len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5491+#endif
5492 len += sprintf(buffer + len, "\n");
5493
5494 return len;
5495@@ -633,6 +636,7 @@
5496 EXPORT_SYMBOL(ip_conntrack_alter_reply);
5497 EXPORT_SYMBOL(ip_conntrack_destroyed);
5498 EXPORT_SYMBOL(ip_conntrack_get);
5499+EXPORT_SYMBOL(__ip_conntrack_confirm);
5500 EXPORT_SYMBOL(need_ip_conntrack);
5501 EXPORT_SYMBOL(ip_conntrack_helper_register);
5502 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5503diff -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
5504--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c 1970-01-01 01:00:00.000000000 +0100
5505+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c 2004-04-29 11:21:43.000000000 +0200
5506@@ -0,0 +1,360 @@
5507+/*
5508+ * talk extension for IP connection tracking.
5509+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5510+ *
5511+ * This program is free software; you can redistribute it and/or
5512+ * modify it under the terms of the GNU General Public License
5513+ * as published by the Free Software Foundation; either version
5514+ * 2 of the License, or (at your option) any later version.
5515+ **
5516+ * Module load syntax:
5517+ * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5518+ *
5519+ * talk=[0|1] disable|enable old talk support
5520+ * ntalk=[0|1] disable|enable ntalk support
5521+ * ntalk2=[0|1] disable|enable ntalk2 support
5522+ *
5523+ * The default is talk=1 ntalk=1 ntalk2=1
5524+ *
5525+ * The helper does not support simultaneous talk requests.
5526+ **
5527+ *
5528+ * ASCII art on talk protocols
5529+ *
5530+ *
5531+ * caller server callee server
5532+ * | \ /
5533+ * | \ /
5534+ * | \ /
5535+ * | /
5536+ * | / \
5537+ * 2 | 1 / \ 3
5538+ * caller client ----------- callee client
5539+ * 4
5540+ *
5541+ * 1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation
5542+ * ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5543+ * 3. callee client <-> caller server: LOOK_UP invitation
5544+ * 4. callee client <-> caller client: talk data channel
5545+ *
5546+ * [1]: M. Hunter, talk: a historical protocol for interactive communication
5547+ * draft-hunter-talk-00.txt
5548+ * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)
5549+ */
5550+#include <linux/config.h>
5551+#include <linux/module.h>
5552+#include <linux/netfilter.h>
5553+#include <linux/ip.h>
5554+#include <net/checksum.h>
5555+#include <net/udp.h>
5556+
5557+#include <linux/netfilter_ipv4/lockhelp.h>
5558+#include <linux/netfilter_ipv4/ip_conntrack.h>
5559+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5560+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5561+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5562+
5563+/* Default all talk protocols are supported */
5564+static int talk = 1;
5565+static int ntalk = 1;
5566+static int ntalk2 = 1;
5567+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5568+MODULE_DESCRIPTION("talk connection tracking module");
5569+MODULE_LICENSE("GPL");
5570+#ifdef MODULE_PARM
5571+MODULE_PARM(talk, "i");
5572+MODULE_PARM_DESC(talk, "support (old) talk protocol");
5573+MODULE_PARM(ntalk, "i");
5574+MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5575+MODULE_PARM(ntalk2, "i");
5576+MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5577+#endif
5578+
5579+DECLARE_LOCK(ip_talk_lock);
5580+struct module *ip_conntrack_talk = THIS_MODULE;
5581+
5582+#if 0
5583+#define DEBUGP printk
5584+#else
5585+#define DEBUGP(format, args...)
5586+#endif
5587+
5588+static int talk_expect(struct ip_conntrack *ct);
5589+static int ntalk_expect(struct ip_conntrack *ct);
5590+
5591+static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
5592+
5593+static int talk_help_response(const struct iphdr *iph, size_t len,
5594+ struct ip_conntrack *ct,
5595+ enum ip_conntrack_info ctinfo,
5596+ int talk_port,
5597+ u_char mode,
5598+ u_char type,
5599+ u_char answer,
5600+ struct talk_addr *addr)
5601+{
5602+ int dir = CTINFO2DIR(ctinfo);
5603+ struct ip_conntrack_expect expect, *exp = &expect;
5604+ struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
5605+
5606+ DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
5607+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5608+ type, answer);
5609+
5610+ if (!(answer == SUCCESS && type == mode))
5611+ return NF_ACCEPT;
5612+
5613+ memset(&expect, 0, sizeof(expect));
5614+
5615+ if (type == ANNOUNCE) {
5616+
5617+ DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
5618+
5619+ /* update the talk info */
5620+ LOCK_BH(&ip_talk_lock);
5621+ exp_talk_info->port = htons(talk_port);
5622+
5623+ /* expect callee client -> caller server message */
5624+ exp->tuple = ((struct ip_conntrack_tuple)
5625+ { { ct->tuplehash[dir].tuple.src.ip,
5626+ { 0 } },
5627+ { ct->tuplehash[dir].tuple.dst.ip,
5628+ { .tcp = { htons(talk_port) } },
5629+ IPPROTO_UDP }});
5630+ exp->mask = ((struct ip_conntrack_tuple)
5631+ { { 0xFFFFFFFF, { 0 } },
5632+ { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
5633+
5634+ exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
5635+
5636+ DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
5637+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
5638+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
5639+
5640+ /* Ignore failure; should only happen with NAT */
5641+ ip_conntrack_expect_related(ct, &expect);
5642+ UNLOCK_BH(&ip_talk_lock);
5643+ }
5644+ if (type == LOOK_UP) {
5645+
5646+ DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
5647+
5648+ /* update the talk info */
5649+ LOCK_BH(&ip_talk_lock);
5650+ exp_talk_info->port = addr->ta_port;
5651+
5652+ /* expect callee client -> caller client connection */
5653+ exp->tuple = ((struct ip_conntrack_tuple)
5654+ { { ct->tuplehash[!dir].tuple.src.ip,
5655+ { 0 } },
5656+ { addr->ta_addr,
5657+ { addr->ta_port },
5658+ IPPROTO_TCP }});
5659+ exp->mask = ((struct ip_conntrack_tuple)
5660+ { { 0xFFFFFFFF, { 0 } },
5661+ { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5662+
5663+ exp->expectfn = NULL;
5664+
5665+ DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
5666+ NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
5667+ NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
5668+
5669+ /* Ignore failure; should only happen with NAT */
5670+ ip_conntrack_expect_related(ct, &expect);
5671+ UNLOCK_BH(&ip_talk_lock);
5672+ }
5673+
5674+ return NF_ACCEPT;
5675+}
5676+
5677+/* FIXME: This should be in userspace. Later. */
5678+static int talk_help(const struct iphdr *iph, size_t len,
5679+ struct ip_conntrack *ct,
5680+ enum ip_conntrack_info ctinfo,
5681+ int talk_port,
5682+ u_char mode)
5683+{
5684+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
5685+ const char *data = (const char *)udph + sizeof(struct udphdr);
5686+ int dir = CTINFO2DIR(ctinfo);
5687+ size_t udplen;
5688+
5689+ DEBUGP("ip_ct_talk_help: help entered\n");
5690+
5691+ /* Until there's been traffic both ways, don't look in packets. */
5692+ if (ctinfo != IP_CT_ESTABLISHED
5693+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5694+ DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
5695+ return NF_ACCEPT;
5696+ }
5697+
5698+ /* Not whole UDP header? */
5699+ udplen = len - iph->ihl * 4;
5700+ if (udplen < sizeof(struct udphdr)) {
5701+ DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
5702+ return NF_ACCEPT;
5703+ }
5704+
5705+ /* Checksum invalid? Ignore. */
5706+ /* FIXME: Source route IP option packets --RR */
5707+ if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5708+ csum_partial((char *)udph, udplen, 0))) {
5709+ DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5710+ udph, udplen, NIPQUAD(iph->saddr),
5711+ NIPQUAD(iph->daddr));
5712+ return NF_ACCEPT;
5713+ }
5714+
5715+ DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5716+ NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
5717+
5718+ if (dir == IP_CT_DIR_ORIGINAL)
5719+ return NF_ACCEPT;
5720+
5721+ if (talk_port == TALK_PORT
5722+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
5723+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5724+ ((struct talk_response *)data)->type,
5725+ ((struct talk_response *)data)->answer,
5726+ &(((struct talk_response *)data)->addr));
5727+ else if (talk_port == NTALK_PORT
5728+ && ntalk
5729+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5730+ && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5731+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5732+ ((struct ntalk_response *)data)->type,
5733+ ((struct ntalk_response *)data)->answer,
5734+ &(((struct ntalk_response *)data)->addr));
5735+ else if (talk_port == NTALK_PORT
5736+ && ntalk2
5737+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5738+ && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5739+ return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5740+ ((struct ntalk2_response *)data)->type,
5741+ ((struct ntalk2_response *)data)->answer,
5742+ &(((struct ntalk2_response *)data)->addr));
5743+ else {
5744+ DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
5745+ (unsigned)udplen - sizeof(struct udphdr),
5746+ sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5747+ return NF_ACCEPT;
5748+ }
5749+}
5750+
5751+static int lookup_help(const struct iphdr *iph, size_t len,
5752+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5753+{
5754+ return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5755+}
5756+
5757+static int lookup_nhelp(const struct iphdr *iph, size_t len,
5758+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5759+{
5760+ return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5761+}
5762+
5763+static struct ip_conntrack_helper lookup_helpers[2] =
5764+ { { { NULL, NULL },
5765+ "talk", /* name */
5766+ 0, /* flags */
5767+ NULL, /* module */
5768+ 1, /* max_expected */
5769+ 240, /* timeout */
5770+ { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5771+ { 0, { 0 }, IPPROTO_UDP } },
5772+ { { 0, { 0xFFFF } }, /* mask */
5773+ { 0, { 0 }, 0xFFFF } },
5774+ lookup_help }, /* helper */
5775+ { { NULL, NULL },
5776+ "ntalk", /* name */
5777+ 0, /* flags */
5778+ NULL, /* module */
5779+ 1, /* max_expected */
5780+ 240, /* timeout */
5781+ { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5782+ { 0, { 0 }, IPPROTO_UDP } },
5783+ { { 0, { 0xFFFF } }, /* mask */
5784+ { 0, { 0 }, 0xFFFF } },
5785+ lookup_nhelp } /* helper */
5786+ };
5787+
5788+static int talk_expect(struct ip_conntrack *ct)
5789+{
5790+ DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5791+ WRITE_LOCK(&ip_conntrack_lock);
5792+ ct->helper = &lookup_helpers[0];
5793+ WRITE_UNLOCK(&ip_conntrack_lock);
5794+
5795+ return NF_ACCEPT; /* unused */
5796+}
5797+
5798+static int ntalk_expect(struct ip_conntrack *ct)
5799+{
5800+ DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5801+ WRITE_LOCK(&ip_conntrack_lock);
5802+ ct->helper = &lookup_helpers[1];
5803+ WRITE_UNLOCK(&ip_conntrack_lock);
5804+
5805+ return NF_ACCEPT; /* unused */
5806+}
5807+
5808+static int help(const struct iphdr *iph, size_t len,
5809+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5810+{
5811+ return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5812+}
5813+
5814+static int nhelp(const struct iphdr *iph, size_t len,
5815+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5816+{
5817+ return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5818+}
5819+
5820+static struct ip_conntrack_helper talk_helpers[2] =
5821+ { { { NULL, NULL },
5822+ "talk", /* name */
5823+ 0, /* flags */
5824+ THIS_MODULE, /* module */
5825+ 1, /* max_expected */
5826+ 240, /* timeout */
5827+ { { 0, { __constant_htons(TALK_PORT) } }, /* tuple */
5828+ { 0, { 0 }, IPPROTO_UDP } },
5829+ { { 0, { 0xFFFF } }, /* mask */
5830+ { 0, { 0 }, 0xFFFF } },
5831+ help }, /* helper */
5832+ { { NULL, NULL },
5833+ "ntalk", /* name */
5834+ 0, /* flags */
5835+ THIS_MODULE, /* module */
5836+ 1, /* max_expected */
5837+ 240, /* timeout */
5838+ { { 0, { __constant_htons(NTALK_PORT) } }, /* tuple */
5839+ { 0, { 0 }, IPPROTO_UDP } },
5840+ { { 0, { 0xFFFF } }, /* mask */
5841+ { 0, { 0 }, 0xFFFF } },
5842+ nhelp } /* helper */
5843+ };
5844+
5845+static int __init init(void)
5846+{
5847+ if (talk > 0)
5848+ ip_conntrack_helper_register(&talk_helpers[0]);
5849+ if (ntalk > 0 || ntalk2 > 0)
5850+ ip_conntrack_helper_register(&talk_helpers[1]);
5851+
5852+ return 0;
5853+}
5854+
5855+static void __exit fini(void)
5856+{
5857+ if (talk > 0)
5858+ ip_conntrack_helper_unregister(&talk_helpers[0]);
5859+ if (ntalk > 0 || ntalk2 > 0)
5860+ ip_conntrack_helper_unregister(&talk_helpers[1]);
5861+}
5862+
5863+EXPORT_SYMBOL(ip_talk_lock);
5864+
5865+module_init(init);
5866+module_exit(fini);
5867diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c
5868--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c 1970-01-01 01:00:00.000000000 +0100
5869+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c 2004-04-29 11:17:55.000000000 +0200
5870@@ -0,0 +1,289 @@
5871+/* CuSeeMe extension for UDP NAT alteration.
5872+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5873+ * based on ip_masq_cuseeme.c in 2.2 kernels
5874+ *
5875+ * ip_nat_cuseeme.c v0.0.7 2003-02-18
5876+ *
5877+ * This program is free software; you can redistribute it and/or
5878+ * modify it under the terms of the GNU General Public License
5879+ * as published by the Free Software Foundation; either version
5880+ * 2 of the License, or (at your option) any later version.
5881+ *
5882+ * Module load syntax:
5883+ * insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
5884+ *
5885+ * Please give the ports of the CuSeeMe traffic you want to track.
5886+ * If you don't specify ports, the default will be UDP port 7648.
5887+ *
5888+ * CuSeeMe Protocol Documentation:
5889+ * http://cu-seeme.net/squeek/tech/contents.html
5890+ *
5891+ */
5892+
5893+#include <linux/module.h>
5894+#include <linux/netfilter_ipv4.h>
5895+#include <linux/ip.h>
5896+#include <linux/udp.h>
5897+
5898+#include <linux/netfilter.h>
5899+#include <linux/netfilter_ipv4/ip_tables.h>
5900+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5901+#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
5902+#include <linux/netfilter_ipv4/ip_nat_helper.h>
5903+#include <linux/netfilter_ipv4/ip_nat_rule.h>
5904+
5905+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5906+MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
5907+MODULE_LICENSE("GPL");
5908+
5909+#define MAX_PORTS 8
5910+
5911+static int ports[MAX_PORTS];
5912+static int ports_c = 0;
5913+#ifdef MODULE_PARM
5914+MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
5915+MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
5916+#endif
5917+
5918+#if 0
5919+#define DEBUGP printk
5920+#else
5921+#define DEBUGP(format, args...)
5922+#endif
5923+
5924+/* process packet from client->reflector, possibly manipulate client IP in payload */
5925+void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
5926+ struct ip_nat_info *info,
5927+ enum ip_conntrack_info ctinfo,
5928+ struct sk_buff **pskb,
5929+ char *data,
5930+ unsigned int datalen)
5931+{
5932+ char new_port_ip[6];
5933+ struct cu_header *cu_head=(struct cu_header *)data;
5934+
5935+ DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n",
5936+ ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5937+
5938+ /* At least check that the data at offset 10 is the client's port and IP address */
5939+ if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
5940+ (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
5941+ DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
5942+ NIPQUAD(cu_head->addr),
5943+ ntohs(cu_head->port),
5944+ NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5945+ ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
5946+ *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
5947+ *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5948+ /* at offset 10, replace 6 bytes containing port + IP address */
5949+ ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5950+ 10, 6, (char *)(new_port_ip), 6);
5951+ } else
5952+ DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5953+ NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5954+ ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
5955+ NIPQUAD(cu_head->addr),
5956+ ntohs(cu_head->port));
5957+}
5958+
5959+/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
5960+void cuseeme_mangle_incoming(struct ip_conntrack *ct,
5961+ struct ip_nat_info *info,
5962+ enum ip_conntrack_info ctinfo,
5963+ struct sk_buff **pskb,
5964+ char *data,
5965+ unsigned int datalen)
5966+{
5967+ char new_port_ip[6];
5968+ struct cu_header *cu_head = (struct cu_header *)data;
5969+ struct oc_header *oc_head = (struct oc_header *)data;
5970+ struct client_info *ci;
5971+ int i, off;
5972+
5973+
5974+ DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n",
5975+ ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5976+
5977+ /* Check if we're really dealing with the client's port + IP address before rewriting */
5978+ if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
5979+ (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
5980+ DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
5981+ NIPQUAD(cu_head->dest_addr),
5982+ ntohs(cu_head->dest_port),
5983+ NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5984+ ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
5985+ *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
5986+ *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5987+ /* at offset 2, replace 6 bytes containing port + IP address */
5988+ ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5989+ 2, 6, (char *)(new_port_ip), 6);
5990+ } else
5991+ DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5992+ NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5993+ ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
5994+ NIPQUAD(cu_head->dest_addr),
5995+ ntohs(cu_head->dest_port));
5996+
5997+ /* Check if we're really dealing with the server's port + IP address before rewriting.
5998+ In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
5999+ if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
6000+ (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
6001+ DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
6002+ NIPQUAD(cu_head->addr),
6003+ ntohs(cu_head->port),
6004+ NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
6005+ ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
6006+ *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
6007+ *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6008+ /* at offset 10, replace 6 bytes containing port + IP address */
6009+ ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
6010+ 10, 6, (char *)(new_port_ip), 6);
6011+ } else
6012+ /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
6013+ is not that important so we're not logging this unless we're debugging */
6014+ DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
6015+ NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
6016+ ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
6017+ NIPQUAD(cu_head->addr),
6018+ ntohs(cu_head->port));
6019+
6020+ /* Spin through client_info structs until we find our own */
6021+ if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
6022+ DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
6023+ for(i=0, off=sizeof(struct oc_header);
6024+ (i < oc_head->client_count &&
6025+ off+sizeof(struct client_info) <= datalen);
6026+ i++) {
6027+ ci=(struct client_info *)(data+off);
6028+ DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n",
6029+ NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
6030+ (unsigned int)((void *)&(ci->address) - (void *)cu_head));
6031+ if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
6032+ /* mangle this IP address */
6033+ DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
6034+ NIPQUAD(ci->address),
6035+ NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
6036+ (unsigned int)((void *)&(ci->address) - (void *)cu_head));
6037+ ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
6038+ (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4,
6039+ (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
6040+ break;
6041+ } else
6042+ off+=sizeof(struct client_info);
6043+ }
6044+ } else
6045+ DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n",
6046+ ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
6047+}
6048+
6049+static unsigned int
6050+cuseeme_nat_help(struct ip_conntrack *ct,
6051+ struct ip_conntrack_expect *exp,
6052+ struct ip_nat_info *info,
6053+ enum ip_conntrack_info ctinfo,
6054+ unsigned int hooknum,
6055+ struct sk_buff **pskb)
6056+{
6057+ struct iphdr *iph = (*pskb)->nh.iph;
6058+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
6059+ int dir = CTINFO2DIR(ctinfo);
6060+ unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
6061+ char *data = (char *) &udph[1];
6062+
6063+ DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
6064+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6065+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6066+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6067+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6068+ );
6069+
6070+ /* Only mangle things once: original direction in POST_ROUTING
6071+ and reply direction on PRE_ROUTING. */
6072+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6073+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6074+ DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
6075+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6076+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6077+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6078+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6079+ return NF_ACCEPT;
6080+ }
6081+
6082+ if(datalen < sizeof(struct cu_header)) {
6083+ /* packet too small */
6084+ if (net_ratelimit())
6085+ printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n",
6086+ datalen, sizeof(struct cu_header));
6087+ return NF_ACCEPT;
6088+ }
6089+
6090+
6091+ /* In the debugging output, "outgoing" is from client to server, and
6092+ "incoming" is from server to client */
6093+ if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6094+ cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
6095+ else
6096+ cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
6097+
6098+ return NF_ACCEPT;
6099+}
6100+
6101+static struct ip_nat_helper cuseeme[MAX_PORTS];
6102+static char cuseeme_names[MAX_PORTS][14]; /* cuseeme-65535 */
6103+
6104+static void fini(void)
6105+{
6106+ int i;
6107+
6108+ for (i = 0 ; i < ports_c; i++) {
6109+ DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
6110+ ip_nat_helper_unregister(&cuseeme[i]);
6111+ }
6112+}
6113+
6114+static int __init init(void)
6115+{
6116+ int i, ret = 0;
6117+ char *tmpname;
6118+
6119+ if (!ports[0])
6120+ ports[0] = CUSEEME_PORT;
6121+
6122+ for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6123+ memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
6124+
6125+ cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
6126+ cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
6127+ cuseeme[i].mask.dst.protonum = 0xFFFF;
6128+ cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
6129+ cuseeme[i].help = cuseeme_nat_help;
6130+ cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE +
6131+ IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
6132+ is stricly needed... */
6133+ cuseeme[i].me = THIS_MODULE;
6134+ cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
6135+
6136+ tmpname = &cuseeme_names[i][0];
6137+ if (ports[i] == CUSEEME_PORT)
6138+ sprintf(tmpname, "cuseeme");
6139+ else
6140+ sprintf(tmpname, "cuseeme-%d", ports[i]);
6141+ cuseeme[i].name = tmpname;
6142+
6143+ DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
6144+ ports[i], cuseeme[i].name);
6145+ ret = ip_nat_helper_register(&cuseeme[i]);
6146+
6147+ if (ret) {
6148+ printk("ip_nat_cuseeme: unable to register helper for port %d\n",
6149+ ports[i]);
6150+ fini();
6151+ return ret;
6152+ }
6153+ ports_c++;
6154+ }
6155+ return ret;
6156+}
6157+
6158+module_init(init);
6159+module_exit(fini);
6160diff -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
6161--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c 1970-01-01 01:00:00.000000000 +0100
6162+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c 2004-04-29 11:18:00.000000000 +0200
6163@@ -0,0 +1,419 @@
6164+/*
6165+ * H.323 'brute force' extension for NAT alteration.
6166+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6167+ *
6168+ * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6169+ * (http://www.coritel.it/projects/sofia/nat.html)
6170+ * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6171+ * the unregistered helpers to the conntrack entries.
6172+ */
6173+
6174+
6175+#include <linux/module.h>
6176+#include <linux/netfilter.h>
6177+#include <linux/ip.h>
6178+#include <net/checksum.h>
6179+#include <net/tcp.h>
6180+
6181+#include <linux/netfilter_ipv4/lockhelp.h>
6182+#include <linux/netfilter_ipv4/ip_nat.h>
6183+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6184+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6185+#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6186+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6187+#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6188+
6189+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6190+MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6191+MODULE_LICENSE("GPL");
6192+
6193+DECLARE_LOCK_EXTERN(ip_h323_lock);
6194+struct module *ip_nat_h323 = THIS_MODULE;
6195+
6196+#if 0
6197+#define DEBUGP printk
6198+#else
6199+#define DEBUGP(format, args...)
6200+#endif
6201+
6202+/* FIXME: Time out? --RR */
6203+
6204+static unsigned int
6205+h225_nat_expected(struct sk_buff **pskb,
6206+ unsigned int hooknum,
6207+ struct ip_conntrack *ct,
6208+ struct ip_nat_info *info);
6209+
6210+static unsigned int h225_nat_help(struct ip_conntrack *ct,
6211+ struct ip_conntrack_expect *exp,
6212+ struct ip_nat_info *info,
6213+ enum ip_conntrack_info ctinfo,
6214+ unsigned int hooknum,
6215+ struct sk_buff **pskb);
6216+
6217+static struct ip_nat_helper h245 =
6218+ { { NULL, NULL },
6219+ "H.245", /* name */
6220+ 0, /* flags */
6221+ NULL, /* module */
6222+ { { 0, { 0 } }, /* tuple */
6223+ { 0, { 0 }, IPPROTO_TCP } },
6224+ { { 0, { 0xFFFF } }, /* mask */
6225+ { 0, { 0 }, 0xFFFF } },
6226+ h225_nat_help, /* helper */
6227+ h225_nat_expected /* expectfn */
6228+ };
6229+
6230+static unsigned int
6231+h225_nat_expected(struct sk_buff **pskb,
6232+ unsigned int hooknum,
6233+ struct ip_conntrack *ct,
6234+ struct ip_nat_info *info)
6235+{
6236+ struct ip_nat_multi_range mr;
6237+ u_int32_t newdstip, newsrcip, newip;
6238+ u_int16_t port;
6239+ struct ip_ct_h225_expect *exp_info;
6240+ struct ip_ct_h225_master *master_info;
6241+ struct ip_conntrack *master = master_ct(ct);
6242+ unsigned int is_h225, ret;
6243+
6244+ IP_NF_ASSERT(info);
6245+ IP_NF_ASSERT(master);
6246+
6247+ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6248+
6249+ DEBUGP("h225_nat_expected: We have a connection!\n");
6250+ master_info = &ct->master->expectant->help.ct_h225_info;
6251+ exp_info = &ct->master->help.exp_h225_info;
6252+
6253+ LOCK_BH(&ip_h323_lock);
6254+
6255+ DEBUGP("master: ");
6256+ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6257+ DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6258+ DEBUGP("conntrack: ");
6259+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6260+ if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6261+ /* Make connection go to the client. */
6262+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6263+ newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6264+ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6265+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
6266+ } else {
6267+ /* Make the connection go to the server */
6268+ newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6269+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6270+ DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6271+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
6272+ }
6273+ port = exp_info->port;
6274+ is_h225 = master_info->is_h225 == H225_PORT;
6275+ UNLOCK_BH(&ip_h323_lock);
6276+
6277+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6278+ newip = newsrcip;
6279+ else
6280+ newip = newdstip;
6281+
6282+ DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6283+
6284+ mr.rangesize = 1;
6285+ /* We don't want to manip the per-protocol, just the IPs... */
6286+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6287+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
6288+
6289+ /* ... unless we're doing a MANIP_DST, in which case, make
6290+ sure we map to the correct port */
6291+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6292+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6293+ mr.range[0].min = mr.range[0].max
6294+ = ((union ip_conntrack_manip_proto)
6295+ { .tcp = { port } });
6296+ }
6297+
6298+ ret = ip_nat_setup_info(ct, &mr, hooknum);
6299+
6300+ if (is_h225) {
6301+ DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6302+ /* NAT expectfn called with ip_nat_lock write-locked */
6303+ info->helper = &h245;
6304+ }
6305+ return ret;
6306+}
6307+
6308+static int h323_signal_address_fixup(struct ip_conntrack *ct,
6309+ struct sk_buff **pskb,
6310+ enum ip_conntrack_info ctinfo)
6311+{
6312+ struct iphdr *iph = (*pskb)->nh.iph;
6313+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6314+ char *data = (char *) tcph + tcph->doff * 4;
6315+ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6316+ u_int32_t datalen = tcplen - tcph->doff*4;
6317+ struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6318+ u_int32_t newip;
6319+ u_int16_t port;
6320+ int i;
6321+
6322+ MUST_BE_LOCKED(&ip_h323_lock);
6323+
6324+ DEBUGP("h323_signal_address_fixup: %s %s\n",
6325+ between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6326+ ? "yes" : "no",
6327+ between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6328+ ? "yes" : "no");
6329+ if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6330+ || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6331+ return 1;
6332+
6333+ DEBUGP("h323_signal_address_fixup: offsets %u + 6 and %u + 6 in %u\n",
6334+ info->offset[IP_CT_DIR_ORIGINAL],
6335+ info->offset[IP_CT_DIR_REPLY],
6336+ tcplen);
6337+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6338+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6339+
6340+ for (i = 0; i < IP_CT_DIR_MAX; i++) {
6341+ DEBUGP("h323_signal_address_fixup: %s %s\n",
6342+ info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6343+ i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6344+ if (!between(info->seq[i], ntohl(tcph->seq),
6345+ ntohl(tcph->seq) + datalen))
6346+ continue;
6347+ if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6348+ ntohl(tcph->seq) + datalen)) {
6349+ /* Partial retransmisison. It's a cracker being funky. */
6350+ if (net_ratelimit()) {
6351+ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6352+ info->seq[i],
6353+ ntohl(tcph->seq),
6354+ ntohl(tcph->seq) + datalen);
6355+ }
6356+ return 0;
6357+ }
6358+
6359+ /* Change address inside packet to match way we're mapping
6360+ this connection. */
6361+ if (i == IP_CT_DIR_ORIGINAL) {
6362+ newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6363+ port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6364+ } else {
6365+ newip = ct->tuplehash[!info->dir].tuple.src.ip;
6366+ port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6367+ }
6368+
6369+ DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n",
6370+ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6371+ NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6372+ ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6373+
6374+ /* Modify the packet */
6375+ *(u_int32_t *)(data + info->offset[i]) = newip;
6376+ *(u_int16_t *)(data + info->offset[i] + 4) = port;
6377+
6378+ DEBUGP("h323_signal_address_fixup: new %s IP:port %u.%u.%u.%u:%u\n",
6379+ i == IP_CT_DIR_ORIGINAL ? "source" : "dest ",
6380+ NIPQUAD(*((u_int32_t *)(data + info->offset[i]))),
6381+ ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6382+ }
6383+
6384+ /* fix checksum information */
6385+
6386+ (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6387+ datalen, 0);
6388+
6389+ tcph->check = 0;
6390+ tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6391+ csum_partial((char *)tcph, tcph->doff*4,
6392+ (*pskb)->csum));
6393+ ip_send_check(iph);
6394+
6395+ return 1;
6396+}
6397+
6398+static int h323_data_fixup(struct ip_ct_h225_expect *info,
6399+ struct ip_conntrack *ct,
6400+ struct sk_buff **pskb,
6401+ enum ip_conntrack_info ctinfo,
6402+ struct ip_conntrack_expect *expect)
6403+{
6404+ u_int32_t newip;
6405+ u_int16_t port;
6406+ struct ip_conntrack_tuple newtuple;
6407+ struct iphdr *iph = (*pskb)->nh.iph;
6408+ struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6409+ char *data = (char *) tcph + tcph->doff * 4;
6410+ u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6411+ struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6412+ int is_h225;
6413+
6414+ MUST_BE_LOCKED(&ip_h323_lock);
6415+ DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6416+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6417+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6418+
6419+ if (!between(expect->seq + 6, ntohl(tcph->seq),
6420+ ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6421+ /* Partial retransmisison. It's a cracker being funky. */
6422+ if (net_ratelimit()) {
6423+ printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6424+ expect->seq,
6425+ ntohl(tcph->seq),
6426+ ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6427+ }
6428+ return 0;
6429+ }
6430+
6431+ /* Change address inside packet to match way we're mapping
6432+ this connection. */
6433+ if (info->dir == IP_CT_DIR_REPLY) {
6434+ /* Must be where client thinks server is */
6435+ newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6436+ /* Expect something from client->server */
6437+ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6438+ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6439+ } else {
6440+ /* Must be where server thinks client is */
6441+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6442+ /* Expect something from server->client */
6443+ newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6444+ newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6445+ }
6446+
6447+ is_h225 = (master_info->is_h225 == H225_PORT);
6448+
6449+ if (is_h225) {
6450+ newtuple.dst.protonum = IPPROTO_TCP;
6451+ newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6452+ } else {
6453+ newtuple.dst.protonum = IPPROTO_UDP;
6454+ newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6455+ }
6456+
6457+ /* Try to get same port: if not, try to change it. */
6458+ for (port = ntohs(info->port); port != 0; port++) {
6459+ if (is_h225)
6460+ newtuple.dst.u.tcp.port = htons(port);
6461+ else
6462+ newtuple.dst.u.udp.port = htons(port);
6463+
6464+ if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6465+ break;
6466+ }
6467+ if (port == 0) {
6468+ DEBUGP("h323_data_fixup: no free port found!\n");
6469+ return 0;
6470+ }
6471+
6472+ port = htons(port);
6473+
6474+ DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n",
6475+ NIPQUAD(*((u_int32_t *)(data + info->offset))),
6476+ ntohs(*((u_int16_t *)(data + info->offset + 4))));
6477+
6478+ /* Modify the packet */
6479+ *(u_int32_t *)(data + info->offset) = newip;
6480+ *(u_int16_t *)(data + info->offset + 4) = port;
6481+
6482+ DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n",
6483+ NIPQUAD(*((u_int32_t *)(data + info->offset))),
6484+ ntohs(*((u_int16_t *)(data + info->offset + 4))));
6485+
6486+ /* fix checksum information */
6487+ /* FIXME: usually repeated multiple times in the case of H.245! */
6488+
6489+ (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6490+ tcplen - tcph->doff*4, 0);
6491+
6492+ tcph->check = 0;
6493+ tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6494+ csum_partial((char *)tcph, tcph->doff*4,
6495+ (*pskb)->csum));
6496+ ip_send_check(iph);
6497+
6498+ return 1;
6499+}
6500+
6501+static unsigned int h225_nat_help(struct ip_conntrack *ct,
6502+ struct ip_conntrack_expect *exp,
6503+ struct ip_nat_info *info,
6504+ enum ip_conntrack_info ctinfo,
6505+ unsigned int hooknum,
6506+ struct sk_buff **pskb)
6507+{
6508+ int dir;
6509+ struct ip_ct_h225_expect *exp_info;
6510+
6511+ /* Only mangle things once: original direction in POST_ROUTING
6512+ and reply direction on PRE_ROUTING. */
6513+ dir = CTINFO2DIR(ctinfo);
6514+ DEBUGP("nat_h323: dir %s at hook %s\n",
6515+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6516+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6517+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6518+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6519+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6520+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6521+ DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6522+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6523+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6524+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6525+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6526+ return NF_ACCEPT;
6527+ }
6528+
6529+ if (!exp) {
6530+ LOCK_BH(&ip_h323_lock);
6531+ if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6532+ UNLOCK_BH(&ip_h323_lock);
6533+ return NF_DROP;
6534+ }
6535+ UNLOCK_BH(&ip_h323_lock);
6536+ return NF_ACCEPT;
6537+ }
6538+
6539+ exp_info = &exp->help.exp_h225_info;
6540+
6541+ LOCK_BH(&ip_h323_lock);
6542+ if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6543+ UNLOCK_BH(&ip_h323_lock);
6544+ return NF_DROP;
6545+ }
6546+ UNLOCK_BH(&ip_h323_lock);
6547+
6548+ return NF_ACCEPT;
6549+}
6550+
6551+static struct ip_nat_helper h225 =
6552+ { { NULL, NULL },
6553+ "H.225", /* name */
6554+ IP_NAT_HELPER_F_ALWAYS, /* flags */
6555+ THIS_MODULE, /* module */
6556+ { { 0, { .tcp = { __constant_htons(H225_PORT) } } }, /* tuple */
6557+ { 0, { 0 }, IPPROTO_TCP } },
6558+ { { 0, { .tcp = { 0xFFFF } } }, /* mask */
6559+ { 0, { 0 }, 0xFFFF } },
6560+ h225_nat_help, /* helper */
6561+ h225_nat_expected /* expectfn */
6562+ };
6563+
6564+static int __init init(void)
6565+{
6566+ int ret;
6567+
6568+ ret = ip_nat_helper_register(&h225);
6569+
6570+ if (ret != 0)
6571+ printk("ip_nat_h323: cannot initialize the module!\n");
6572+
6573+ return ret;
6574+}
6575+
6576+static void __exit fini(void)
6577+{
6578+ ip_nat_helper_unregister(&h225);
6579+}
6580+
6581+module_init(init);
6582+module_exit(fini);
6583diff -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
6584--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6585+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c 2004-04-29 11:19:01.000000000 +0200
6586@@ -0,0 +1,350 @@
6587+/* MMS extension for TCP NAT alteration.
6588+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6589+ * based on ip_nat_ftp.c and ip_nat_irc.c
6590+ *
6591+ * ip_nat_mms.c v0.3 2002-09-22
6592+ *
6593+ * This program is free software; you can redistribute it and/or
6594+ * modify it under the terms of the GNU General Public License
6595+ * as published by the Free Software Foundation; either version
6596+ * 2 of the License, or (at your option) any later version.
6597+ *
6598+ * Module load syntax:
6599+ * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6600+ *
6601+ * Please give the ports of all MMS servers You wish to connect to.
6602+ * If you don't specify ports, the default will be TCP port 1755.
6603+ *
6604+ * More info on MMS protocol, firewalls and NAT:
6605+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6606+ * http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6607+ *
6608+ * The SDP project people are reverse-engineering MMS:
6609+ * http://get.to/sdp
6610+ */
6611+
6612+/* FIXME: issue with UDP & fragmentation with this URL:
6613+ http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx
6614+ may be related to out-of-order first packets:
6615+ basically the expectation is set up correctly, then the server sends
6616+ a first UDP packet which is fragmented plus arrives out-of-order.
6617+ the MASQUERADING firewall with ip_nat_mms loaded responds with
6618+ an ICMP unreachable back to the server */
6619+
6620+#include <linux/module.h>
6621+#include <linux/netfilter_ipv4.h>
6622+#include <linux/ip.h>
6623+#include <linux/tcp.h>
6624+#include <net/tcp.h>
6625+#include <linux/netfilter_ipv4/ip_nat.h>
6626+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6627+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6628+#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6629+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6630+
6631+#if 0
6632+#define DEBUGP printk
6633+#define DUMP_BYTES(address, counter) \
6634+({ \
6635+ int temp_counter; \
6636+ for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6637+ DEBUGP("%u ", (u8)*(address+temp_counter)); \
6638+ }; \
6639+ DEBUGP("\n"); \
6640+})
6641+#else
6642+#define DEBUGP(format, args...)
6643+#define DUMP_BYTES(address, counter)
6644+#endif
6645+
6646+#define MAX_PORTS 8
6647+static int ports[MAX_PORTS];
6648+static int ports_c = 0;
6649+
6650+#ifdef MODULE_PARM
6651+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6652+#endif
6653+
6654+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6655+MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6656+MODULE_LICENSE("GPL");
6657+
6658+DECLARE_LOCK_EXTERN(ip_mms_lock);
6659+
6660+/* FIXME: Time out? --RR */
6661+
6662+static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6663+ struct ip_conntrack *ct,
6664+ struct sk_buff **pskb,
6665+ enum ip_conntrack_info ctinfo,
6666+ struct ip_conntrack_expect *expect)
6667+{
6668+ u_int32_t newip;
6669+ struct ip_conntrack_tuple t;
6670+ struct iphdr *iph = (*pskb)->nh.iph;
6671+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6672+ char *data = (char *)tcph + tcph->doff * 4;
6673+ int i, j, k, port;
6674+ u_int16_t mms_proto;
6675+
6676+ u_int32_t *mms_chunkLenLV = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6677+ u_int32_t *mms_chunkLenLM = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6678+ u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6679+
6680+ int zero_padding;
6681+
6682+ char buffer[28]; /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6683+ char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6684+ char proto_string[6];
6685+
6686+ MUST_BE_LOCKED(&ip_mms_lock);
6687+
6688+ /* what was the protocol again ? */
6689+ mms_proto = expect->tuple.dst.protonum;
6690+ sprintf(proto_string, "%u", mms_proto);
6691+
6692+ DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6693+ expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6694+ mms_proto == IPPROTO_UDP ? "UDP"
6695+ : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6696+
6697+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6698+
6699+ /* Alter conntrack's expectations. */
6700+ t = expect->tuple;
6701+ t.dst.ip = newip;
6702+ for (port = ct_mms_info->port; port != 0; port++) {
6703+ t.dst.u.tcp.port = htons(port);
6704+ if (ip_conntrack_change_expect(expect, &t) == 0) {
6705+ DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6706+ break;
6707+ }
6708+ }
6709+
6710+ if(port == 0)
6711+ return 0;
6712+
6713+ sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6714+ NIPQUAD(newip),
6715+ expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6716+ : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6717+ port);
6718+ DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6719+
6720+ memset(unicode_buffer, 0, sizeof(char)*75);
6721+
6722+ for (i=0; i<strlen(buffer); ++i)
6723+ *(unicode_buffer+i*2)=*(buffer+i);
6724+
6725+ DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6726+ DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6727+ DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6728+
6729+ /* add end of packet to it */
6730+ for (j=0; j<ct_mms_info->padding; ++j) {
6731+ DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n",
6732+ i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6733+ *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6734+ }
6735+
6736+ /* pad with zeroes at the end ? see explanation of weird math below */
6737+ zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6738+ for (k=0; k<zero_padding; ++k)
6739+ *(unicode_buffer+i*2+j+k)= (char)0;
6740+
6741+ DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6742+ DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6743+ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6744+
6745+ /* explanation, before I forget what I did:
6746+ strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6747+ divide by 8 and add 3 to compute the mms_chunkLenLM field,
6748+ but note that things may have to be padded with zeroes to align by 8
6749+ bytes, hence we add 7 and divide by 8 to get the correct length */
6750+ *mms_chunkLenLM = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6751+ *mms_chunkLenLV = *mms_chunkLenLM+2;
6752+ *mms_messageLength = *mms_chunkLenLV*8;
6753+
6754+ DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6755+ *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6756+
6757+ ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6758+ expect->seq - ntohl(tcph->seq),
6759+ ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6760+ strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6761+ DUMP_BYTES(unicode_buffer, 60);
6762+
6763+ return 1;
6764+}
6765+
6766+static unsigned int
6767+mms_nat_expected(struct sk_buff **pskb,
6768+ unsigned int hooknum,
6769+ struct ip_conntrack *ct,
6770+ struct ip_nat_info *info)
6771+{
6772+ struct ip_nat_multi_range mr;
6773+ u_int32_t newdstip, newsrcip, newip;
6774+
6775+ struct ip_conntrack *master = master_ct(ct);
6776+
6777+ IP_NF_ASSERT(info);
6778+ IP_NF_ASSERT(master);
6779+
6780+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6781+
6782+ DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6783+
6784+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6785+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6786+ DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6787+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6788+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6789+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6790+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
6791+
6792+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6793+ newip = newsrcip;
6794+ else
6795+ newip = newdstip;
6796+
6797+ DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6798+
6799+ mr.rangesize = 1;
6800+ /* We don't want to manip the per-protocol, just the IPs. */
6801+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6802+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
6803+
6804+ return ip_nat_setup_info(ct, &mr, hooknum);
6805+}
6806+
6807+
6808+static unsigned int mms_nat_help(struct ip_conntrack *ct,
6809+ struct ip_conntrack_expect *exp,
6810+ struct ip_nat_info *info,
6811+ enum ip_conntrack_info ctinfo,
6812+ unsigned int hooknum,
6813+ struct sk_buff **pskb)
6814+{
6815+ struct iphdr *iph = (*pskb)->nh.iph;
6816+ struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6817+ unsigned int datalen;
6818+ int dir;
6819+ struct ip_ct_mms_expect *ct_mms_info;
6820+
6821+ if (!exp)
6822+ DEBUGP("ip_nat_mms: no exp!!");
6823+
6824+ ct_mms_info = &exp->help.exp_mms_info;
6825+
6826+ /* Only mangle things once: original direction in POST_ROUTING
6827+ and reply direction on PRE_ROUTING. */
6828+ dir = CTINFO2DIR(ctinfo);
6829+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6830+ ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6831+ DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6832+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6833+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6834+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6835+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6836+ return NF_ACCEPT;
6837+ }
6838+ DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6839+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6840+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6841+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6842+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6843+
6844+ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6845+
6846+ DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6847+ exp->seq + ct_mms_info->len,
6848+ ntohl(tcph->seq),
6849+ ntohl(tcph->seq) + datalen);
6850+
6851+ LOCK_BH(&ip_mms_lock);
6852+ /* Check wether the whole IP/proto/port pattern is carried in the payload */
6853+ if (between(exp->seq + ct_mms_info->len,
6854+ ntohl(tcph->seq),
6855+ ntohl(tcph->seq) + datalen)) {
6856+ if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6857+ UNLOCK_BH(&ip_mms_lock);
6858+ return NF_DROP;
6859+ }
6860+ } else {
6861+ /* Half a match? This means a partial retransmisison.
6862+ It's a cracker being funky. */
6863+ if (net_ratelimit()) {
6864+ printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6865+ exp->seq, ct_mms_info->len,
6866+ ntohl(tcph->seq),
6867+ ntohl(tcph->seq) + datalen);
6868+ }
6869+ UNLOCK_BH(&ip_mms_lock);
6870+ return NF_DROP;
6871+ }
6872+ UNLOCK_BH(&ip_mms_lock);
6873+
6874+ return NF_ACCEPT;
6875+}
6876+
6877+static struct ip_nat_helper mms[MAX_PORTS];
6878+static char mms_names[MAX_PORTS][10];
6879+
6880+/* Not __exit: called from init() */
6881+static void fini(void)
6882+{
6883+ int i;
6884+
6885+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6886+ DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6887+ ip_nat_helper_unregister(&mms[i]);
6888+ }
6889+}
6890+
6891+static int __init init(void)
6892+{
6893+ int i, ret = 0;
6894+ char *tmpname;
6895+
6896+ if (ports[0] == 0)
6897+ ports[0] = MMS_PORT;
6898+
6899+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6900+
6901+ memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6902+
6903+ mms[i].tuple.dst.protonum = IPPROTO_TCP;
6904+ mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6905+ mms[i].mask.dst.protonum = 0xFFFF;
6906+ mms[i].mask.src.u.tcp.port = 0xFFFF;
6907+ mms[i].help = mms_nat_help;
6908+ mms[i].me = THIS_MODULE;
6909+ mms[i].flags = 0;
6910+ mms[i].expect = mms_nat_expected;
6911+
6912+ tmpname = &mms_names[i][0];
6913+ if (ports[i] == MMS_PORT)
6914+ sprintf(tmpname, "mms");
6915+ else
6916+ sprintf(tmpname, "mms-%d", i);
6917+ mms[i].name = tmpname;
6918+
6919+ DEBUGP("ip_nat_mms: register helper for port %d\n",
6920+ ports[i]);
6921+ ret = ip_nat_helper_register(&mms[i]);
6922+
6923+ if (ret) {
6924+ printk("ip_nat_mms: error registering "
6925+ "helper for port %d\n", ports[i]);
6926+ fini();
6927+ return ret;
6928+ }
6929+ ports_c++;
6930+ }
6931+
6932+ return ret;
6933+}
6934+
6935+module_init(init);
6936+module_exit(fini);
6937diff -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
6938--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c 1970-01-01 01:00:00.000000000 +0100
6939+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c 2004-04-29 11:19:53.000000000 +0200
6940@@ -0,0 +1,249 @@
6941+/* Quake3 extension for UDP NAT alteration.
6942+ * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6943+ * based on ip_nat_ftp.c and ip_nat_tftp.c
6944+ *
6945+ * ip_nat_quake3.c v0.0.3 2002-08-31
6946+ *
6947+ * This program is free software; you can redistribute it and/or
6948+ * modify it under the terms of the GNU General Public License
6949+ * as published by the Free Software Foundation; either version
6950+ * 2 of the License, or (at your option) any later version.
6951+ *
6952+ * Module load syntax:
6953+ * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6954+ *
6955+ * please give the ports of all Quake3 master servers You wish to
6956+ * connect to. If you don't specify ports, the default will be UDP
6957+ * port 27950.
6958+ *
6959+ * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6960+ *
6961+ * Notes:
6962+ * - If you're one of those people who would try anything to lower
6963+ * latency while playing Quake (and who isn't :-) ), you may want to
6964+ * consider not loading ip_nat_quake3 at all and just MASQUERADE all
6965+ * outgoing UDP traffic.
6966+ * This will make ip_conntrack_quake3 add the necessary expectations,
6967+ * but there will be no overhead for client->server UDP streams. If
6968+ * ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6969+ * hook for every packet in the client->server UDP stream.
6970+ * - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6971+ * The IP addresses in the master connection payload (=IP addresses
6972+ * of Quake servers) have no relation with the master server so
6973+ * DNAT'ing the master connection to a server should not change the
6974+ * expected connections.
6975+ * - Not tested due to lack of equipment:
6976+ * - multiple Quake3 clients behind one MASQUERADE gateway
6977+ * - what if Quake3 client is running on router too
6978+ */
6979+
6980+#include <linux/module.h>
6981+#include <linux/netfilter_ipv4.h>
6982+#include <linux/ip.h>
6983+#include <linux/udp.h>
6984+
6985+#include <linux/netfilter.h>
6986+#include <linux/netfilter_ipv4/ip_tables.h>
6987+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6988+#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6989+#include <linux/netfilter_ipv4/ip_nat_helper.h>
6990+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6991+
6992+MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6993+MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6994+MODULE_LICENSE("GPL");
6995+
6996+#define MAX_PORTS 8
6997+
6998+static int ports[MAX_PORTS];
6999+static int ports_c = 0;
7000+#ifdef MODULE_PARM
7001+MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7002+MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7003+#endif
7004+
7005+/* Quake3 master server reply will add > 100 expectations per reply packet; when
7006+ doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7007+#if 0
7008+#define DEBUGP printk
7009+#else
7010+#define DEBUGP(format, args...)
7011+#endif
7012+
7013+static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7014+
7015+static unsigned int
7016+quake3_nat_help(struct ip_conntrack *ct,
7017+ struct ip_conntrack_expect *exp,
7018+ struct ip_nat_info *info,
7019+ enum ip_conntrack_info ctinfo,
7020+ unsigned int hooknum,
7021+ struct sk_buff **pskb)
7022+{
7023+ struct iphdr *iph = (*pskb)->nh.iph;
7024+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
7025+ struct ip_conntrack_tuple repl;
7026+ int dir = CTINFO2DIR(ctinfo);
7027+ int i;
7028+
7029+ DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7030+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7031+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7032+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7033+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7034+ );
7035+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7036+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7037+
7038+ /* Only mangle things once: original direction in POST_ROUTING
7039+ and reply direction on PRE_ROUTING. */
7040+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7041+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7042+ DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7043+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7044+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7045+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7046+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7047+ return NF_ACCEPT;
7048+ }
7049+
7050+ if (!exp) {
7051+ DEBUGP("no conntrack expectation to modify\n");
7052+ return NF_ACCEPT;
7053+ }
7054+
7055+ if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7056+ for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7057+ i+6 < ntohs(udph->len);
7058+ i+=7) {
7059+ DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
7060+ i, ntohs(udph->len),
7061+ NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7062+ ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7063+
7064+ memset(&repl, 0, sizeof(repl));
7065+
7066+ repl.dst.protonum = IPPROTO_UDP;
7067+ repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7068+ repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7069+ repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 ) );
7070+
7071+ ip_conntrack_change_expect(exp, &repl);
7072+ }
7073+ }
7074+ return NF_ACCEPT;
7075+}
7076+
7077+static unsigned int
7078+quake3_nat_expected(struct sk_buff **pskb,
7079+ unsigned int hooknum,
7080+ struct ip_conntrack *ct,
7081+ struct ip_nat_info *info)
7082+{
7083+ const struct ip_conntrack *master = ct->master->expectant;
7084+ struct ip_nat_multi_range mr;
7085+ u_int32_t newsrcip, newdstip, newip;
7086+#if 0
7087+ const struct ip_conntrack_tuple *repl =
7088+ &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7089+ struct iphdr *iph = (*pskb)->nh.iph;
7090+ struct udphdr *udph = (void *)iph + iph->ihl*4;
7091+#endif
7092+
7093+ DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7094+ DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7095+
7096+ IP_NF_ASSERT(info);
7097+ IP_NF_ASSERT(master);
7098+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7099+
7100+ newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7101+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7102+
7103+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7104+ newip = newsrcip;
7105+ DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7106+ "newsrc: %u.%u.%u.%u\n",
7107+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7108+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7109+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7110+ NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7111+ NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7112+ NIPQUAD(newip));
7113+
7114+ } else {
7115+ newip = newdstip;
7116+ DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7117+ "newdst: %u.%u.%u.%u\n",
7118+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7119+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7120+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7121+ NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7122+ NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7123+ NIPQUAD(newip));
7124+ }
7125+
7126+ mr.rangesize = 1;
7127+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7128+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
7129+
7130+ return ip_nat_setup_info(ct,&mr,hooknum);
7131+}
7132+
7133+static struct ip_nat_helper quake3[MAX_PORTS];
7134+static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
7135+
7136+static void fini(void)
7137+{
7138+ int i;
7139+
7140+ for (i = 0 ; i < ports_c; i++) {
7141+ DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7142+ ip_nat_helper_unregister(&quake3[i]);
7143+ }
7144+}
7145+
7146+static int __init init(void)
7147+ {
7148+ int i, ret = 0;
7149+ char *tmpname;
7150+
7151+ if (!ports[0])
7152+ ports[0] = QUAKE3_MASTER_PORT;
7153+
7154+ for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7155+ memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7156+
7157+ quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7158+ quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7159+ quake3[i].mask.dst.protonum = 0xFFFF;
7160+ quake3[i].mask.src.u.udp.port = 0xFFFF;
7161+ quake3[i].help = quake3_nat_help;
7162+ quake3[i].flags = 0;
7163+ quake3[i].me = THIS_MODULE;
7164+ quake3[i].expect = quake3_nat_expected;
7165+
7166+ tmpname = &quake3_names[i][0];
7167+ if (ports[i] == QUAKE3_MASTER_PORT)
7168+ sprintf(tmpname, "quake3");
7169+ else
7170+ sprintf(tmpname, "quake3-%d", i);
7171+ quake3[i].name = tmpname;
7172+
7173+ DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7174+ ports[i], quake3[i].name);
7175+ ret = ip_nat_helper_register(&quake3[i]);
7176+
7177+ if (ret) {
7178+ printk("ip_nat_quake3: unable to register helper for port %d\n",
7179+ ports[i]);
7180+ fini();
7181+ return ret;
7182+ }
7183+ ports_c++;
7184+ }
7185+ return ret;
7186+ }
7187+
7188+module_init(init);
7189+module_exit(fini);
7190diff -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
7191--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c 1970-01-01 01:00:00.000000000 +0100
7192+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c 2004-04-29 11:20:13.000000000 +0200
7193@@ -0,0 +1,621 @@
7194+/*
7195+ * RTSP extension for TCP NAT alteration
7196+ * (C) 2003 by Tom Marshall <tmarshall@real.com>
7197+ * based on ip_nat_irc.c
7198+ *
7199+ * This program is free software; you can redistribute it and/or
7200+ * modify it under the terms of the GNU General Public License
7201+ * as published by the Free Software Foundation; either version
7202+ * 2 of the License, or (at your option) any later version.
7203+ *
7204+ * Module load syntax:
7205+ * insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7206+ * stunaddr=<address>
7207+ * destaction=[auto|strip|none]
7208+ *
7209+ * If no ports are specified, the default will be port 554 only.
7210+ *
7211+ * stunaddr specifies the address used to detect that a client is using STUN.
7212+ * If this address is seen in the destination parameter, it is assumed that
7213+ * the client has already punched a UDP hole in the firewall, so we don't
7214+ * mangle the client_port. If none is specified, it is autodetected. It
7215+ * only needs to be set if you have multiple levels of NAT. It should be
7216+ * set to the external address that the STUN clients detect. Note that in
7217+ * this case, it will not be possible for clients to use UDP with servers
7218+ * between the NATs.
7219+ *
7220+ * If no destaction is specified, auto is used.
7221+ * destaction=auto: strip destination parameter if it is not stunaddr.
7222+ * destaction=strip: always strip destination parameter (not recommended).
7223+ * destaction=none: do not touch destination parameter (not recommended).
7224+ */
7225+
7226+#include <linux/module.h>
7227+#include <linux/netfilter_ipv4.h>
7228+#include <linux/ip.h>
7229+#include <linux/tcp.h>
7230+#include <linux/kernel.h>
7231+#include <net/tcp.h>
7232+#include <linux/netfilter_ipv4/ip_nat.h>
7233+#include <linux/netfilter_ipv4/ip_nat_helper.h>
7234+#include <linux/netfilter_ipv4/ip_nat_rule.h>
7235+#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7236+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7237+
7238+#include <linux/inet.h>
7239+#include <linux/ctype.h>
7240+#define NF_NEED_STRNCASECMP
7241+#define NF_NEED_STRTOU16
7242+#include <linux/netfilter_helpers.h>
7243+#define NF_NEED_MIME_NEXTLINE
7244+#include <linux/netfilter_mime.h>
7245+
7246+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7247+#ifdef IP_NF_RTSP_DEBUG
7248+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7249+#else
7250+#define DEBUGP(fmt, args...)
7251+#endif
7252+
7253+#define MAX_PORTS 8
7254+#define DSTACT_AUTO 0
7255+#define DSTACT_STRIP 1
7256+#define DSTACT_NONE 2
7257+
7258+static int ports[MAX_PORTS];
7259+static char* stunaddr = NULL;
7260+static char* destaction = NULL;
7261+
7262+static int num_ports = 0;
7263+static u_int32_t extip = 0;
7264+static int dstact = 0;
7265+
7266+MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7267+MODULE_DESCRIPTION("RTSP network address translation module");
7268+MODULE_LICENSE("GPL");
7269+#ifdef MODULE_PARM
7270+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7271+MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7272+MODULE_PARM(stunaddr, "s");
7273+MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7274+MODULE_PARM(destaction, "s");
7275+MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7276+#endif
7277+
7278+/* protects rtsp part of conntracks */
7279+DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7280+
7281+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7282+
7283+/*** helper functions ***/
7284+
7285+static void
7286+get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7287+{
7288+ struct iphdr* iph = (struct iphdr*)skb->nh.iph;
7289+ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7290+
7291+ *pptcpdata = (char*)tcph + tcph->doff*4;
7292+ *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7293+}
7294+
7295+/*** nat functions ***/
7296+
7297+/*
7298+ * Mangle the "Transport:" header:
7299+ * - Replace all occurences of "client_port=<spec>"
7300+ * - Handle destination parameter
7301+ *
7302+ * In:
7303+ * ct, ctinfo = conntrack context
7304+ * pskb = packet
7305+ * tranoff = Transport header offset from TCP data
7306+ * tranlen = Transport header length (incl. CRLF)
7307+ * rport_lo = replacement low port (host endian)
7308+ * rport_hi = replacement high port (host endian)
7309+ *
7310+ * Returns packet size difference.
7311+ *
7312+ * Assumes that a complete transport header is present, ending with CR or LF
7313+ */
7314+static int
7315+rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7316+ struct ip_conntrack_expect* exp,
7317+ struct sk_buff** pskb, uint tranoff, uint tranlen)
7318+{
7319+ char* ptcp;
7320+ uint tcplen;
7321+ char* ptran;
7322+ char rbuf1[16]; /* Replacement buffer (one port) */
7323+ uint rbuf1len; /* Replacement len (one port) */
7324+ char rbufa[16]; /* Replacement buffer (all ports) */
7325+ uint rbufalen; /* Replacement len (all ports) */
7326+ u_int32_t newip;
7327+ u_int16_t loport, hiport;
7328+ uint off = 0;
7329+ uint diff; /* Number of bytes we removed */
7330+
7331+ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7332+ struct ip_conntrack_tuple t;
7333+
7334+ char szextaddr[15+1];
7335+ uint extaddrlen;
7336+ int is_stun;
7337+
7338+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7339+ ptran = ptcp+tranoff;
7340+
7341+ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7342+ tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7343+ nf_strncasecmp(ptran, "Transport:", 10) != 0)
7344+ {
7345+ INFOP("sanity check failed\n");
7346+ return 0;
7347+ }
7348+ off += 10;
7349+ SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7350+
7351+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7352+ t = exp->tuple;
7353+ t.dst.ip = newip;
7354+
7355+ extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7356+ : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7357+ DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7358+
7359+ rbuf1len = rbufalen = 0;
7360+ switch (prtspexp->pbtype)
7361+ {
7362+ case pb_single:
7363+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7364+ {
7365+ t.dst.u.udp.port = htons(loport);
7366+ if (ip_conntrack_change_expect(exp, &t) == 0)
7367+ {
7368+ DEBUGP("using port %hu\n", loport);
7369+ break;
7370+ }
7371+ }
7372+ if (loport != 0)
7373+ {
7374+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7375+ rbufalen = sprintf(rbufa, "%hu", loport);
7376+ }
7377+ break;
7378+ case pb_range:
7379+ for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7380+ {
7381+ t.dst.u.udp.port = htons(loport);
7382+ if (ip_conntrack_change_expect(exp, &t) == 0)
7383+ {
7384+ hiport = loport + ~exp->mask.dst.u.udp.port;
7385+ DEBUGP("using ports %hu-%hu\n", loport, hiport);
7386+ break;
7387+ }
7388+ }
7389+ if (loport != 0)
7390+ {
7391+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7392+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7393+ }
7394+ break;
7395+ case pb_discon:
7396+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7397+ {
7398+ t.dst.u.udp.port = htons(loport);
7399+ if (ip_conntrack_change_expect(exp, &t) == 0)
7400+ {
7401+ DEBUGP("using port %hu (1 of 2)\n", loport);
7402+ break;
7403+ }
7404+ }
7405+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7406+ {
7407+ t.dst.u.udp.port = htons(hiport);
7408+ if (ip_conntrack_change_expect(exp, &t) == 0)
7409+ {
7410+ DEBUGP("using port %hu (2 of 2)\n", hiport);
7411+ break;
7412+ }
7413+ }
7414+ if (loport != 0 && hiport != 0)
7415+ {
7416+ rbuf1len = sprintf(rbuf1, "%hu", loport);
7417+ if (hiport == loport+1)
7418+ {
7419+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7420+ }
7421+ else
7422+ {
7423+ rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7424+ }
7425+ }
7426+ break;
7427+ }
7428+
7429+ if (rbuf1len == 0)
7430+ {
7431+ return 0; /* cannot get replacement port(s) */
7432+ }
7433+
7434+ /* Transport: tran;field;field=val,tran;field;field=val,... */
7435+ while (off < tranlen)
7436+ {
7437+ uint saveoff;
7438+ const char* pparamend;
7439+ uint nextparamoff;
7440+
7441+ pparamend = memchr(ptran+off, ',', tranlen-off);
7442+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7443+ nextparamoff = pparamend-ptcp;
7444+
7445+ /*
7446+ * We pass over each param twice. On the first pass, we look for a
7447+ * destination= field. It is handled by the security policy. If it
7448+ * is present, allowed, and equal to our external address, we assume
7449+ * that STUN is being used and we leave the client_port= field alone.
7450+ */
7451+ is_stun = 0;
7452+ saveoff = off;
7453+ while (off < nextparamoff)
7454+ {
7455+ const char* pfieldend;
7456+ uint nextfieldoff;
7457+
7458+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7459+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7460+
7461+ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7462+ {
7463+ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7464+ {
7465+ is_stun = 1;
7466+ }
7467+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7468+ {
7469+ diff = nextfieldoff-off;
7470+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7471+ off, diff, NULL, 0))
7472+ {
7473+ /* mangle failed, all we can do is bail */
7474+ return 0;
7475+ }
7476+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7477+ ptran = ptcp+tranoff;
7478+ tranlen -= diff;
7479+ nextparamoff -= diff;
7480+ nextfieldoff -= diff;
7481+ }
7482+ }
7483+
7484+ off = nextfieldoff;
7485+ }
7486+ if (is_stun)
7487+ {
7488+ continue;
7489+ }
7490+ off = saveoff;
7491+ while (off < nextparamoff)
7492+ {
7493+ const char* pfieldend;
7494+ uint nextfieldoff;
7495+
7496+ pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7497+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7498+
7499+ if (strncmp(ptran+off, "client_port=", 12) == 0)
7500+ {
7501+ u_int16_t port;
7502+ uint numlen;
7503+ uint origoff;
7504+ uint origlen;
7505+ char* rbuf = rbuf1;
7506+ uint rbuflen = rbuf1len;
7507+
7508+ off += 12;
7509+ origoff = (ptran-ptcp)+off;
7510+ origlen = 0;
7511+ numlen = nf_strtou16(ptran+off, &port);
7512+ off += numlen;
7513+ origlen += numlen;
7514+ if (port != prtspexp->loport)
7515+ {
7516+ DEBUGP("multiple ports found, port %hu ignored\n", port);
7517+ }
7518+ else
7519+ {
7520+ if (ptran[off] == '-' || ptran[off] == '/')
7521+ {
7522+ off++;
7523+ origlen++;
7524+ numlen = nf_strtou16(ptran+off, &port);
7525+ off += numlen;
7526+ origlen += numlen;
7527+ rbuf = rbufa;
7528+ rbuflen = rbufalen;
7529+ }
7530+
7531+ /*
7532+ * note we cannot just memcpy() if the sizes are the same.
7533+ * the mangle function does skb resizing, checks for a
7534+ * cloned skb, and updates the checksums.
7535+ *
7536+ * parameter 4 below is offset from start of tcp data.
7537+ */
7538+ diff = origlen-rbuflen;
7539+ if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7540+ origoff, origlen, rbuf, rbuflen))
7541+ {
7542+ /* mangle failed, all we can do is bail */
7543+ return 0;
7544+ }
7545+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7546+ ptran = ptcp+tranoff;
7547+ tranlen -= diff;
7548+ nextparamoff -= diff;
7549+ nextfieldoff -= diff;
7550+ }
7551+ }
7552+
7553+ off = nextfieldoff;
7554+ }
7555+
7556+ off = nextparamoff;
7557+ }
7558+
7559+ return 1;
7560+}
7561+
7562+static unsigned int
7563+expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7564+{
7565+ struct ip_nat_multi_range mr;
7566+ u_int32_t newdstip, newsrcip, newip;
7567+
7568+ struct ip_conntrack *master = master_ct(ct);
7569+
7570+ IP_NF_ASSERT(info);
7571+ IP_NF_ASSERT(master);
7572+
7573+ IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7574+
7575+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7576+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7577+ newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7578+
7579+ DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7580+ NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7581+
7582+ mr.rangesize = 1;
7583+ /* We don't want to manip the per-protocol, just the IPs. */
7584+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7585+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
7586+
7587+ return ip_nat_setup_info(ct, &mr, hooknum);
7588+}
7589+
7590+static uint
7591+help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7592+ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7593+{
7594+ char* ptcp;
7595+ uint tcplen;
7596+ uint hdrsoff;
7597+ uint hdrslen;
7598+ uint lineoff;
7599+ uint linelen;
7600+ uint off;
7601+
7602+ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7603+ struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7604+
7605+ struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7606+
7607+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7608+
7609+ hdrsoff = exp->seq - ntohl(tcph->seq);
7610+ hdrslen = prtspexp->len;
7611+ off = hdrsoff;
7612+
7613+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7614+ {
7615+ if (linelen == 0)
7616+ {
7617+ break;
7618+ }
7619+ if (off > hdrsoff+hdrslen)
7620+ {
7621+ INFOP("!! overrun !!");
7622+ break;
7623+ }
7624+ DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7625+
7626+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7627+ {
7628+ uint oldtcplen = tcplen;
7629+ if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7630+ {
7631+ break;
7632+ }
7633+ get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7634+ hdrslen -= (oldtcplen-tcplen);
7635+ off -= (oldtcplen-tcplen);
7636+ lineoff -= (oldtcplen-tcplen);
7637+ linelen -= (oldtcplen-tcplen);
7638+ DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7639+ }
7640+ }
7641+
7642+ return NF_ACCEPT;
7643+}
7644+
7645+static uint
7646+help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7647+ struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7648+{
7649+ /* XXX: unmangle */
7650+ return NF_ACCEPT;
7651+}
7652+
7653+static uint
7654+help(struct ip_conntrack* ct,
7655+ struct ip_conntrack_expect* exp,
7656+ struct ip_nat_info* info,
7657+ enum ip_conntrack_info ctinfo,
7658+ unsigned int hooknum,
7659+ struct sk_buff** pskb)
7660+{
7661+ struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7662+ struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7663+ uint datalen;
7664+ int dir;
7665+ struct ip_ct_rtsp_expect* ct_rtsp_info;
7666+ int rc = NF_ACCEPT;
7667+
7668+ if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7669+ {
7670+ DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7671+ return NF_ACCEPT;
7672+ }
7673+
7674+ ct_rtsp_info = &exp->help.exp_rtsp_info;
7675+
7676+ /*
7677+ * Only mangle things once: original direction in POST_ROUTING
7678+ * and reply direction on PRE_ROUTING.
7679+ */
7680+ dir = CTINFO2DIR(ctinfo);
7681+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7682+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7683+ {
7684+ DEBUGP("Not touching dir %s at hook %s\n",
7685+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7686+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7687+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7688+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7689+ return NF_ACCEPT;
7690+ }
7691+ DEBUGP("got beyond not touching\n");
7692+
7693+ datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7694+
7695+ LOCK_BH(&ip_rtsp_lock);
7696+ /* Ensure the packet contains all of the marked data */
7697+ if (!between(exp->seq + ct_rtsp_info->len,
7698+ ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7699+ {
7700+ /* Partial retransmission? Probably a hacker. */
7701+ if (net_ratelimit())
7702+ {
7703+ INFOP("partial packet %u/%u in %u/%u\n",
7704+ exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7705+ }
7706+ UNLOCK_BH(&ip_rtsp_lock);
7707+ return NF_DROP;
7708+ }
7709+
7710+ switch (dir)
7711+ {
7712+ case IP_CT_DIR_ORIGINAL:
7713+ rc = help_out(ct, ctinfo, exp, pskb);
7714+ break;
7715+ case IP_CT_DIR_REPLY:
7716+ rc = help_in(ct, ctinfo, exp, pskb);
7717+ break;
7718+ }
7719+ UNLOCK_BH(&ip_rtsp_lock);
7720+
7721+ return rc;
7722+}
7723+
7724+static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7725+static char rtsp_names[MAX_PORTS][10];
7726+
7727+/* This function is intentionally _NOT_ defined as __exit */
7728+static void
7729+fini(void)
7730+{
7731+ int i;
7732+
7733+ for (i = 0; i < num_ports; i++)
7734+ {
7735+ DEBUGP("unregistering helper for port %d\n", ports[i]);
7736+ ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7737+ }
7738+}
7739+
7740+static int __init
7741+init(void)
7742+{
7743+ int ret = 0;
7744+ int i;
7745+ struct ip_nat_helper* hlpr;
7746+ char* tmpname;
7747+
7748+ printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7749+
7750+ if (ports[0] == 0)
7751+ {
7752+ ports[0] = RTSP_PORT;
7753+ }
7754+
7755+ for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7756+ {
7757+ hlpr = &ip_nat_rtsp_helpers[i];
7758+ memset(hlpr, 0, sizeof(struct ip_nat_helper));
7759+
7760+ hlpr->tuple.dst.protonum = IPPROTO_TCP;
7761+ hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7762+ hlpr->mask.src.u.tcp.port = 0xFFFF;
7763+ hlpr->mask.dst.protonum = 0xFFFF;
7764+ hlpr->help = help;
7765+ hlpr->flags = 0;
7766+ hlpr->me = THIS_MODULE;
7767+ hlpr->expect = expected;
7768+
7769+ tmpname = &rtsp_names[i][0];
7770+ if (ports[i] == RTSP_PORT)
7771+ {
7772+ sprintf(tmpname, "rtsp");
7773+ }
7774+ else
7775+ {
7776+ sprintf(tmpname, "rtsp-%d", i);
7777+ }
7778+ hlpr->name = tmpname;
7779+
7780+ DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7781+ ret = ip_nat_helper_register(hlpr);
7782+
7783+ if (ret)
7784+ {
7785+ printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7786+ fini();
7787+ return 1;
7788+ }
7789+ num_ports++;
7790+ }
7791+ if (stunaddr != NULL)
7792+ {
7793+ extip = in_aton(stunaddr);
7794+ }
7795+ if (destaction != NULL)
7796+ {
7797+ if (strcmp(destaction, "auto") == 0)
7798+ {
7799+ dstact = DSTACT_AUTO;
7800+ }
7801+ if (strcmp(destaction, "strip") == 0)
7802+ {
7803+ dstact = DSTACT_STRIP;
7804+ }
7805+ if (strcmp(destaction, "none") == 0)
7806+ {
7807+ dstact = DSTACT_NONE;
7808+ }
7809+ }
7810+ return ret;
7811+}
7812+
7813+module_init(init);
7814+module_exit(fini);
7815diff -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
7816--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c 2004-04-28 03:35:44.000000000 +0200
7817+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c 2004-04-29 11:17:15.000000000 +0200
7818@@ -75,7 +75,7 @@
7819 0,
7820 sizeof(struct ipt_entry),
7821 sizeof(struct ipt_standard),
7822- 0, { 0, 0 }, { } },
7823+ 0, NULL, 0, { 0, 0 }, { } },
7824 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7825 -NF_ACCEPT - 1 } },
7826 /* POST_ROUTING */
7827@@ -83,7 +83,7 @@
7828 0,
7829 sizeof(struct ipt_entry),
7830 sizeof(struct ipt_standard),
7831- 0, { 0, 0 }, { } },
7832+ 0, NULL, 0, { 0, 0 }, { } },
7833 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7834 -NF_ACCEPT - 1 } },
7835 /* LOCAL_OUT */
7836@@ -91,7 +91,7 @@
7837 0,
7838 sizeof(struct ipt_entry),
7839 sizeof(struct ipt_standard),
7840- 0, { 0, 0 }, { } },
7841+ 0, NULL, 0, { 0, 0 }, { } },
7842 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7843 -NF_ACCEPT - 1 } }
7844 },
7845@@ -100,7 +100,7 @@
7846 0,
7847 sizeof(struct ipt_entry),
7848 sizeof(struct ipt_error),
7849- 0, { 0, 0 }, { } },
7850+ 0, NULL, 0, { 0, 0 }, { } },
7851 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7852 { } },
7853 "ERROR"
7854diff -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
7855--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-28 03:36:29.000000000 +0200
7856+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c 2004-04-29 11:18:04.000000000 +0200
7857@@ -175,6 +175,45 @@
7858 return do_bindings(ct, ctinfo, info, hooknum, pskb);
7859 }
7860
7861+struct nat_route_key
7862+{
7863+ u_int32_t addr;
7864+#ifdef CONFIG_XFRM
7865+ u_int16_t port;
7866+#endif
7867+};
7868+
7869+static inline void
7870+nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
7871+{
7872+ struct iphdr *iph = skb->nh.iph;
7873+
7874+ key->addr = which ? iph->daddr : iph->saddr;
7875+#ifdef CONFIG_XFRM
7876+ key->port = 0;
7877+ if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7878+ u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7879+ key->port = ports[which];
7880+ }
7881+#endif
7882+}
7883+
7884+static inline int
7885+nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
7886+{
7887+ struct iphdr *iph = skb->nh.iph;
7888+
7889+ if (key->addr != (which ? iph->daddr : iph->saddr))
7890+ return 1;
7891+#ifdef CONFIG_XFRM
7892+ if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7893+ u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7894+ if (key->port != ports[which])
7895+ return 1;
7896+ }
7897+#endif
7898+}
7899+
7900 static unsigned int
7901 ip_nat_out(unsigned int hooknum,
7902 struct sk_buff **pskb,
7903@@ -182,6 +221,9 @@
7904 const struct net_device *out,
7905 int (*okfn)(struct sk_buff *))
7906 {
7907+ struct nat_route_key key;
7908+ unsigned int ret;
7909+
7910 /* root is playing with raw sockets. */
7911 if ((*pskb)->len < sizeof(struct iphdr)
7912 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7913@@ -204,7 +246,29 @@
7914 return NF_STOLEN;
7915 }
7916
7917- return ip_nat_fn(hooknum, pskb, in, out, okfn);
7918+ nat_route_key_get(*pskb, &key, 0);
7919+ ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7920+
7921+ if (ret != NF_DROP && ret != NF_STOLEN
7922+ && nat_route_key_compare(*pskb, &key, 0)) {
7923+ if (ip_route_me_harder(pskb) != 0)
7924+ ret = NF_DROP;
7925+#ifdef CONFIG_XFRM
7926+ /*
7927+ * POST_ROUTING hook is called with fixed outfn, we need
7928+ * to manually confirm the packet and direct it to the
7929+ * transformers if a policy matches.
7930+ */
7931+ else if ((*pskb)->dst->xfrm != NULL) {
7932+ ret = ip_conntrack_confirm(*pskb);
7933+ if (ret != NF_DROP) {
7934+ dst_output(*pskb);
7935+ ret = NF_STOLEN;
7936+ }
7937+ }
7938+#endif
7939+ }
7940+ return ret;
7941 }
7942
7943 #ifdef CONFIG_IP_NF_NAT_LOCAL
7944@@ -215,7 +279,7 @@
7945 const struct net_device *out,
7946 int (*okfn)(struct sk_buff *))
7947 {
7948- u_int32_t saddr, daddr;
7949+ struct nat_route_key key;
7950 unsigned int ret;
7951
7952 /* root is playing with raw sockets. */
7953@@ -223,14 +287,14 @@
7954 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7955 return NF_ACCEPT;
7956
7957- saddr = (*pskb)->nh.iph->saddr;
7958- daddr = (*pskb)->nh.iph->daddr;
7959-
7960+ nat_route_key_get(*pskb, &key, 1);
7961 ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7962+
7963 if (ret != NF_DROP && ret != NF_STOLEN
7964- && ((*pskb)->nh.iph->saddr != saddr
7965- || (*pskb)->nh.iph->daddr != daddr))
7966- return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
7967+ && nat_route_key_compare(*pskb, &key, 1)) {
7968+ if (ip_route_me_harder(pskb) != 0)
7969+ ret = NF_DROP;
7970+ }
7971 return ret;
7972 }
7973 #endif
7974diff -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
7975--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c 1970-01-01 01:00:00.000000000 +0100
7976+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c 2004-04-29 11:21:43.000000000 +0200
7977@@ -0,0 +1,473 @@
7978+/*
7979+ * talk extension for UDP NAT alteration.
7980+ * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7981+ *
7982+ * This program is free software; you can redistribute it and/or
7983+ * modify it under the terms of the GNU General Public License
7984+ * as published by the Free Software Foundation; either version
7985+ * 2 of the License, or (at your option) any later version.
7986+ **
7987+ * Module load syntax:
7988+ * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7989+ *
7990+ * talk=[0|1] disable|enable old talk support
7991+ * ntalk=[0|1] disable|enable ntalk support
7992+ * ntalk2=[0|1] disable|enable ntalk2 support
7993+ *
7994+ * The default is talk=1 ntalk=1 ntalk2=1
7995+ *
7996+ *
7997+ */
7998+#include <linux/module.h>
7999+#include <linux/netfilter_ipv4.h>
8000+#include <linux/ip.h>
8001+#include <linux/udp.h>
8002+#include <linux/kernel.h>
8003+#include <net/tcp.h>
8004+#include <net/udp.h>
8005+
8006+#include <linux/netfilter_ipv4/ip_nat.h>
8007+#include <linux/netfilter_ipv4/ip_nat_helper.h>
8008+#include <linux/netfilter_ipv4/ip_nat_rule.h>
8009+#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8010+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8011+
8012+/* Default all talk protocols are supported */
8013+static int talk = 1;
8014+static int ntalk = 1;
8015+static int ntalk2 = 1;
8016+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8017+MODULE_DESCRIPTION("talk network address translation module");
8018+#ifdef MODULE_PARM
8019+MODULE_PARM(talk, "i");
8020+MODULE_PARM_DESC(talk, "support (old) talk protocol");
8021+MODULE_PARM(ntalk, "i");
8022+MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8023+MODULE_PARM(ntalk2, "i");
8024+MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8025+#endif
8026+
8027+#if 0
8028+#define DEBUGP printk
8029+#define IP_NAT_TALK_DEBUG
8030+#else
8031+#define DEBUGP(format, args...)
8032+#endif
8033+
8034+/* FIXME: Time out? --RR */
8035+
8036+static int
8037+mangle_packet(struct sk_buff **pskb,
8038+ struct ip_conntrack *ct,
8039+ u_int32_t newip,
8040+ u_int16_t port,
8041+ struct talk_addr *addr,
8042+ struct talk_addr *ctl_addr)
8043+{
8044+ struct iphdr *iph = (*pskb)->nh.iph;
8045+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
8046+ size_t udplen = (*pskb)->len - iph->ihl * 4;
8047+
8048+ /* Fortunately talk sends a structure with the address and
8049+ port in it. The size of the packet won't change. */
8050+
8051+ if (ctl_addr == NULL) {
8052+ /* response */
8053+ if (addr->ta_addr == INADDR_ANY)
8054+ return 1;
8055+ DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8056+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8057+ NIPQUAD(newip), ntohs(port));
8058+ addr->ta_addr = newip;
8059+ addr->ta_port = port;
8060+ } else {
8061+ /* message */
8062+ if (addr->ta_addr != INADDR_ANY) {
8063+ /* Change address inside packet to match way we're mapping
8064+ this connection. */
8065+ DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8066+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8067+ NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
8068+ ntohs(addr->ta_port));
8069+ addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8070+ }
8071+ DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n",
8072+ NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8073+ NIPQUAD(newip), ntohs(port));
8074+ ctl_addr->ta_addr = newip;
8075+ ctl_addr->ta_port = port;
8076+ }
8077+
8078+ /* Fix checksums */
8079+ (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8080+ udph->check = 0;
8081+ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8082+ csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8083+
8084+ ip_send_check(iph);
8085+ return 1;
8086+}
8087+
8088+static int talk_help_msg(struct ip_conntrack *ct,
8089+ struct sk_buff **pskb,
8090+ u_char type,
8091+ struct talk_addr *addr,
8092+ struct talk_addr *ctl_addr)
8093+{
8094+ u_int32_t newip;
8095+ u_int16_t port;
8096+
8097+ unsigned int verdict = NF_ACCEPT;
8098+
8099+ DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8100+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8101+ NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8102+ type);
8103+
8104+ /* Change address inside packet to match way we're mapping
8105+ this connection. */
8106+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8107+ port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8108+ DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8109+ NIPQUAD(newip), ntohs(port));
8110+
8111+ if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8112+ verdict = NF_DROP;
8113+
8114+ return verdict;
8115+}
8116+
8117+static int talk_help_response(struct ip_conntrack *ct,
8118+ struct ip_conntrack_expect *exp,
8119+ struct sk_buff **pskb,
8120+ u_char type,
8121+ u_char answer,
8122+ struct talk_addr *addr)
8123+{
8124+ u_int32_t newip;
8125+ u_int16_t port;
8126+ struct ip_conntrack_tuple t;
8127+ struct ip_ct_talk_expect *ct_talk_info;
8128+
8129+ DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8130+ NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8131+ type, answer);
8132+
8133+ LOCK_BH(&ip_talk_lock);
8134+ ct_talk_info = &exp->help.exp_talk_info;
8135+
8136+ if (!(answer == SUCCESS
8137+ && (type == LOOK_UP || type == ANNOUNCE)
8138+ && exp != NULL)) {
8139+ UNLOCK_BH(&ip_talk_lock);
8140+ return NF_ACCEPT;
8141+ }
8142+
8143+ DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n",
8144+ ntohs(ct_talk_info->port),
8145+ type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8146+
8147+ /* Change address inside packet to match way we're mapping
8148+ this connection. */
8149+ newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL :
8150+ IP_CT_DIR_REPLY].tuple.dst.ip;
8151+ /* We can read expect here without conntrack lock, since it's
8152+ only set in ip_conntrack_talk , with ip_talk_lock held
8153+ writable */
8154+ t = exp->tuple;
8155+ t.dst.ip = newip;
8156+
8157+ /* Try to get same port: if not, try to change it. */
8158+ for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8159+ if (type == LOOK_UP)
8160+ t.dst.u.tcp.port = htons(port);
8161+ else
8162+ t.dst.u.udp.port = htons(port);
8163+
8164+ if (ip_conntrack_change_expect(exp, &t) == 0) {
8165+ DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8166+ break;
8167+ }
8168+ }
8169+ UNLOCK_BH(&ip_talk_lock);
8170+
8171+ if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8172+ return NF_DROP;
8173+
8174+ return NF_ACCEPT;
8175+}
8176+
8177+static unsigned int talk_help(struct ip_conntrack *ct,
8178+ struct ip_conntrack_expect *exp,
8179+ struct ip_nat_info *info,
8180+ enum ip_conntrack_info ctinfo,
8181+ unsigned int hooknum,
8182+ struct sk_buff **pskb,
8183+ int talk_port)
8184+{
8185+ struct iphdr *iph = (*pskb)->nh.iph;
8186+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
8187+ unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8188+ char *data = (char *)udph + sizeof(struct udphdr);
8189+ int dir;
8190+
8191+ /* Only mangle things once: original direction in POST_ROUTING
8192+ and reply direction on PRE_ROUTING. */
8193+ dir = CTINFO2DIR(ctinfo);
8194+ if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8195+ || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8196+ DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8197+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8198+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8199+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8200+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8201+ return NF_ACCEPT;
8202+ }
8203+ DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8204+ dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8205+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8206+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8207+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8208+ NIPQUAD(iph->saddr), ntohs(udph->source),
8209+ NIPQUAD(iph->daddr), ntohs(udph->dest),
8210+ talk_port);
8211+
8212+ /* Because conntrack does not drop packets, checking must be repeated here... */
8213+ if (talk_port == TALK_PORT) {
8214+ if (dir == IP_CT_DIR_ORIGINAL
8215+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8216+ return talk_help_msg(ct, pskb,
8217+ ((struct talk_msg *)data)->type,
8218+ &(((struct talk_msg *)data)->addr),
8219+ &(((struct talk_msg *)data)->ctl_addr));
8220+ else if (dir == IP_CT_DIR_REPLY
8221+ && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8222+ return talk_help_response(ct, exp, pskb,
8223+ ((struct talk_response *)data)->type,
8224+ ((struct talk_response *)data)->answer,
8225+ &(((struct talk_response *)data)->addr));
8226+ else {
8227+ DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8228+ dir == IP_CT_DIR_ORIGINAL ? "message" : "response",
8229+ (unsigned)udplen - sizeof(struct udphdr),
8230+ dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8231+ return NF_DROP;
8232+ }
8233+ } else {
8234+ if (dir == IP_CT_DIR_ORIGINAL) {
8235+ if (ntalk
8236+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8237+ && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8238+ return talk_help_msg(ct, pskb,
8239+ ((struct ntalk_msg *)data)->type,
8240+ &(((struct ntalk_msg *)data)->addr),
8241+ &(((struct ntalk_msg *)data)->ctl_addr));
8242+ else if (ntalk2
8243+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8244+ && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8245+ && udplen == sizeof(struct udphdr)
8246+ + sizeof(struct ntalk2_msg)
8247+ + ((struct ntalk2_msg *)data)->extended)
8248+ return talk_help_msg(ct, pskb,
8249+ ((struct ntalk2_msg *)data)->type,
8250+ &(((struct ntalk2_msg *)data)->addr),
8251+ &(((struct ntalk2_msg *)data)->ctl_addr));
8252+ else {
8253+ DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n",
8254+ (unsigned)udplen - sizeof(struct udphdr),
8255+ sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8256+ return NF_DROP;
8257+ }
8258+ } else {
8259+ if (ntalk
8260+ && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8261+ && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8262+ return talk_help_response(ct, exp, pskb,
8263+ ((struct ntalk_response *)data)->type,
8264+ ((struct ntalk_response *)data)->answer,
8265+ &(((struct ntalk_response *)data)->addr));
8266+ else if (ntalk2
8267+ && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8268+ && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8269+ return talk_help_response(ct, exp, pskb,
8270+ ((struct ntalk2_response *)data)->type,
8271+ ((struct ntalk2_response *)data)->answer,
8272+ &(((struct ntalk2_response *)data)->addr));
8273+ else {
8274+ DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n",
8275+ (unsigned)udplen - sizeof(struct udphdr),
8276+ sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8277+ return NF_DROP;
8278+ }
8279+ }
8280+ }
8281+}
8282+
8283+static unsigned int help(struct ip_conntrack *ct,
8284+ struct ip_conntrack_expect *exp,
8285+ struct ip_nat_info *info,
8286+ enum ip_conntrack_info ctinfo,
8287+ unsigned int hooknum,
8288+ struct sk_buff **pskb)
8289+{
8290+ return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8291+}
8292+
8293+static unsigned int nhelp(struct ip_conntrack *ct,
8294+ struct ip_conntrack_expect *exp,
8295+ struct ip_nat_info *info,
8296+ enum ip_conntrack_info ctinfo,
8297+ unsigned int hooknum,
8298+ struct sk_buff **pskb)
8299+{
8300+ return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8301+}
8302+
8303+static unsigned int
8304+talk_nat_expected(struct sk_buff **pskb,
8305+ unsigned int hooknum,
8306+ struct ip_conntrack *ct,
8307+ struct ip_nat_info *info);
8308+
8309+static struct ip_nat_helper talk_helpers[2] =
8310+ { { { NULL, NULL },
8311+ "talk", /* name */
8312+ IP_NAT_HELPER_F_ALWAYS, /* flags */
8313+ THIS_MODULE, /* module */
8314+ { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8315+ { 0, { 0 }, IPPROTO_UDP } },
8316+ { { 0, { .udp = { 0xFFFF } } }, /* mask */
8317+ { 0, { 0 }, 0xFFFF } },
8318+ help, /* helper */
8319+ talk_nat_expected }, /* expectfn */
8320+ { { NULL, NULL },
8321+ "ntalk", /* name */
8322+ IP_NAT_HELPER_F_ALWAYS, /* flags */
8323+ THIS_MODULE, /* module */
8324+ { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8325+ { 0, { 0 }, IPPROTO_UDP } },
8326+ { { 0, { .udp = { 0xFFFF } } }, /* mask */
8327+ { 0, { 0 }, 0xFFFF } },
8328+ nhelp, /* helper */
8329+ talk_nat_expected } /* expectfn */
8330+ };
8331+
8332+static unsigned int
8333+talk_nat_expected(struct sk_buff **pskb,
8334+ unsigned int hooknum,
8335+ struct ip_conntrack *ct,
8336+ struct ip_nat_info *info)
8337+{
8338+ struct ip_nat_multi_range mr;
8339+ u_int32_t newdstip, newsrcip, newip;
8340+ u_int16_t port;
8341+ unsigned int ret;
8342+
8343+ struct ip_conntrack *master = master_ct(ct);
8344+
8345+ IP_NF_ASSERT(info);
8346+ IP_NF_ASSERT(master);
8347+
8348+ IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8349+
8350+ DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8351+
8352+ LOCK_BH(&ip_talk_lock);
8353+ port = ct->master->help.exp_talk_info.port;
8354+ UNLOCK_BH(&ip_talk_lock);
8355+
8356+ DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8357+ CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8358+ hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8359+ : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8360+ : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8361+ ct, master);
8362+
8363+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8364+ /* Callee client -> caller server */
8365+#ifdef IP_NAT_TALK_DEBUG
8366+ struct iphdr *iph = (*pskb)->nh.iph;
8367+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
8368+
8369+ DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8370+ NIPQUAD(iph->saddr), ntohs(udph->source),
8371+ NIPQUAD(iph->daddr), ntohs(udph->dest));
8372+#endif
8373+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8374+ newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8375+ DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8376+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
8377+ } else {
8378+ /* Callee client -> caller client */
8379+#ifdef IP_NAT_TALK_DEBUG
8380+ struct iphdr *iph = (*pskb)->nh.iph;
8381+ struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8382+
8383+ DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8384+ NIPQUAD(iph->saddr), ntohs(tcph->source),
8385+ NIPQUAD(iph->daddr), ntohs(tcph->dest));
8386+#endif
8387+ newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8388+ newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8389+ DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8390+ NIPQUAD(newsrcip), NIPQUAD(newdstip));
8391+ }
8392+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8393+ newip = newsrcip;
8394+ else
8395+ newip = newdstip;
8396+
8397+ DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8398+
8399+ mr.rangesize = 1;
8400+ /* We don't want to manip the per-protocol, just the IPs... */
8401+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8402+ mr.range[0].min_ip = mr.range[0].max_ip = newip;
8403+
8404+ /* ... unless we're doing a MANIP_DST, in which case, make
8405+ sure we map to the correct port */
8406+ if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8407+ mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8408+ mr.range[0].min = mr.range[0].max
8409+ = ((union ip_conntrack_manip_proto)
8410+ { .udp = { port } });
8411+ }
8412+ ret = ip_nat_setup_info(ct, &mr, hooknum);
8413+
8414+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8415+ DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8416+ /* NAT expectfn called with ip_nat_lock write-locked */
8417+ info->helper = &talk_helpers[htons(port) - TALK_PORT];
8418+ }
8419+ return ret;
8420+}
8421+
8422+static int __init init(void)
8423+{
8424+ int ret = 0;
8425+
8426+ if (talk > 0) {
8427+ ret = ip_nat_helper_register(&talk_helpers[0]);
8428+
8429+ if (ret != 0)
8430+ return ret;
8431+ }
8432+ if (ntalk > 0 || ntalk2 > 0) {
8433+ ret = ip_nat_helper_register(&talk_helpers[1]);
8434+
8435+ if (ret != 0 && talk > 0)
8436+ ip_nat_helper_unregister(&talk_helpers[0]);
8437+ }
8438+ return ret;
8439+}
8440+
8441+static void __exit fini(void)
8442+{
8443+ if (talk > 0)
8444+ ip_nat_helper_unregister(&talk_helpers[0]);
8445+ if (ntalk > 0 || ntalk2 > 0)
8446+ ip_nat_helper_unregister(&talk_helpers[1]);
8447+}
8448+
8449+module_init(init);
8450+module_exit(fini);
8451diff -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
8452--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-04-29 11:24:39.000000000 +0200
8453+++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c 2004-04-29 11:17:15.000000000 +0200
8454@@ -29,6 +29,14 @@
8455
8456 #include <linux/netfilter_ipv4/ip_tables.h>
8457
8458+static const char *hooknames[] = {
8459+ [NF_IP_PRE_ROUTING] "PREROUTING",
8460+ [NF_IP_LOCAL_IN] "INPUT",
8461+ [NF_IP_FORWARD] "FORWARD",
8462+ [NF_IP_LOCAL_OUT] "OUTPUT",
8463+ [NF_IP_POST_ROUTING] "POSTROUTING",
8464+};
8465+
8466 MODULE_LICENSE("GPL");
8467 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8468 MODULE_DESCRIPTION("IPv4 packet filter");
8469@@ -326,6 +334,12 @@
8470
8471 t = ipt_get_target(e);
8472 IP_NF_ASSERT(t->u.kernel.target);
8473+
8474+ /* The packet traced and the rule isn't an unconditional return/END. */
8475+ if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
8476+ nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8477+ table->name, e->chainname, e->rulenum);
8478+ }
8479 /* Standard target? */
8480 if (!t->u.kernel.target->target) {
8481 int v;
8482@@ -352,7 +366,6 @@
8483 /* set back pointer to next entry */
8484 back = next;
8485 }
8486-
8487 e = get_entry(table_base, v);
8488 } else {
8489 /* Targets which reenter must return
8490@@ -478,6 +491,29 @@
8491 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8492 }
8493
8494+static inline int
8495+find_error_target(struct ipt_entry *s,
8496+ struct ipt_entry *e,
8497+ char **chainname)
8498+{
8499+ struct ipt_entry_target *t;
8500+ static struct ipt_entry *found = NULL;
8501+
8502+ if (s == e) {
8503+ if (!found)
8504+ return 0;
8505+ t = ipt_get_target(found);
8506+ if (strcmp(t->u.user.name,
8507+ IPT_ERROR_TARGET) == 0) {
8508+ *chainname = t->data;
8509+ return 1;
8510+ }
8511+ } else
8512+ found = s;
8513+
8514+ return 0;
8515+}
8516+
8517 /* All zeroes == unconditional rule. */
8518 static inline int
8519 unconditional(const struct ipt_ip *ip)
8520@@ -497,6 +533,8 @@
8521 mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
8522 {
8523 unsigned int hook;
8524+ char *chainname = NULL;
8525+ u_int32_t rulenum;
8526
8527 /* No recursion; use packet counter to save back ptrs (reset
8528 to 0 as we leave), and comefrom to save source hook bitmask */
8529@@ -510,6 +548,8 @@
8530
8531 /* Set initial back pointer. */
8532 e->counters.pcnt = pos;
8533+ rulenum = 1;
8534+ chainname = (char *) hooknames[hook];
8535
8536 for (;;) {
8537 struct ipt_standard_target *t
8538@@ -522,6 +562,8 @@
8539 }
8540 e->comefrom
8541 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
8542+ e->rulenum = rulenum++;
8543+ e->chainname = chainname;
8544
8545 /* Unconditional return/END. */
8546 if (e->target_offset == sizeof(struct ipt_entry)
8547@@ -531,6 +573,10 @@
8548 && unconditional(&e->ip)) {
8549 unsigned int oldpos, size;
8550
8551+ /* Set unconditional rulenum to zero. */
8552+ e->rulenum = 0;
8553+ e->counters.bcnt = 0;
8554+
8555 /* Return: backtrack through the last
8556 big jump. */
8557 do {
8558@@ -556,6 +602,11 @@
8559 (newinfo->entries + pos);
8560 } while (oldpos == pos + e->next_offset);
8561
8562+ /* Restore chainname, rulenum. */
8563+ chainname = e->chainname;
8564+ rulenum = e->counters.bcnt;
8565+ e->counters.bcnt = 0;
8566+
8567 /* Move along one */
8568 size = e->next_offset;
8569 e = (struct ipt_entry *)
8570@@ -571,6 +622,17 @@
8571 /* This a jump; chase it. */
8572 duprintf("Jump rule %u -> %u\n",
8573 pos, newpos);
8574+ e->counters.bcnt = rulenum++;
8575+ rulenum = 1;
8576+ e = (struct ipt_entry *)
8577+ (newinfo->entries + newpos);
8578+ if (IPT_ENTRY_ITERATE(newinfo->entries,
8579+ newinfo->size,
8580+ find_error_target,
8581+ e, &chainname) == 0) {
8582+ printk("ip_tables: table screwed up!\n");
8583+ return 0;
8584+ }
8585 } else {
8586 /* ... this is a fallthru */
8587 newpos = pos + e->next_offset;
8588diff -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
8589--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
8590+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c 2004-04-29 11:10:59.000000000 +0200
8591@@ -0,0 +1,118 @@
8592+/* This kernel module is used to modify the connection mark values, or
8593+ * to optionally restore the skb nfmark from the connection mark
8594+ *
8595+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8596+ * by Henrik Nordstrom <hno@marasystems.com>
8597+ *
8598+ * This program is free software; you can redistribute it and/or modify
8599+ * it under the terms of the GNU General Public License as published by
8600+ * the Free Software Foundation; either version 2 of the License, or
8601+ * (at your option) any later version.
8602+ *
8603+ * This program is distributed in the hope that it will be useful,
8604+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8605+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8606+ * GNU General Public License for more details.
8607+ *
8608+ * You should have received a copy of the GNU General Public License
8609+ * along with this program; if not, write to the Free Software
8610+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8611+ */
8612+#include <linux/module.h>
8613+#include <linux/skbuff.h>
8614+#include <linux/ip.h>
8615+#include <net/checksum.h>
8616+
8617+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8618+MODULE_DESCRIPTION("IP tables CONNMARK matching module");
8619+MODULE_LICENSE("GPL");
8620+
8621+#include <linux/netfilter_ipv4/ip_tables.h>
8622+#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
8623+#include <linux/netfilter_ipv4/ip_conntrack.h>
8624+
8625+static unsigned int
8626+target(struct sk_buff **pskb,
8627+ const struct net_device *in,
8628+ const struct net_device *out,
8629+ unsigned int hooknum,
8630+ const void *targinfo,
8631+ void *userinfo)
8632+{
8633+ const struct ipt_connmark_target_info *markinfo = targinfo;
8634+ unsigned long diff;
8635+ unsigned long nfmark;
8636+ unsigned long newmark;
8637+
8638+ enum ip_conntrack_info ctinfo;
8639+ struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
8640+ if (ct) {
8641+ switch(markinfo->mode) {
8642+ case IPT_CONNMARK_SET:
8643+ newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
8644+ if (newmark != ct->mark)
8645+ ct->mark = newmark;
8646+ break;
8647+ case IPT_CONNMARK_SAVE:
8648+ newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
8649+ if (ct->mark != newmark)
8650+ ct->mark = newmark;
8651+ break;
8652+ case IPT_CONNMARK_RESTORE:
8653+ nfmark = (*pskb)->nfmark;
8654+ diff = (ct->mark ^ nfmark & markinfo->mask);
8655+ if (diff != 0) {
8656+ (*pskb)->nfmark = nfmark ^ diff;
8657+ (*pskb)->nfcache |= NFC_ALTERED;
8658+ }
8659+ break;
8660+ }
8661+ }
8662+
8663+ return IPT_CONTINUE;
8664+}
8665+
8666+static int
8667+checkentry(const char *tablename,
8668+ const struct ipt_entry *e,
8669+ void *targinfo,
8670+ unsigned int targinfosize,
8671+ unsigned int hook_mask)
8672+{
8673+ struct ipt_connmark_target_info *matchinfo = targinfo;
8674+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
8675+ printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
8676+ targinfosize,
8677+ IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
8678+ return 0;
8679+ }
8680+
8681+ if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
8682+ if (strcmp(tablename, "mangle") != 0) {
8683+ printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8684+ return 0;
8685+ }
8686+ }
8687+
8688+ return 1;
8689+}
8690+
8691+static struct ipt_target ipt_connmark_reg = {
8692+ .name = "CONNMARK",
8693+ .target = &target,
8694+ .checkentry = &checkentry,
8695+ .me = THIS_MODULE
8696+};
8697+
8698+static int __init init(void)
8699+{
8700+ return ipt_register_target(&ipt_connmark_reg);
8701+}
8702+
8703+static void __exit fini(void)
8704+{
8705+ ipt_unregister_target(&ipt_connmark_reg);
8706+}
8707+
8708+module_init(init);
8709+module_exit(fini);
8710diff -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
8711--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
8712+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c 2004-04-29 11:17:03.000000000 +0200
8713@@ -0,0 +1,81 @@
8714+/* This is a module which is used for setting the NFMARK field of an skb. */
8715+#include <linux/module.h>
8716+#include <linux/skbuff.h>
8717+#include <linux/ip.h>
8718+#include <net/checksum.h>
8719+
8720+#include <linux/netfilter_ipv4/ip_tables.h>
8721+#include <linux/netfilter_ipv4/ipt_IPMARK.h>
8722+
8723+MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
8724+MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
8725+MODULE_LICENSE("GPL");
8726+
8727+static unsigned int
8728+target(struct sk_buff **pskb,
8729+ const struct net_device *in,
8730+ const struct net_device *out,
8731+ unsigned int hooknum,
8732+ const void *targinfo,
8733+ void *userinfo)
8734+{
8735+ const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
8736+ struct iphdr *iph = (*pskb)->nh.iph;
8737+ unsigned long mark;
8738+
8739+ if (ipmarkinfo->addr == IPT_IPMARK_SRC)
8740+ mark = (unsigned long) ntohl(iph->saddr);
8741+ else
8742+ mark = (unsigned long) ntohl(iph->daddr);
8743+
8744+ mark &= ipmarkinfo->andmask;
8745+ mark |= ipmarkinfo->ormask;
8746+
8747+ if ((*pskb)->nfmark != mark) {
8748+ (*pskb)->nfmark = mark;
8749+ (*pskb)->nfcache |= NFC_ALTERED;
8750+ }
8751+ return IPT_CONTINUE;
8752+}
8753+
8754+static int
8755+checkentry(const char *tablename,
8756+ const struct ipt_entry *e,
8757+ void *targinfo,
8758+ unsigned int targinfosize,
8759+ unsigned int hook_mask)
8760+{
8761+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
8762+ printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
8763+ targinfosize,
8764+ IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
8765+ return 0;
8766+ }
8767+
8768+ if (strcmp(tablename, "mangle") != 0) {
8769+ printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8770+ return 0;
8771+ }
8772+
8773+ return 1;
8774+}
8775+
8776+static struct ipt_target ipt_ipmark_reg = {
8777+ .name = "IPMARK",
8778+ .target = target,
8779+ .checkentry = checkentry,
8780+ .me = THIS_MODULE
8781+};
8782+
8783+static int __init init(void)
8784+{
8785+ return ipt_register_target(&ipt_ipmark_reg);
8786+}
8787+
8788+static void __exit fini(void)
8789+{
8790+ ipt_unregister_target(&ipt_ipmark_reg);
8791+}
8792+
8793+module_init(init);
8794+module_exit(fini);
8795diff -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
8796--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
8797+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c 2004-04-29 11:17:08.000000000 +0200
8798@@ -0,0 +1,289 @@
8799+/*
8800+ * Kernel module to capture and hold incoming TCP connections using
8801+ * no local per-connection resources.
8802+ *
8803+ * Based on ipt_REJECT.c and offering functionality similar to
8804+ * LaBrea <http://www.hackbusters.net/LaBrea/>.
8805+ *
8806+ * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
8807+ *
8808+ * This program is free software; you can redistribute it and/or modify
8809+ * it under the terms of the GNU General Public License as published by
8810+ * the Free Software Foundation; either version 2 of the License, or
8811+ * (at your option) any later version.
8812+ *
8813+ * This program is distributed in the hope that it will be useful,
8814+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8815+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8816+ * GNU General Public License for more details.
8817+ *
8818+ * You should have received a copy of the GNU General Public License
8819+ * along with this program; if not, write to the Free Software
8820+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8821+ *
8822+ * Goal:
8823+ * - Allow incoming TCP connections to be established.
8824+ * - Passing data should result in the connection being switched to the
8825+ * persist state (0 byte window), in which the remote side stops sending
8826+ * data and asks to continue every 60 seconds.
8827+ * - Attempts to shut down the connection should be ignored completely, so
8828+ * the remote side ends up having to time it out.
8829+ *
8830+ * This means:
8831+ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
8832+ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
8833+ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
8834+ */
8835+
8836+#include <linux/config.h>
8837+#include <linux/module.h>
8838+#include <linux/skbuff.h>
8839+#include <linux/ip.h>
8840+#include <net/ip.h>
8841+#include <net/tcp.h>
8842+#include <net/icmp.h>
8843+struct in_device;
8844+#include <net/route.h>
8845+#include <linux/random.h>
8846+#include <linux/netfilter_ipv4/ip_tables.h>
8847+
8848+#if 0
8849+#define DEBUGP printk
8850+#else
8851+#define DEBUGP(format, args...)
8852+#endif
8853+
8854+MODULE_LICENSE("GPL");
8855+MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
8856+
8857+/* Stolen from ip_finish_output2 */
8858+static int ip_direct_send(struct sk_buff *skb)
8859+{
8860+ struct dst_entry *dst = skb->dst;
8861+ struct hh_cache *hh = dst->hh;
8862+
8863+ if (hh) {
8864+ read_lock_bh(&hh->hh_lock);
8865+ memcpy(skb->data - 16, hh->hh_data, 16);
8866+ read_unlock_bh(&hh->hh_lock);
8867+ skb_push(skb, hh->hh_len);
8868+ return hh->hh_output(skb);
8869+ } else if (dst->neighbour)
8870+ return dst->neighbour->output(skb);
8871+
8872+ if (net_ratelimit())
8873+ printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
8874+ kfree_skb(skb);
8875+ return -EINVAL;
8876+}
8877+
8878+
8879+/* Send reply */
8880+static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
8881+{
8882+ struct sk_buff *nskb;
8883+ struct rtable *nrt;
8884+ struct tcphdr *otcph, *ntcph;
8885+ unsigned int otcplen;
8886+ u_int16_t tmp;
8887+ struct flowi fl = {};
8888+
8889+ /* A truncated TCP header isn't going to be useful */
8890+ if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
8891+ return;
8892+
8893+ otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
8894+ + oskb->nh.iph->ihl);
8895+ otcplen = oskb->len - oskb->nh.iph->ihl*4;
8896+
8897+ /* No replies for RST or FIN */
8898+ if (otcph->rst || otcph->fin)
8899+ return;
8900+
8901+ /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
8902+ if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
8903+ return;
8904+
8905+ /* Check checksum. */
8906+ if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
8907+ oskb->nh.iph->daddr,
8908+ csum_partial((char *)otcph, otcplen, 0)) != 0)
8909+ return;
8910+
8911+ /* Copy skb (even if skb is about to be dropped, we can't just
8912+ clone it because there may be other things, such as tcpdump,
8913+ interested in it) */
8914+ nskb = skb_copy(oskb, GFP_ATOMIC);
8915+ if (!nskb)
8916+ return;
8917+
8918+ /* This packet will not be the same as the other: clear nf fields */
8919+ nf_conntrack_put(nskb->nfct);
8920+ nskb->nfct = NULL;
8921+ nskb->nfcache = 0;
8922+#ifdef CONFIG_NETFILTER_DEBUG
8923+ nskb->nf_debug = 0;
8924+#endif
8925+
8926+ ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
8927+
8928+ /* Truncate to length (no data) */
8929+ ntcph->doff = sizeof(struct tcphdr)/4;
8930+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
8931+ nskb->nh.iph->tot_len = htons(nskb->len);
8932+
8933+ /* Swap source and dest */
8934+ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
8935+ tmp = ntcph->source;
8936+ ntcph->source = ntcph->dest;
8937+ ntcph->dest = tmp;
8938+
8939+ /* Use supplied sequence number or make a new one */
8940+ ntcph->seq = otcph->ack ? otcph->ack_seq
8941+ : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
8942+ nskb->nh.iph->daddr,
8943+ ntcph->source,
8944+ ntcph->dest));
8945+
8946+ /* Our SYN-ACKs must have a >0 window */
8947+ ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
8948+
8949+ ntcph->urg_ptr = 0;
8950+
8951+ /* Reset flags */
8952+ ((u_int8_t *)ntcph)[13] = 0;
8953+
8954+ if (otcph->syn && otcph->ack) {
8955+ ntcph->rst = 1;
8956+ ntcph->ack_seq = 0;
8957+ } else {
8958+ ntcph->syn = otcph->syn;
8959+ ntcph->ack = 1;
8960+ ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
8961+ }
8962+
8963+ /* Adjust TCP checksum */
8964+ ntcph->check = 0;
8965+ ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
8966+ nskb->nh.iph->saddr,
8967+ nskb->nh.iph->daddr,
8968+ csum_partial((char *)ntcph,
8969+ sizeof(struct tcphdr), 0));
8970+
8971+ /* Adjust IP TTL */
8972+ nskb->nh.iph->ttl = sysctl_ip_default_ttl;
8973+
8974+ /* Set DF, id = 0 */
8975+ nskb->nh.iph->frag_off = htons(IP_DF);
8976+ nskb->nh.iph->id = 0;
8977+
8978+ /* Adjust IP checksum */
8979+ nskb->nh.iph->check = 0;
8980+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
8981+ nskb->nh.iph->ihl);
8982+
8983+ fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
8984+ fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
8985+ fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
8986+ fl.oif = 0;
8987+ if (ip_route_output_key(&nrt, &fl) != 0)
8988+ goto free_nskb;
8989+
8990+ dst_release(nskb->dst);
8991+ nskb->dst = &nrt->u.dst;
8992+
8993+ /* "Never happens" */
8994+ if (nskb->len > dst_pmtu(nskb->dst))
8995+ goto free_nskb;
8996+
8997+ ip_direct_send (nskb);
8998+
8999+ return;
9000+
9001+ free_nskb:
9002+ kfree_skb(nskb);
9003+}
9004+
9005+
9006+static unsigned int tarpit(struct sk_buff **pskb,
9007+ const struct net_device *in,
9008+ const struct net_device *out,
9009+ unsigned int hooknum,
9010+ const void *targinfo,
9011+ void *userinfo)
9012+{
9013+ struct sk_buff *skb = *pskb;
9014+ struct rtable *rt = (struct rtable*)skb->dst;
9015+
9016+ /* Do we have an input route cache entry? */
9017+ if (!rt)
9018+ return NF_DROP;
9019+
9020+ /* No replies to physical multicast/broadcast */
9021+ if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
9022+ return NF_DROP;
9023+
9024+ /* Now check at the protocol level */
9025+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
9026+ return NF_DROP;
9027+
9028+ /* Our naive response construction doesn't deal with IP
9029+ options, and probably shouldn't try. */
9030+ if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
9031+ return NF_DROP;
9032+
9033+ /* We aren't interested in fragments */
9034+ if (skb->nh.iph->frag_off & htons(IP_OFFSET))
9035+ return NF_DROP;
9036+
9037+ tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
9038+
9039+ return NF_DROP;
9040+}
9041+
9042+
9043+static int check(const char *tablename,
9044+ const struct ipt_entry *e,
9045+ void *targinfo,
9046+ unsigned int targinfosize,
9047+ unsigned int hook_mask)
9048+{
9049+ /* Only allow these for input/forward packet filtering. */
9050+ if (strcmp(tablename, "filter") != 0) {
9051+ DEBUGP("TARPIT: bad table %s'.\n", tablename);
9052+ return 0;
9053+ }
9054+ if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
9055+ | (1 << NF_IP_FORWARD))) != 0) {
9056+ DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
9057+ return 0;
9058+ }
9059+
9060+ /* Must specify that it's a TCP packet */
9061+ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
9062+ DEBUGP("TARPIT: not valid for non-tcp\n");
9063+ return 0;
9064+ }
9065+
9066+ return 1;
9067+}
9068+
9069+static struct ipt_target ipt_tarpit_reg = {
9070+ .name = "TARPIT",
9071+ .target = tarpit,
9072+ .checkentry = check,
9073+ .me = THIS_MODULE
9074+};
9075+
9076+static int __init init(void)
9077+{
9078+ return ipt_register_target(&ipt_tarpit_reg);
9079+}
9080+
9081+static void __exit fini(void)
9082+{
9083+ ipt_unregister_target(&ipt_tarpit_reg);
9084+}
9085+
9086+module_init(init);
9087+module_exit(fini);
9088diff -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
9089--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c 1970-01-01 01:00:00.000000000 +0100
9090+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c 2004-04-29 11:17:15.000000000 +0200
9091@@ -0,0 +1,64 @@
9092+/* This is a module which is used for setting
9093+ * the NFC_TRACE flag in the nfcache field of an skb.
9094+ */
9095+#include <linux/module.h>
9096+#include <linux/skbuff.h>
9097+
9098+#include <linux/netfilter_ipv4/ip_tables.h>
9099+
9100+static unsigned int
9101+target(struct sk_buff **pskb,
9102+ const struct net_device *in,
9103+ const struct net_device *out,
9104+ unsigned int hooknum,
9105+ const void *targinfo,
9106+ void *userinfo)
9107+{
9108+ (*pskb)->nfcache |= NFC_TRACE;
9109+ return IPT_CONTINUE;
9110+}
9111+
9112+static int
9113+checkentry(const char *tablename,
9114+ const struct ipt_entry *e,
9115+ void *targinfo,
9116+ unsigned int targinfosize,
9117+ unsigned int hook_mask)
9118+{
9119+ if (targinfosize != 0) {
9120+ printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
9121+ targinfosize);
9122+ return 0;
9123+ }
9124+
9125+ if (strcmp(tablename, "raw") != 0) {
9126+ printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
9127+ return 0;
9128+ }
9129+
9130+ return 1;
9131+}
9132+
9133+static struct ipt_target ipt_trace_reg = {
9134+ .name = "TRACE",
9135+ .target = target,
9136+ .checkentry = checkentry,
9137+ .me = THIS_MODULE
9138+};
9139+
9140+static int __init init(void)
9141+{
9142+ if (ipt_register_target(&ipt_trace_reg))
9143+ return -EINVAL;
9144+
9145+ return 0;
9146+}
9147+
9148+static void __exit fini(void)
9149+{
9150+ ipt_unregister_target(&ipt_trace_reg);
9151+}
9152+
9153+module_init(init);
9154+module_exit(fini);
9155+MODULE_LICENSE("GPL");
9156diff -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
9157--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
9158+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c 2004-04-29 11:17:18.000000000 +0200
9159@@ -0,0 +1,117 @@
9160+/* XOR target for IP tables
9161+ * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9162+ * Based on ipt_TTL.c
9163+ *
9164+ * Version 1.0
9165+ *
9166+ * This software is distributed under the terms of GNU GPL
9167+ */
9168+
9169+#include <linux/module.h>
9170+#include <linux/skbuff.h>
9171+#include <linux/ip.h>
9172+#include <linux/tcp.h>
9173+#include <linux/udp.h>
9174+
9175+#include <linux/netfilter_ipv4/ip_tables.h>
9176+#include <linux/netfilter_ipv4/ipt_XOR.h>
9177+
9178+MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9179+MODULE_DESCRIPTION("IP tables XOR module");
9180+MODULE_LICENSE("GPL");
9181+
9182+static unsigned int
9183+ipt_xor_target(struct sk_buff **pskb,
9184+ const struct net_device *in, const struct net_device *out,
9185+ unsigned int hooknum, const void *targinfo, void *userinfo)
9186+{
9187+ struct ipt_XOR_info *info = (void *) targinfo;
9188+ struct iphdr *iph;
9189+ struct tcphdr *tcph;
9190+ struct udphdr *udph;
9191+ int i, j, k;
9192+
9193+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
9194+ return NF_DROP;
9195+
9196+ iph = (*pskb)->nh.iph;
9197+
9198+ if (iph->protocol == IPPROTO_TCP) {
9199+ tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9200+ for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9201+ for (k=0; k<=info->block_size; k++) {
9202+ (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
9203+ info->key[j];
9204+ i++;
9205+ }
9206+ j++;
9207+ if (info->key[j] == 0x00)
9208+ j = 0;
9209+ }
9210+ } else if (iph->protocol == IPPROTO_UDP) {
9211+ udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9212+ for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9213+ for (k=0; k<=info->block_size; k++) {
9214+ (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
9215+ info->key[j];
9216+ i++;
9217+ }
9218+ j++;
9219+ if (info->key[j] == 0x00)
9220+ j = 0;
9221+ }
9222+ }
9223+
9224+ return IPT_CONTINUE;
9225+}
9226+
9227+static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9228+ void *targinfo, unsigned int targinfosize,
9229+ unsigned int hook_mask)
9230+{
9231+ struct ipt_XOR_info *info = targinfo;
9232+
9233+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9234+ printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
9235+ targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9236+ return 0;
9237+ }
9238+
9239+ if (strcmp(tablename, "mangle")) {
9240+ printk(KERN_WARNING "XOR: can only be called from"
9241+ "\"mangle\" table, not \"%s\"\n", tablename);
9242+ return 0;
9243+ }
9244+
9245+ if (!strcmp(info->key, "")) {
9246+ printk(KERN_WARNING "XOR: You must specify a key");
9247+ return 0;
9248+ }
9249+
9250+ if (info->block_size == 0) {
9251+ printk(KERN_WARNING "XOR: You must specify a block-size");
9252+ return 0;
9253+ }
9254+
9255+ return 1;
9256+}
9257+
9258+static struct ipt_target ipt_XOR = {
9259+ .name = "XOR",
9260+ .target = ipt_xor_target,
9261+ .checkentry = ipt_xor_checkentry,
9262+ .me = THIS_MODULE,
9263+};
9264+
9265+static int __init init(void)
9266+{
9267+ return ipt_register_target(&ipt_XOR);
9268+}
9269+
9270+static void __exit fini(void)
9271+{
9272+ ipt_unregister_target(&ipt_XOR);
9273+}
9274+
9275+module_init(init);
9276+module_exit(fini);
9277diff -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
9278--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
9279+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c 2004-04-29 11:17:23.000000000 +0200
9280@@ -0,0 +1,68 @@
9281+/*
9282+ * iptables module to match inet_addr_type() of an ip.
9283+ */
9284+
9285+#include <linux/module.h>
9286+#include <linux/skbuff.h>
9287+#include <linux/netdevice.h>
9288+#include <net/route.h>
9289+
9290+#include <linux/netfilter_ipv4/ipt_addrtype.h>
9291+#include <linux/netfilter_ipv4/ip_tables.h>
9292+
9293+MODULE_LICENSE("GPL");
9294+
9295+static inline int match_type(u_int32_t addr, u_int16_t mask)
9296+{
9297+ return !!(mask & (1 << inet_addr_type(addr)));
9298+}
9299+
9300+static int match(const struct sk_buff *skb, const struct net_device *in,
9301+ const struct net_device *out, const void *matchinfo,
9302+ int offset, int *hotdrop)
9303+{
9304+ const struct ipt_addrtype_info *info = matchinfo;
9305+ const struct iphdr *iph = skb->nh.iph;
9306+ int ret = 1;
9307+
9308+ if (info->source)
9309+ ret &= match_type(iph->saddr, info->source)^info->invert_source;
9310+ if (info->dest)
9311+ ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9312+
9313+ return ret;
9314+}
9315+
9316+static int checkentry(const char *tablename, const struct ipt_ip *ip,
9317+ void *matchinfo, unsigned int matchsize,
9318+ unsigned int hook_mask)
9319+{
9320+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9321+ printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9322+ matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9323+ return 0;
9324+ }
9325+
9326+ return 1;
9327+}
9328+
9329+static struct ipt_match addrtype_match = {
9330+ .name = "addrtype",
9331+ .match = match,
9332+ .checkentry = checkentry,
9333+ .me = THIS_MODULE
9334+};
9335+
9336+static int __init init(void)
9337+{
9338+ return ipt_register_match(&addrtype_match);
9339+}
9340+
9341+static void __exit fini(void)
9342+{
9343+ ipt_unregister_match(&addrtype_match);
9344+
9345+}
9346+
9347+module_init(init);
9348+module_exit(fini);
9349diff -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
9350--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
9351+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c 2004-04-29 11:10:59.000000000 +0200
9352@@ -0,0 +1,81 @@
9353+/* This kernel module matches connection mark values set by the
9354+ * CONNMARK target
9355+ *
9356+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9357+ * by Henrik Nordstrom <hno@marasystems.com>
9358+ *
9359+ * This program is free software; you can redistribute it and/or modify
9360+ * it under the terms of the GNU General Public License as published by
9361+ * the Free Software Foundation; either version 2 of the License, or
9362+ * (at your option) any later version.
9363+ *
9364+ * This program is distributed in the hope that it will be useful,
9365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9367+ * GNU General Public License for more details.
9368+ *
9369+ * You should have received a copy of the GNU General Public License
9370+ * along with this program; if not, write to the Free Software
9371+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9372+ */
9373+
9374+#include <linux/module.h>
9375+#include <linux/skbuff.h>
9376+
9377+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9378+MODULE_DESCRIPTION("IP tables connmark match module");
9379+MODULE_LICENSE("GPL");
9380+
9381+#include <linux/netfilter_ipv4/ip_tables.h>
9382+#include <linux/netfilter_ipv4/ipt_connmark.h>
9383+#include <linux/netfilter_ipv4/ip_conntrack.h>
9384+
9385+static int
9386+match(const struct sk_buff *skb,
9387+ const struct net_device *in,
9388+ const struct net_device *out,
9389+ const void *matchinfo,
9390+ int offset,
9391+ int *hotdrop)
9392+{
9393+ const struct ipt_connmark_info *info = matchinfo;
9394+ enum ip_conntrack_info ctinfo;
9395+ struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
9396+ if (!ct)
9397+ return 0;
9398+
9399+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
9400+}
9401+
9402+static int
9403+checkentry(const char *tablename,
9404+ const struct ipt_ip *ip,
9405+ void *matchinfo,
9406+ unsigned int matchsize,
9407+ unsigned int hook_mask)
9408+{
9409+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
9410+ return 0;
9411+
9412+ return 1;
9413+}
9414+
9415+static struct ipt_match connmark_match = {
9416+ .name = "connmark",
9417+ .match = &match,
9418+ .checkentry = &checkentry,
9419+ .me = THIS_MODULE
9420+};
9421+
9422+static int __init init(void)
9423+{
9424+ return ipt_register_match(&connmark_match);
9425+}
9426+
9427+static void __exit fini(void)
9428+{
9429+ ipt_unregister_match(&connmark_match);
9430+}
9431+
9432+module_init(init);
9433+module_exit(fini);
9434diff -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
9435--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-04-29 11:24:39.000000000 +0200
9436+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c 2004-04-29 11:18:37.000000000 +0200
9437@@ -71,8 +71,11 @@
9438 DEBUGP("master's name = %s , info->name = %s\n",
9439 exp->expectant->helper->name, info->name);
9440
9441- ret ^= !strncmp(exp->expectant->helper->name, info->name,
9442- strlen(exp->expectant->helper->name));
9443+ if (info->name[0] == '\0')
9444+ ret ^= 1;
9445+ else
9446+ ret ^= !strncmp(exp->expectant->helper->name, info->name,
9447+ strlen(exp->expectant->helper->name));
9448 out_unlock:
9449 READ_UNLOCK(&ip_conntrack_lock);
9450 return ret;
9451@@ -92,10 +95,6 @@
9452 if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
9453 return 0;
9454
9455- /* verify that we actually should match anything */
9456- if ( strlen(info->name) == 0 )
9457- return 0;
9458-
9459 return 1;
9460 }
9461
9462diff -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
9463--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c 2004-04-28 03:36:37.000000000 +0200
9464+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c 2004-04-29 11:19:32.000000000 +0200
9465@@ -6,12 +6,19 @@
9466 * This program is free software; you can redistribute it and/or modify
9467 * it under the terms of the GNU General Public License version 2 as
9468 * published by the Free Software Foundation.
9469+ *
9470+ * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
9471 */
9472
9473 #include <linux/module.h>
9474 #include <linux/skbuff.h>
9475 #include <linux/file.h>
9476+#include <linux/ip.h>
9477+#include <linux/tcp.h>
9478+#include <linux/udp.h>
9479 #include <net/sock.h>
9480+#include <net/tcp.h>
9481+#include <net/udp.h>
9482
9483 #include <linux/netfilter_ipv4/ipt_owner.h>
9484 #include <linux/netfilter_ipv4/ip_tables.h>
9485@@ -21,7 +28,7 @@
9486 MODULE_DESCRIPTION("iptables owner match");
9487
9488 static int
9489-match_comm(const struct sk_buff *skb, const char *comm)
9490+match_comm(const struct sock *sk, const char *comm)
9491 {
9492 struct task_struct *g, *p;
9493 struct files_struct *files;
9494@@ -38,7 +45,7 @@
9495 spin_lock(&files->file_lock);
9496 for (i=0; i < files->max_fds; i++) {
9497 if (fcheck_files(files, i) ==
9498- skb->sk->sk_socket->file) {
9499+ sk->sk_socket->file) {
9500 spin_unlock(&files->file_lock);
9501 task_unlock(p);
9502 read_unlock(&tasklist_lock);
9503@@ -54,7 +61,7 @@
9504 }
9505
9506 static int
9507-match_pid(const struct sk_buff *skb, pid_t pid)
9508+match_pid(const struct sock *sk, pid_t pid)
9509 {
9510 struct task_struct *p;
9511 struct files_struct *files;
9512@@ -70,7 +77,7 @@
9513 spin_lock(&files->file_lock);
9514 for (i=0; i < files->max_fds; i++) {
9515 if (fcheck_files(files, i) ==
9516- skb->sk->sk_socket->file) {
9517+ sk->sk_socket->file) {
9518 spin_unlock(&files->file_lock);
9519 task_unlock(p);
9520 read_unlock(&tasklist_lock);
9521@@ -86,10 +93,10 @@
9522 }
9523
9524 static int
9525-match_sid(const struct sk_buff *skb, pid_t sid)
9526+match_sid(const struct sock *sk, pid_t sid)
9527 {
9528 struct task_struct *g, *p;
9529- struct file *file = skb->sk->sk_socket->file;
9530+ struct file *file = sk->sk_socket->file;
9531 int i, found=0;
9532
9533 read_lock(&tasklist_lock);
9534@@ -129,41 +136,71 @@
9535 int *hotdrop)
9536 {
9537 const struct ipt_owner_info *info = matchinfo;
9538+ struct iphdr *iph = skb->nh.iph;
9539+ struct sock *sk = NULL;
9540+ int ret = 0;
9541+
9542+ if (out) {
9543+ sk = skb->sk;
9544+ } else {
9545+ if (iph->protocol == IPPROTO_TCP) {
9546+ struct tcphdr *tcph =
9547+ (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
9548+ sk = tcp_v4_lookup(iph->saddr, tcph->source,
9549+ iph->daddr, tcph->dest,
9550+ skb->dev->ifindex);
9551+ if (sk && sk->sk_state == TCP_TIME_WAIT) {
9552+ tcp_tw_put((struct tcp_tw_bucket *)sk);
9553+ return ret;
9554+ }
9555+ } else if (iph->protocol == IPPROTO_UDP) {
9556+ struct udphdr *udph =
9557+ (struct udphdr *)((u_int32_t *)iph + iph->ihl);
9558+ sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
9559+ udph->dest, skb->dev->ifindex);
9560+ }
9561+ }
9562
9563- if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
9564- return 0;
9565+ if (!sk || !sk->sk_socket || !sk->sk_socket->file)
9566+ goto out;
9567
9568 if(info->match & IPT_OWNER_UID) {
9569- if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
9570+ if ((sk->sk_socket->file->f_uid != info->uid) ^
9571 !!(info->invert & IPT_OWNER_UID))
9572- return 0;
9573+ goto out;
9574 }
9575
9576 if(info->match & IPT_OWNER_GID) {
9577- if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
9578+ if ((sk->sk_socket->file->f_gid != info->gid) ^
9579 !!(info->invert & IPT_OWNER_GID))
9580- return 0;
9581+ goto out;
9582 }
9583
9584 if(info->match & IPT_OWNER_PID) {
9585- if (!match_pid(skb, info->pid) ^
9586+ if (!match_pid(sk, info->pid) ^
9587 !!(info->invert & IPT_OWNER_PID))
9588- return 0;
9589+ goto out;
9590 }
9591
9592 if(info->match & IPT_OWNER_SID) {
9593- if (!match_sid(skb, info->sid) ^
9594+ if (!match_sid(sk, info->sid) ^
9595 !!(info->invert & IPT_OWNER_SID))
9596- return 0;
9597+ goto out;
9598 }
9599
9600 if(info->match & IPT_OWNER_COMM) {
9601- if (!match_comm(skb, info->comm) ^
9602+ if (!match_comm(sk, info->comm) ^
9603 !!(info->invert & IPT_OWNER_COMM))
9604- return 0;
9605+ goto out;
9606 }
9607
9608- return 1;
9609+ ret = 1;
9610+
9611+out:
9612+ if (in && sk)
9613+ sock_put(sk);
9614+
9615+ return ret;
9616 }
9617
9618 static int
9619@@ -173,11 +210,19 @@
9620 unsigned int matchsize,
9621 unsigned int hook_mask)
9622 {
9623- if (hook_mask
9624- & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
9625- printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
9626- return 0;
9627- }
9628+ if (hook_mask
9629+ & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
9630+ (1 << NF_IP_LOCAL_IN))) {
9631+ printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
9632+ "or POST_ROUTING.\n");
9633+ return 0;
9634+ }
9635+
9636+ if ((hook_mask & (1 << NF_IP_LOCAL_IN))
9637+ && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
9638+ printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
9639+ return 0;
9640+ }
9641
9642 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
9643 printk("Matchsize %u != %Zu\n", matchsize,
9644diff -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
9645--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
9646+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c 2004-04-29 11:19:41.000000000 +0200
9647@@ -0,0 +1,176 @@
9648+/* IP tables module for matching IPsec policy
9649+ *
9650+ * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
9651+ *
9652+ * This program is free software; you can redistribute it and/or modify
9653+ * it under the terms of the GNU General Public License version 2 as
9654+ * published by the Free Software Foundation.
9655+ */
9656+
9657+#include <linux/kernel.h>
9658+#include <linux/config.h>
9659+#include <linux/module.h>
9660+#include <linux/skbuff.h>
9661+#include <linux/init.h>
9662+#include <net/xfrm.h>
9663+
9664+#include <linux/netfilter_ipv4.h>
9665+#include <linux/netfilter_ipv4/ipt_policy.h>
9666+#include <linux/netfilter_ipv4/ip_tables.h>
9667+
9668+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
9669+MODULE_DESCRIPTION("IPtables IPsec policy matching module");
9670+MODULE_LICENSE("GPL");
9671+
9672+
9673+static inline int
9674+match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
9675+{
9676+#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
9677+
9678+ if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
9679+ MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
9680+ MISMATCH(proto, x->id.proto) ||
9681+ MISMATCH(mode, x->props.mode) ||
9682+ MISMATCH(spi, x->id.spi) ||
9683+ MISMATCH(reqid, x->props.reqid))
9684+ return 0;
9685+ return 1;
9686+}
9687+
9688+static int
9689+match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
9690+{
9691+ const struct ipt_policy_elem *e;
9692+ struct sec_path *sp = skb->sp;
9693+ int strict = info->flags & POLICY_MATCH_STRICT;
9694+ int i, pos;
9695+
9696+ if (sp == NULL)
9697+ return -1;
9698+ if (strict && info->len != sp->len)
9699+ return 0;
9700+
9701+ for (i = sp->len - 1; i >= 0; i--) {
9702+ pos = strict ? i - sp->len + 1 : 0;
9703+ if (pos >= info->len)
9704+ return 0;
9705+ e = &info->pol[pos];
9706+
9707+ if (match_xfrm_state(sp->x[i].xvec, e)) {
9708+ if (!strict)
9709+ return 1;
9710+ } else if (strict)
9711+ return 0;
9712+ }
9713+
9714+ return strict ? 1 : 0;
9715+}
9716+
9717+static int
9718+match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
9719+{
9720+ const struct ipt_policy_elem *e;
9721+ struct dst_entry *dst = skb->dst;
9722+ int strict = info->flags & POLICY_MATCH_STRICT;
9723+ int i, pos;
9724+
9725+ if (dst->xfrm == NULL)
9726+ return -1;
9727+
9728+ for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
9729+ pos = strict ? i : 0;
9730+ if (pos >= info->len)
9731+ return 0;
9732+ e = &info->pol[pos];
9733+
9734+ if (match_xfrm_state(dst->xfrm, e)) {
9735+ if (!strict)
9736+ return 1;
9737+ } else if (strict)
9738+ return 0;
9739+ }
9740+
9741+ return strict ? 1 : 0;
9742+}
9743+
9744+static int match(const struct sk_buff *skb,
9745+ const struct net_device *in,
9746+ const struct net_device *out,
9747+ const void *matchinfo, int offset, int *hotdrop)
9748+{
9749+ const struct ipt_policy_info *info = matchinfo;
9750+ int ret;
9751+
9752+ if (info->flags & POLICY_MATCH_IN)
9753+ ret = match_policy_in(skb, info);
9754+ else
9755+ ret = match_policy_out(skb, info);
9756+
9757+ if (ret < 0) {
9758+ if (info->flags & POLICY_MATCH_NONE)
9759+ ret = 1;
9760+ else
9761+ ret = 0;
9762+ } else if (info->flags & POLICY_MATCH_NONE)
9763+ ret = 0;
9764+
9765+ return ret;
9766+}
9767+
9768+static int checkentry(const char *tablename, const struct ipt_ip *ip,
9769+ void *matchinfo, unsigned int matchsize,
9770+ unsigned int hook_mask)
9771+{
9772+ struct ipt_policy_info *info = matchinfo;
9773+
9774+ if (matchsize != IPT_ALIGN(sizeof(*info))) {
9775+ printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
9776+ matchsize, IPT_ALIGN(sizeof(*info)));
9777+ return 0;
9778+ }
9779+ if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
9780+ printk(KERN_ERR "ipt_policy: neither incoming nor "
9781+ "outgoing policy selected\n");
9782+ return 0;
9783+ }
9784+ if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
9785+ && info->flags & POLICY_MATCH_OUT) {
9786+ printk(KERN_ERR "ipt_policy: output policy not valid in "
9787+ "PRE_ROUTING and INPUT\n");
9788+ return 0;
9789+ }
9790+ if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
9791+ && info->flags & POLICY_MATCH_IN) {
9792+ printk(KERN_ERR "ipt_policy: input policy not valid in "
9793+ "POST_ROUTING and OUTPUT\n");
9794+ return 0;
9795+ }
9796+ if (info->len > POLICY_MAX_ELEM) {
9797+ printk(KERN_ERR "ipt_policy: too many policy elements\n");
9798+ return 0;
9799+ }
9800+
9801+ return 1;
9802+}
9803+
9804+static struct ipt_match policy_match =
9805+{
9806+ .name = "policy",
9807+ .match = match,
9808+ .checkentry = checkentry,
9809+ .me = THIS_MODULE,
9810+};
9811+
9812+static int __init init(void)
9813+{
9814+ return ipt_register_match(&policy_match);
9815+}
9816+
9817+static void __exit fini(void)
9818+{
9819+ ipt_unregister_match(&policy_match);
9820+}
9821+
9822+module_init(init);
9823+module_exit(fini);
9824diff -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
9825--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
9826+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_rpc.c 2004-04-29 11:20:02.000000000 +0200
9827@@ -0,0 +1,428 @@
9828+/* RPC extension for IP connection matching, Version 2.2
9829+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
9830+ * - original rpc tracking module
9831+ * - "recent" connection handling for kernel 2.3+ netfilter
9832+ *
9833+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
9834+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
9835+ *
9836+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
9837+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
9838+ * - extended matching to support filtering on procedures
9839+ *
9840+ * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
9841+ *
9842+ * This program is free software; you can redistribute it and/or
9843+ * modify it under the terms of the GNU General Public License
9844+ * as published by the Free Software Foundation; either version
9845+ * 2 of the License, or (at your option) any later version.
9846+ **
9847+ * Module load syntax:
9848+ * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
9849+ *
9850+ * Please give the ports of all RPC servers you wish to connect to.
9851+ * If you don't specify ports, the default will be port 111.
9852+ **
9853+ * Note to all:
9854+ *
9855+ * RPCs should not be exposed to the internet - ask the Pentagon;
9856+ *
9857+ * "The unidentified crackers pleaded guilty in July to charges
9858+ * of juvenile delinquency stemming from a string of Pentagon
9859+ * network intrusions in February.
9860+ *
9861+ * The youths, going by the names TooShort and Makaveli, used
9862+ * a common server security hole to break in, according to
9863+ * Dane Jasper, owner of the California Internet service
9864+ * provider, Sonic. They used the hole, known as the 'statd'
9865+ * exploit, to attempt more than 800 break-ins, Jasper said."
9866+ *
9867+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
9868+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
9869+ **
9870+ */
9871+
9872+#include <linux/module.h>
9873+#include <linux/skbuff.h>
9874+#include <linux/list.h>
9875+#include <linux/udp.h>
9876+#include <linux/tcp.h>
9877+#include <linux/netfilter_ipv4/ip_conntrack.h>
9878+#include <linux/netfilter_ipv4/ip_tables.h>
9879+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
9880+#include <linux/netfilter_ipv4/lockhelp.h>
9881+#include <linux/netfilter_ipv4/ipt_rpc.h>
9882+
9883+#define MAX_PORTS 8
9884+static int ports[MAX_PORTS];
9885+static int ports_n_c = 0;
9886+
9887+#ifdef MODULE_PARM
9888+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9889+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
9890+#endif
9891+
9892+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
9893+MODULE_DESCRIPTION("RPC connection matching module");
9894+MODULE_LICENSE("GPL");
9895+
9896+#if 0
9897+#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
9898+ format, ## args)
9899+#else
9900+#define DEBUGP(format, args...)
9901+#endif
9902+
9903+EXPORT_NO_SYMBOLS;
9904+
9905+/* vars from ip_conntrack_rpc_tcp */
9906+extern struct list_head request_p_list_tcp;
9907+extern struct module *ip_conntrack_rpc_tcp;
9908+
9909+/* vars from ip_conntrack_rpc_udp */
9910+extern struct list_head request_p_list_udp;
9911+extern struct module *ip_conntrack_rpc_udp;
9912+
9913+DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
9914+DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
9915+
9916+#define ASSERT_READ_LOCK(x) \
9917+do { \
9918+ if (x == &request_p_list_udp) \
9919+ MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
9920+ else if (x == &request_p_list_tcp) \
9921+ MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
9922+} while (0)
9923+
9924+#define ASSERT_WRITE_LOCK(x) \
9925+do { \
9926+ if (x == &request_p_list_udp) \
9927+ MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
9928+ else if (x == &request_p_list_tcp) \
9929+ MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
9930+} while (0)
9931+
9932+#include <linux/netfilter_ipv4/listhelp.h>
9933+
9934+const int IPT_RPC_CHAR_LEN = 11;
9935+
9936+
9937+static int k_atoi(char *string)
9938+{
9939+ unsigned int result = 0;
9940+ int maxoctet = IPT_RPC_CHAR_LEN;
9941+
9942+ for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
9943+ if (*string < 0)
9944+ return(0);
9945+ if (*string == 0)
9946+ break;
9947+ if (*string < 48 || *string > 57) {
9948+ return(0);
9949+ }
9950+ result = result * 10 + ( *string - 48 );
9951+ }
9952+ return(result);
9953+}
9954+
9955+
9956+static int match_rpcs(char *c_procs, int i_procs, int proc)
9957+{
9958+ int proc_ctr;
9959+ char *proc_ptr;
9960+ unsigned int proc_num;
9961+
9962+ DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
9963+
9964+ if (i_procs == -1)
9965+ return 1;
9966+
9967+ for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
9968+
9969+ proc_ptr = c_procs;
9970+ proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
9971+ proc_num = k_atoi(proc_ptr);
9972+
9973+ if (proc_num == proc)
9974+ return 1;
9975+ }
9976+
9977+ return 0;
9978+}
9979+
9980+
9981+static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
9982+ int *hotdrop, int dir, struct ip_conntrack *ct,
9983+ int offset, struct list_head request_p_list)
9984+{
9985+ const struct ipt_rpc_info *rpcinfo = matchinfo;
9986+ struct request_p *req_p;
9987+ u_int32_t xid;
9988+
9989+
9990+ /* Get XID */
9991+ xid = *data;
9992+
9993+ /* This does sanity checking on RPC payloads,
9994+ * and permits only the RPC "get port" (3)
9995+ * in authorised procedures in client
9996+ * communications with the portmapper.
9997+ */
9998+
9999+ data += 5;
10000+
10001+ /* Get RPC requestor */
10002+ if (IXDR_GET_INT32(data) != 3) {
10003+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
10004+ if(rpcinfo->strict == 1)
10005+ *hotdrop = 1;
10006+ return 0;
10007+ }
10008+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
10009+
10010+ data++;
10011+
10012+ /* Jump Credentials and Verfifier */
10013+ data = data + IXDR_GET_INT32(data) + 2;
10014+ data = data + IXDR_GET_INT32(data) + 2;
10015+
10016+ /* Get RPC procedure */
10017+ if (match_rpcs((char *)&rpcinfo->c_procs,
10018+ rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
10019+ DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
10020+ (unsigned int)IXDR_GET_INT32(data));
10021+
10022+ /* If the RPC conntrack half entry already exists .. */
10023+
10024+ switch (ct->tuplehash[0].tuple.dst.protonum) {
10025+ case IPPROTO_UDP:
10026+ WRITE_LOCK(&ipct_rpc_udp_lock);
10027+ case IPPROTO_TCP:
10028+ WRITE_LOCK(&ipct_rpc_tcp_lock);
10029+ }
10030+ req_p = LIST_FIND(&request_p_list, request_p_cmp,
10031+ struct request_p *, xid,
10032+ ct->tuplehash[dir].tuple.src.ip,
10033+ ct->tuplehash[dir].tuple.src.u.all);
10034+
10035+ if (req_p) {
10036+ DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10037+ xid, ct->tuplehash[dir].tuple.dst.protonum,
10038+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10039+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
10040+
10041+ /* .. remove it */
10042+ if (del_timer(&req_p->timeout))
10043+ req_p->timeout.expires = 0;
10044+
10045+ LIST_DELETE(&request_p_list, req_p);
10046+ DEBUGP("RPC req_p removed. [done]\n");
10047+
10048+ } else {
10049+ DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10050+ xid, ct->tuplehash[dir].tuple.dst.protonum,
10051+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10052+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
10053+
10054+ }
10055+ switch (ct->tuplehash[0].tuple.dst.protonum) {
10056+ case IPPROTO_UDP:
10057+ WRITE_UNLOCK(&ipct_rpc_udp_lock);
10058+ case IPPROTO_TCP:
10059+ WRITE_UNLOCK(&ipct_rpc_tcp_lock);
10060+ }
10061+
10062+ if(rpcinfo->strict == 1)
10063+ *hotdrop = 1;
10064+ return 0;
10065+ }
10066+
10067+ DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
10068+ (unsigned int)IXDR_GET_INT32(data));
10069+ return (1 && (!offset));
10070+}
10071+
10072+
10073+static int match(const struct sk_buff *skb, const struct net_device *in,
10074+ const struct net_device *out, const void *matchinfo,
10075+ int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
10076+{
10077+ struct ip_conntrack *ct;
10078+ enum ip_conntrack_info ctinfo;
10079+ const u_int32_t *data;
10080+ enum ip_conntrack_dir dir;
10081+ const struct tcphdr *tcp;
10082+ const struct ipt_rpc_info *rpcinfo = matchinfo;
10083+ int port, portsok;
10084+ int tval;
10085+
10086+
10087+ DEBUGP("new packet to evaluate ..\n");
10088+
10089+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10090+ if (!ct) {
10091+ DEBUGP("no ct available [skip]\n");
10092+ return 0;
10093+ }
10094+
10095+ DEBUGP("ct detected. [cont]\n");
10096+ dir = CTINFO2DIR(ctinfo);
10097+
10098+ /* we only want the client to server packets for matching */
10099+ if (dir != IP_CT_DIR_ORIGINAL)
10100+ return 0;
10101+
10102+ /* This does sanity checking on UDP or TCP packets,
10103+ * like their respective modules.
10104+ */
10105+
10106+ switch (ct->tuplehash[0].tuple.dst.protonum) {
10107+
10108+ case IPPROTO_UDP:
10109+ DEBUGP("PROTO_UDP [cont]\n");
10110+ if (offset == 0 && datalen < sizeof(struct udphdr)) {
10111+ DEBUGP("packet does not contain a complete header. [drop]\n");
10112+ return 0;
10113+ }
10114+
10115+ for (port=0,portsok=0; port <= ports_n_c; port++) {
10116+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10117+ portsok++;
10118+ break;
10119+ }
10120+ }
10121+ if (portsok == 0) {
10122+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10123+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10124+ return 0;
10125+ }
10126+
10127+ if ((datalen - sizeof(struct udphdr)) != 56) {
10128+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
10129+ if (rpcinfo->strict == 1)
10130+ *hotdrop = 1;
10131+ return 0;
10132+ }
10133+ DEBUGP("packet length is correct. [cont]\n");
10134+
10135+ /* Get to the data */
10136+ data = (const u_int32_t *)hdr + 2;
10137+
10138+ /* Check the RPC data */
10139+ tval = check_rpc_packet(data, matchinfo, hotdrop,
10140+ dir, ct, offset,
10141+ request_p_list_udp);
10142+
10143+ return tval;
10144+
10145+
10146+ case IPPROTO_TCP:
10147+ DEBUGP("PROTO_TCP [cont]\n");
10148+ if (offset == 0 && datalen < sizeof(struct tcphdr)) {
10149+ DEBUGP("packet does not contain a complete header. [drop]\n");
10150+ return 0;
10151+ }
10152+
10153+ for (port=0,portsok=0; port <= ports_n_c; port++) {
10154+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10155+ portsok++;
10156+ break;
10157+ }
10158+ }
10159+ if (portsok == 0) {
10160+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10161+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10162+ return 0;
10163+ }
10164+
10165+ tcp = hdr;
10166+ if (datalen == (tcp->doff * 4)) {
10167+ DEBUGP("packet does not contain any data. [match]\n");
10168+ return (1 && (!offset));
10169+ }
10170+
10171+ /* Tests if packet len is ok */
10172+ if ((datalen - (tcp->doff * 4)) != 60) {
10173+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
10174+ if(rpcinfo->strict == 1)
10175+ *hotdrop = 1;
10176+ return 0;
10177+ }
10178+ DEBUGP("packet length is correct. [cont]\n");
10179+
10180+ /* Get to the data */
10181+ data = (const u_int32_t *)tcp + tcp->doff + 1;
10182+
10183+ /* Check the RPC data */
10184+ tval = check_rpc_packet(data, matchinfo, hotdrop,
10185+ dir, ct, offset,
10186+ request_p_list_tcp);
10187+
10188+ return tval;
10189+
10190+ }
10191+
10192+ DEBUGP("transport protocol=%u, is not supported [skip]\n",
10193+ ct->tuplehash[0].tuple.dst.protonum);
10194+ return 0;
10195+}
10196+
10197+
10198+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
10199+ unsigned int matchsize, unsigned int hook_mask)
10200+{
10201+ if (hook_mask
10202+ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
10203+ | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
10204+ printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
10205+ return 0;
10206+ }
10207+
10208+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
10209+ return 0;
10210+
10211+ return 1;
10212+}
10213+
10214+
10215+static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
10216+ &match, &checkentry, NULL,
10217+ THIS_MODULE };
10218+
10219+
10220+static int __init init(void)
10221+{
10222+ int port;
10223+
10224+ DEBUGP("incrementing usage counts\n");
10225+ __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
10226+ __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
10227+
10228+ /* If no port given, default to standard RPC port */
10229+ if (ports[0] == 0)
10230+ ports[0] = RPC_PORT;
10231+
10232+ DEBUGP("registering match [%s] for;\n", rpc_match.name);
10233+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
10234+ DEBUGP(" port %i (UDP|TCP);\n", ports[port]);
10235+ ports_n_c++;
10236+ }
10237+
10238+ return ipt_register_match(&rpc_match);
10239+}
10240+
10241+
10242+static void fini(void)
10243+{
10244+ DEBUGP("unregistering match\n");
10245+ ipt_unregister_match(&rpc_match);
10246+
10247+ DEBUGP("decrementing usage counts\n");
10248+ __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
10249+ __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
10250+}
10251+
10252+
10253+module_init(init);
10254+module_exit(fini);
10255+
10256diff -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
10257--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
10258+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c 2004-04-29 11:21:38.000000000 +0200
10259@@ -0,0 +1,183 @@
10260+/* Kernel module to match a string into a packet.
10261+ *
10262+ * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
10263+ *
10264+ * ChangeLog
10265+ * 24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
10266+ * Initial 2.6 port
10267+ * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
10268+ * Fixed SMP re-entrancy problem using per-cpu data areas
10269+ * for the skip/shift tables.
10270+ * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10271+ * Fixed kernel panic, due to overrunning boyer moore string
10272+ * tables. Also slightly tweaked heuristic for deciding what
10273+ * search algo to use.
10274+ * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10275+ * Implemented Boyer Moore Sublinear search algorithm
10276+ * alongside the existing linear search based on memcmp().
10277+ * Also a quick check to decide which method to use on a per
10278+ * packet basis.
10279+ */
10280+
10281+#include <linux/smp.h>
10282+#include <linux/percpu.h>
10283+#include <linux/module.h>
10284+#include <linux/skbuff.h>
10285+#include <linux/file.h>
10286+#include <net/sock.h>
10287+
10288+#include <linux/netfilter_ipv4/ip_tables.h>
10289+#include <linux/netfilter_ipv4/ipt_string.h>
10290+
10291+MODULE_LICENSE("GPL");
10292+
10293+struct string_per_cpu {
10294+ int skip[BM_MAX_HLEN];
10295+ int shift[BM_MAX_HLEN];
10296+ int len[BM_MAX_HLEN];
10297+};
10298+
10299+static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
10300+
10301+
10302+/* Boyer Moore Sublinear string search - VERY FAST */
10303+char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
10304+{
10305+ int M1, right_end, sk, sh;
10306+ int ended, j, i;
10307+
10308+ int *skip, *shift, *len;
10309+
10310+ /* use data suitable for this CPU */
10311+ shift=__get_cpu_var(bm_string_data).shift;
10312+ skip=__get_cpu_var(bm_string_data).skip;
10313+ len=__get_cpu_var(bm_string_data).len;
10314+
10315+ /* Setup skip/shift tables */
10316+ M1 = right_end = needle_len-1;
10317+ for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
10318+ for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
10319+
10320+ for (i = 1; i < needle_len; i++) {
10321+ for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
10322+ len[i] = j;
10323+ }
10324+
10325+ shift[0] = 1;
10326+ for (i = 1; i < needle_len; i++) shift[i] = needle_len;
10327+ for (i = M1; i > 0; i--) shift[len[i]] = i;
10328+ ended = 0;
10329+
10330+ for (i = 0; i < needle_len; i++) {
10331+ if (len[i] == M1 - i) ended = i;
10332+ if (ended) shift[i] = ended;
10333+ }
10334+
10335+ /* Do the search*/
10336+ while (right_end < haystack_len)
10337+ {
10338+ for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
10339+ if (i == needle_len) {
10340+ return haystack+(right_end - M1);
10341+ }
10342+
10343+ sk = skip[(int)haystack[right_end - i]];
10344+ sh = shift[i];
10345+ right_end = max(right_end - i + sk, right_end + sh);
10346+ }
10347+
10348+ return NULL;
10349+}
10350+
10351+/* Linear string search based on memcmp() */
10352+char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
10353+{
10354+ char *k = haystack + (haystack_len-needle_len);
10355+ char *t = haystack;
10356+
10357+ while ( t <= k ) {
10358+ if (memcmp(t, needle, needle_len) == 0)
10359+ return t;
10360+ t++;
10361+ }
10362+
10363+ return NULL;
10364+}
10365+
10366+static int
10367+match(const struct sk_buff *skb,
10368+ const struct net_device *in,
10369+ const struct net_device *out,
10370+ const void *matchinfo,
10371+ int offset,
10372+ int *hotdrop)
10373+{
10374+ const struct ipt_string_info *info = matchinfo;
10375+ struct iphdr *ip = skb->nh.iph;
10376+ int hlen, nlen;
10377+ char *needle, *haystack;
10378+ proc_ipt_search search=search_linear;
10379+
10380+ if ( !ip ) return 0;
10381+
10382+ /* get lenghts, and validate them */
10383+ nlen=info->len;
10384+ hlen=ntohs(ip->tot_len)-(ip->ihl*4);
10385+ if ( nlen > hlen ) return 0;
10386+
10387+ needle=(char *)&info->string;
10388+ haystack=(char *)ip+(ip->ihl*4);
10389+
10390+ /* The sublinear search comes in to its own
10391+ * on the larger packets */
10392+ if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
10393+ (nlen>IPT_STRING_NEEDLE_THRESH) ) {
10394+ if ( hlen < BM_MAX_HLEN ) {
10395+ search=search_sublinear;
10396+ }else{
10397+ if (net_ratelimit())
10398+ printk(KERN_INFO "ipt_string: Packet too big "
10399+ "to attempt sublinear string search "
10400+ "(%d bytes)\n", hlen );
10401+ }
10402+ }
10403+
10404+ return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
10405+}
10406+
10407+static int
10408+checkentry(const char *tablename,
10409+ const struct ipt_ip *ip,
10410+ void *matchinfo,
10411+ unsigned int matchsize,
10412+ unsigned int hook_mask)
10413+{
10414+
10415+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
10416+ return 0;
10417+
10418+ return 1;
10419+}
10420+
10421+static struct ipt_match string_match = {
10422+ .name = "string",
10423+ .match = &match,
10424+ .checkentry = &checkentry,
10425+ .me = THIS_MODULE
10426+};
10427+
10428+
10429+static int __init init(void)
10430+{
10431+ return ipt_register_match(&string_match);
10432+}
10433+
10434+static void __exit fini(void)
10435+{
10436+ ipt_unregister_match(&string_match);
10437+}
10438+
10439+module_init(init);
10440+module_exit(fini);
10441+
10442+
10443diff -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
10444--- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
10445+++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c 2004-04-29 11:21:33.000000000 +0200
10446@@ -0,0 +1,604 @@
10447+/* Kernel module to match suspect packets. */
10448+#include <linux/module.h>
10449+#include <linux/skbuff.h>
10450+#include <linux/ip.h>
10451+#include <linux/udp.h>
10452+#include <linux/tcp.h>
10453+#include <linux/icmp.h>
10454+#include <net/checksum.h>
10455+
10456+#include <linux/netfilter_ipv4/ip_tables.h>
10457+
10458+#define limpk(format, args...) \
10459+do { \
10460+ if (net_ratelimit()) \
10461+ printk("ipt_unclean: %s" format, \
10462+ embedded ? "(embedded packet) " : "" , ## args); \
10463+} while(0)
10464+
10465+enum icmp_error_status
10466+{
10467+ ICMP_MAY_BE_ERROR,
10468+ ICMP_IS_ERROR,
10469+ ICMP_NOT_ERROR
10470+};
10471+
10472+struct icmp_info
10473+{
10474+ size_t min_len, max_len;
10475+ enum icmp_error_status err;
10476+ u_int8_t min_code, max_code;
10477+};
10478+
10479+static int
10480+check_ip(struct iphdr *iph, size_t length, int embedded);
10481+
10482+/* ICMP-specific checks. */
10483+static int
10484+check_icmp(const struct icmphdr *icmph,
10485+ u_int16_t datalen,
10486+ unsigned int offset,
10487+ int more_frags,
10488+ int embedded)
10489+{
10490+ static struct icmp_info info[]
10491+ = { [ICMP_ECHOREPLY]
10492+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10493+ [ICMP_DEST_UNREACH]
10494+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
10495+ [ICMP_SOURCE_QUENCH]
10496+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
10497+ [ICMP_REDIRECT]
10498+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
10499+ [ICMP_ECHO]
10500+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10501+ /* Router advertisement. */
10502+ [9]
10503+ = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
10504+ /* Router solicitation. */
10505+ [10]
10506+ = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
10507+ [ICMP_TIME_EXCEEDED]
10508+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
10509+ [ICMP_PARAMETERPROB]
10510+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
10511+ [ICMP_TIMESTAMP]
10512+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10513+ [ICMP_TIMESTAMPREPLY]
10514+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10515+ [ICMP_INFO_REQUEST]
10516+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10517+ [ICMP_INFO_REPLY]
10518+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10519+ [ICMP_ADDRESS]
10520+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
10521+ [ICMP_ADDRESSREPLY]
10522+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
10523+
10524+ /* Can't do anything if it's a fragment. */
10525+ if (offset)
10526+ return 1;
10527+
10528+ /* Must cover type and code. */
10529+ if (datalen < 2) {
10530+ limpk("ICMP len=%u too short\n", datalen);
10531+ return 0;
10532+ }
10533+
10534+ /* If not embedded. */
10535+ if (!embedded) {
10536+ /* Bad checksum? Don't print, just ignore. */
10537+ if (!more_frags
10538+ && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
10539+ return 0;
10540+
10541+ /* CHECK: Truncated ICMP (even if first fragment). */
10542+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10543+ && info[icmph->type].min_len != 0
10544+ && datalen < info[icmph->type].min_len) {
10545+ limpk("ICMP type %u len %u too short\n",
10546+ icmph->type, datalen);
10547+ return 0;
10548+ }
10549+
10550+ /* CHECK: Check within known error ICMPs. */
10551+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10552+ && info[icmph->type].err == ICMP_IS_ERROR) {
10553+ /* CHECK: Embedded packet must be at least
10554+ length of iph + 8 bytes. */
10555+ struct iphdr *inner = (void *)icmph + 8;
10556+
10557+ /* datalen > 8 since all ICMP_IS_ERROR types
10558+ have min length > 8 */
10559+ if (datalen - 8 < sizeof(struct iphdr)) {
10560+ limpk("ICMP error internal way too short\n");
10561+ return 0;
10562+ }
10563+ if (datalen - 8 < inner->ihl*4 + 8) {
10564+ limpk("ICMP error internal too short\n");
10565+ return 0;
10566+ }
10567+ if (!check_ip(inner, datalen - 8, 1))
10568+ return 0;
10569+ }
10570+ } else {
10571+ /* CHECK: Can't embed ICMP unless known non-error. */
10572+ if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
10573+ || info[icmph->type].err != ICMP_NOT_ERROR) {
10574+ limpk("ICMP type %u not embeddable\n",
10575+ icmph->type);
10576+ return 0;
10577+ }
10578+ }
10579+
10580+ /* CHECK: Invalid ICMP codes. */
10581+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10582+ && (icmph->code < info[icmph->type].min_code
10583+ || icmph->code > info[icmph->type].max_code)) {
10584+ limpk("ICMP type=%u code=%u\n",
10585+ icmph->type, icmph->code);
10586+ return 0;
10587+ }
10588+
10589+ /* CHECK: Above maximum length. */
10590+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10591+ && info[icmph->type].max_len != 0
10592+ && datalen > info[icmph->type].max_len) {
10593+ limpk("ICMP type=%u too long: %u bytes\n",
10594+ icmph->type, datalen);
10595+ return 0;
10596+ }
10597+
10598+ switch (icmph->type) {
10599+ case ICMP_PARAMETERPROB: {
10600+ /* CHECK: Problem param must be within error packet's
10601+ * IP header. */
10602+ struct iphdr *iph = (void *)icmph + 8;
10603+ u_int32_t arg = ntohl(icmph->un.gateway);
10604+
10605+ if (icmph->code == 0) {
10606+ /* Code 0 means that upper 8 bits is pointer
10607+ to problem. */
10608+ if ((arg >> 24) >= iph->ihl*4) {
10609+ limpk("ICMP PARAMETERPROB ptr = %u\n",
10610+ ntohl(icmph->un.gateway) >> 24);
10611+ return 0;
10612+ }
10613+ arg &= 0x00FFFFFF;
10614+ }
10615+
10616+ /* CHECK: Rest must be zero. */
10617+ if (arg) {
10618+ limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
10619+ arg);
10620+ return 0;
10621+ }
10622+ break;
10623+ }
10624+
10625+ case ICMP_TIME_EXCEEDED:
10626+ case ICMP_SOURCE_QUENCH:
10627+ /* CHECK: Unused must be zero. */
10628+ if (icmph->un.gateway != 0) {
10629+ limpk("ICMP type=%u unused = %u\n",
10630+ icmph->type, ntohl(icmph->un.gateway));
10631+ return 0;
10632+ }
10633+ break;
10634+ }
10635+
10636+ return 1;
10637+}
10638+
10639+/* UDP-specific checks. */
10640+static int
10641+check_udp(const struct iphdr *iph,
10642+ const struct udphdr *udph,
10643+ u_int16_t datalen,
10644+ unsigned int offset,
10645+ int more_frags,
10646+ int embedded)
10647+{
10648+ /* Can't do anything if it's a fragment. */
10649+ if (offset)
10650+ return 1;
10651+
10652+ /* CHECK: Must cover UDP header. */
10653+ if (datalen < sizeof(struct udphdr)) {
10654+ limpk("UDP len=%u too short\n", datalen);
10655+ return 0;
10656+ }
10657+
10658+ /* Bad checksum? Don't print, just say it's unclean. */
10659+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
10660+ if (!more_frags && !embedded && udph->check
10661+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
10662+ csum_partial((char *)udph, datalen, 0)) != 0)
10663+ return 0;
10664+
10665+ /* CHECK: Destination port can't be zero. */
10666+ if (!udph->dest) {
10667+ limpk("UDP zero destination port\n");
10668+ return 0;
10669+ }
10670+
10671+ if (!more_frags) {
10672+ if (!embedded) {
10673+ /* CHECK: UDP length must match. */
10674+ if (ntohs(udph->len) != datalen) {
10675+ limpk("UDP len too short %u vs %u\n",
10676+ ntohs(udph->len), datalen);
10677+ return 0;
10678+ }
10679+ } else {
10680+ /* CHECK: UDP length be >= this truncated pkt. */
10681+ if (ntohs(udph->len) < datalen) {
10682+ limpk("UDP len too long %u vs %u\n",
10683+ ntohs(udph->len), datalen);
10684+ return 0;
10685+ }
10686+ }
10687+ } else {
10688+ /* CHECK: UDP length must be > this frag's length. */
10689+ if (ntohs(udph->len) <= datalen) {
10690+ limpk("UDP fragment len too short %u vs %u\n",
10691+ ntohs(udph->len), datalen);
10692+ return 0;
10693+ }
10694+ }
10695+
10696+ return 1;
10697+}
10698+
10699+#define TH_FIN 0x01
10700+#define TH_SYN 0x02
10701+#define TH_RST 0x04
10702+#define TH_PUSH 0x08
10703+#define TH_ACK 0x10
10704+#define TH_URG 0x20
10705+#define TH_ECE 0x40
10706+#define TH_CWR 0x80
10707+
10708+/* table of valid flag combinations - ECE and CWR are always valid */
10709+static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
10710+{
10711+ [TH_SYN] = 1,
10712+ [TH_SYN|TH_ACK] = 1,
10713+ [TH_RST] = 1,
10714+ [TH_RST|TH_ACK] = 1,
10715+ [TH_RST|TH_ACK|TH_PUSH] = 1,
10716+ [TH_FIN|TH_ACK] = 1,
10717+ [TH_ACK] = 1,
10718+ [TH_ACK|TH_PUSH] = 1,
10719+ [TH_ACK|TH_URG] = 1,
10720+ [TH_ACK|TH_URG|TH_PUSH] = 1,
10721+ [TH_FIN|TH_ACK|TH_PUSH] = 1,
10722+ [TH_FIN|TH_ACK|TH_URG] = 1,
10723+ [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
10724+};
10725+
10726+/* TCP-specific checks. */
10727+static int
10728+check_tcp(const struct iphdr *iph,
10729+ const struct tcphdr *tcph,
10730+ u_int16_t datalen,
10731+ unsigned int offset,
10732+ int more_frags,
10733+ int embedded)
10734+{
10735+ u_int8_t *opt = (u_int8_t *)tcph;
10736+ u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
10737+ u_int8_t tcpflags;
10738+ int end_of_options = 0;
10739+ size_t i;
10740+
10741+ /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
10742+ /* In fact, this is caught below (offset < 516). */
10743+
10744+ /* Can't do anything if it's a fragment. */
10745+ if (offset)
10746+ return 1;
10747+
10748+ /* CHECK: Smaller than minimal TCP hdr. */
10749+ if (datalen < sizeof(struct tcphdr)) {
10750+ if (!embedded) {
10751+ limpk("Packet length %u < TCP header.\n", datalen);
10752+ return 0;
10753+ }
10754+ /* Must have ports available (datalen >= 8), from
10755+ check_icmp which set embedded = 1 */
10756+ /* CHECK: TCP ports inside ICMP error */
10757+ if (!tcph->source || !tcph->dest) {
10758+ limpk("Zero TCP ports %u/%u.\n",
10759+ htons(tcph->source), htons(tcph->dest));
10760+ return 0;
10761+ }
10762+ return 1;
10763+ }
10764+
10765+ /* CHECK: Smaller than actual TCP hdr. */
10766+ if (datalen < tcph->doff * 4) {
10767+ if (!embedded) {
10768+ limpk("Packet length %u < actual TCP header.\n",
10769+ datalen);
10770+ return 0;
10771+ } else
10772+ return 1;
10773+ }
10774+
10775+ /* Bad checksum? Don't print, just say it's unclean. */
10776+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
10777+ if (!more_frags && !embedded
10778+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
10779+ csum_partial((char *)tcph, datalen, 0)) != 0)
10780+ return 0;
10781+
10782+ /* CHECK: TCP ports non-zero */
10783+ if (!tcph->source || !tcph->dest) {
10784+ limpk("Zero TCP ports %u/%u.\n",
10785+ htons(tcph->source), htons(tcph->dest));
10786+ return 0;
10787+ }
10788+
10789+ /* CHECK: TCP reserved bits zero. */
10790+ if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
10791+ limpk("TCP reserved bits not zero\n");
10792+ return 0;
10793+ }
10794+
10795+ /* CHECK: TCP flags. */
10796+ tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
10797+ if (!tcp_valid_flags[tcpflags]) {
10798+ limpk("TCP flags bad: %u\n", tcpflags);
10799+ return 0;
10800+ }
10801+
10802+ for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
10803+ switch (opt[i]) {
10804+ case 0:
10805+ end_of_options = 1;
10806+ i++;
10807+ break;
10808+ case 1:
10809+ i++;
10810+ break;
10811+ default:
10812+ /* CHECK: options after EOO. */
10813+ if (end_of_options) {
10814+ limpk("TCP option %u after end\n",
10815+ opt[i]);
10816+ return 0;
10817+ }
10818+ /* CHECK: options at tail. */
10819+ else if (i+1 >= tcph->doff * 4) {
10820+ limpk("TCP option %u at tail\n",
10821+ opt[i]);
10822+ return 0;
10823+ }
10824+ /* CHECK: zero-length options. */
10825+ else if (opt[i+1] == 0) {
10826+ limpk("TCP option %u 0 len\n",
10827+ opt[i]);
10828+ return 0;
10829+ }
10830+ /* CHECK: oversize options. */
10831+ else if (&opt[i] + opt[i+1] > endhdr) {
10832+ limpk("TCP option %u at %Zu too long\n",
10833+ (unsigned int) opt[i], i);
10834+ return 0;
10835+ }
10836+ /* Move to next option */
10837+ i += opt[i+1];
10838+ }
10839+ }
10840+
10841+ return 1;
10842+}
10843+
10844+/* Returns 1 if ok */
10845+/* Standard IP checks. */
10846+static int
10847+check_ip(struct iphdr *iph, size_t length, int embedded)
10848+{
10849+ u_int8_t *opt = (u_int8_t *)iph;
10850+ u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
10851+ int end_of_options = 0;
10852+ void *protoh;
10853+ size_t datalen;
10854+ unsigned int i;
10855+ unsigned int offset;
10856+
10857+ /* Should only happen for local outgoing raw-socket packets. */
10858+ /* CHECK: length >= ip header. */
10859+ if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
10860+ limpk("Packet length %Zu < IP header.\n", length);
10861+ return 0;
10862+ }
10863+
10864+ offset = ntohs(iph->frag_off) & IP_OFFSET;
10865+ protoh = (void *)iph + iph->ihl * 4;
10866+ datalen = length - iph->ihl * 4;
10867+
10868+ /* CHECK: Embedded fragment. */
10869+ if (embedded && offset) {
10870+ limpk("Embedded fragment.\n");
10871+ return 0;
10872+ }
10873+
10874+ for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
10875+ switch (opt[i]) {
10876+ case 0:
10877+ end_of_options = 1;
10878+ i++;
10879+ break;
10880+ case 1:
10881+ i++;
10882+ break;
10883+ default:
10884+ /* CHECK: options after EOO. */
10885+ if (end_of_options) {
10886+ limpk("IP option %u after end\n",
10887+ opt[i]);
10888+ return 0;
10889+ }
10890+ /* CHECK: options at tail. */
10891+ else if (i+1 >= iph->ihl * 4) {
10892+ limpk("IP option %u at tail\n",
10893+ opt[i]);
10894+ return 0;
10895+ }
10896+ /* CHECK: zero-length or one-length options. */
10897+ else if (opt[i+1] < 2) {
10898+ limpk("IP option %u %u len\n",
10899+ opt[i], opt[i+1]);
10900+ return 0;
10901+ }
10902+ /* CHECK: oversize options. */
10903+ else if (&opt[i] + opt[i+1] > endhdr) {
10904+ limpk("IP option %u at %u too long\n",
10905+ opt[i], i);
10906+ return 0;
10907+ }
10908+ /* Move to next option */
10909+ i += opt[i+1];
10910+ }
10911+ }
10912+
10913+ /* Fragment checks. */
10914+
10915+ /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
10916+ if ((ntohs(iph->frag_off) & IP_MF)
10917+ && (ntohs(iph->tot_len) % 8) != 0) {
10918+ limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
10919+ return 0;
10920+ }
10921+
10922+ /* CHECK: Oversize fragment a-la Ping of Death. */
10923+ if (offset * 8 + datalen > 65535) {
10924+ limpk("Oversize fragment to %u.\n", offset * 8);
10925+ return 0;
10926+ }
10927+
10928+ /* CHECK: DF set and offset or MF set. */
10929+ if ((ntohs(iph->frag_off) & IP_DF)
10930+ && (offset || (ntohs(iph->frag_off) & IP_MF))) {
10931+ limpk("DF set and offset=%u, MF=%u.\n",
10932+ offset, ntohs(iph->frag_off) & IP_MF);
10933+ return 0;
10934+ }
10935+
10936+ /* CHECK: Zero-sized fragments. */
10937+ if ((offset || (ntohs(iph->frag_off) & IP_MF))
10938+ && datalen == 0) {
10939+ limpk("Zero size fragment offset=%u\n", offset);
10940+ return 0;
10941+ }
10942+
10943+ /* Note: we can have even middle fragments smaller than this:
10944+ consider a large packet passing through a 600MTU then
10945+ 576MTU link: this gives a fragment of 24 data bytes. But
10946+ everyone packs fragments largest first, hence a fragment
10947+ can't START before 576 - MAX_IP_HEADER_LEN. */
10948+
10949+ /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
10950+ down to 128 (576 taken from RFC 791: All hosts must be
10951+ prepared to accept datagrams of up to 576 octets). Use 128
10952+ here. */
10953+#define MIN_LIKELY_MTU 128
10954+ /* CHECK: Min size of first frag = 128. */
10955+ if ((ntohs(iph->frag_off) & IP_MF)
10956+ && offset == 0
10957+ && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
10958+ limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
10959+ MIN_LIKELY_MTU);
10960+ return 0;
10961+ }
10962+
10963+ /* CHECK: Min offset of frag = 128 - IP hdr len. */
10964+ if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
10965+ limpk("Fragment starts at %u < %u\n", offset * 8,
10966+ MIN_LIKELY_MTU - iph->ihl * 4);
10967+ return 0;
10968+ }
10969+
10970+ /* CHECK: Protocol specification non-zero. */
10971+ if (iph->protocol == 0) {
10972+ limpk("Zero protocol\n");
10973+ return 0;
10974+ }
10975+
10976+ /* CHECK: Do not use what is unused.
10977+ * First bit of fragmentation flags should be unused.
10978+ * May be used by OS fingerprinting tools.
10979+ * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
10980+ */
10981+ if (ntohs(iph->frag_off)>>15) {
10982+ limpk("IP unused bit set\n");
10983+ return 0;
10984+ }
10985+
10986+ /* Per-protocol checks. */
10987+ switch (iph->protocol) {
10988+ case IPPROTO_ICMP:
10989+ return check_icmp(protoh, datalen, offset,
10990+ (ntohs(iph->frag_off) & IP_MF),
10991+ embedded);
10992+
10993+ case IPPROTO_UDP:
10994+ return check_udp(iph, protoh, datalen, offset,
10995+ (ntohs(iph->frag_off) & IP_MF),
10996+ embedded);
10997+
10998+ case IPPROTO_TCP:
10999+ return check_tcp(iph, protoh, datalen, offset,
11000+ (ntohs(iph->frag_off) & IP_MF),
11001+ embedded);
11002+ default:
11003+ /* Ignorance is bliss. */
11004+ return 1;
11005+ }
11006+}
11007+
11008+static int
11009+match(const struct sk_buff *skb,
11010+ const struct net_device *in,
11011+ const struct net_device *out,
11012+ const void *matchinfo,
11013+ int offset,
11014+ const void *hdr,
11015+ u_int16_t datalen,
11016+ int *hotdrop)
11017+{
11018+ return !check_ip(skb->nh.iph, skb->len, 0);
11019+}
11020+
11021+/* Called when user tries to insert an entry of this type. */
11022+static int
11023+checkentry(const char *tablename,
11024+ const struct ipt_ip *ip,
11025+ void *matchinfo,
11026+ unsigned int matchsize,
11027+ unsigned int hook_mask)
11028+{
11029+ if (matchsize != IPT_ALIGN(0))
11030+ return 0;
11031+
11032+ return 1;
11033+}
11034+
11035+static struct ipt_match unclean_match
11036+= { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
11037+
11038+static int __init init(void)
11039+{
11040+ return ipt_register_match(&unclean_match);
11041+}
11042+
11043+static void __exit fini(void)
11044+{
11045+ ipt_unregister_match(&unclean_match);
11046+}
11047+
11048+module_init(init);
11049+module_exit(fini);
11050+MODULE_LICENSE("GPL");
11051diff -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
11052--- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c 2004-04-28 03:35:43.000000000 +0200
11053+++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c 2004-04-29 11:17:15.000000000 +0200
11054@@ -59,7 +59,7 @@
11055 0,
11056 sizeof(struct ipt_entry),
11057 sizeof(struct ipt_standard),
11058- 0, { 0, 0 }, { } },
11059+ 0, NULL, 0, { 0, 0 }, { } },
11060 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11061 -NF_ACCEPT - 1 } },
11062 /* FORWARD */
11063@@ -67,7 +67,7 @@
11064 0,
11065 sizeof(struct ipt_entry),
11066 sizeof(struct ipt_standard),
11067- 0, { 0, 0 }, { } },
11068+ 0, NULL, 0, { 0, 0 }, { } },
11069 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11070 -NF_ACCEPT - 1 } },
11071 /* LOCAL_OUT */
11072@@ -75,7 +75,7 @@
11073 0,
11074 sizeof(struct ipt_entry),
11075 sizeof(struct ipt_standard),
11076- 0, { 0, 0 }, { } },
11077+ 0, NULL, 0, { 0, 0 }, { } },
11078 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11079 -NF_ACCEPT - 1 } }
11080 },
11081@@ -84,7 +84,7 @@
11082 0,
11083 sizeof(struct ipt_entry),
11084 sizeof(struct ipt_error),
11085- 0, { 0, 0 }, { } },
11086+ 0, NULL, 0, { 0, 0 }, { } },
11087 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11088 { } },
11089 "ERROR"
11090diff -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
11091--- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c 2004-04-28 03:36:34.000000000 +0200
11092+++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-04-29 11:17:15.000000000 +0200
11093@@ -74,7 +74,7 @@
11094 0,
11095 sizeof(struct ipt_entry),
11096 sizeof(struct ipt_standard),
11097- 0, { 0, 0 }, { } },
11098+ 0, NULL, 0, { 0, 0 }, { } },
11099 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11100 -NF_ACCEPT - 1 } },
11101 /* LOCAL_IN */
11102@@ -82,7 +82,7 @@
11103 0,
11104 sizeof(struct ipt_entry),
11105 sizeof(struct ipt_standard),
11106- 0, { 0, 0 }, { } },
11107+ 0, NULL, 0, { 0, 0 }, { } },
11108 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11109 -NF_ACCEPT - 1 } },
11110 /* FORWARD */
11111@@ -90,7 +90,7 @@
11112 0,
11113 sizeof(struct ipt_entry),
11114 sizeof(struct ipt_standard),
11115- 0, { 0, 0 }, { } },
11116+ 0, NULL, 0, { 0, 0 }, { } },
11117 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11118 -NF_ACCEPT - 1 } },
11119 /* LOCAL_OUT */
11120@@ -98,7 +98,7 @@
11121 0,
11122 sizeof(struct ipt_entry),
11123 sizeof(struct ipt_standard),
11124- 0, { 0, 0 }, { } },
11125+ 0, NULL, 0, { 0, 0 }, { } },
11126 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11127 -NF_ACCEPT - 1 } },
11128 /* POST_ROUTING */
11129@@ -106,7 +106,7 @@
11130 0,
11131 sizeof(struct ipt_entry),
11132 sizeof(struct ipt_standard),
11133- 0, { 0, 0 }, { } },
11134+ 0, NULL, 0, { 0, 0 }, { } },
11135 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11136 -NF_ACCEPT - 1 } },
11137 },
11138@@ -115,7 +115,7 @@
11139 0,
11140 sizeof(struct ipt_entry),
11141 sizeof(struct ipt_error),
11142- 0, { 0, 0 }, { } },
11143+ 0, NULL, 0, { 0, 0 }, { } },
11144 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11145 { } },
11146 "ERROR"
11147diff -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
11148--- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c 2004-04-28 03:36:36.000000000 +0200
11149+++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c 2004-04-29 11:17:15.000000000 +0200
11150@@ -46,7 +46,7 @@
11151 0,
11152 sizeof(struct ipt_entry),
11153 sizeof(struct ipt_standard),
11154- 0, { 0, 0 }, { } },
11155+ 0, NULL, 0, { 0, 0 }, { } },
11156 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11157 -NF_ACCEPT - 1 } },
11158 /* LOCAL_OUT */
11159@@ -54,7 +54,7 @@
11160 0,
11161 sizeof(struct ipt_entry),
11162 sizeof(struct ipt_standard),
11163- 0, { 0, 0 }, { } },
11164+ 0, NULL, 0, { 0, 0 }, { } },
11165 { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11166 -NF_ACCEPT - 1 } }
11167 },
11168@@ -63,7 +63,7 @@
11169 0,
11170 sizeof(struct ipt_entry),
11171 sizeof(struct ipt_error),
11172- 0, { 0, 0 }, { } },
11173+ 0, NULL, 0, { 0, 0 }, { } },
11174 { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11175 { } },
11176 "ERROR"
11177diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/raw.c linux-2.6.6-rc3/net/ipv4/raw.c
11178--- linux-2.6.6-rc3.org/net/ipv4/raw.c 2004-04-28 03:35:49.000000000 +0200
11179+++ linux-2.6.6-rc3/net/ipv4/raw.c 2004-04-29 11:18:06.000000000 +0200
11180@@ -249,6 +249,7 @@
11181 kfree_skb(skb);
11182 return NET_RX_DROP;
11183 }
11184+ nf_reset(skb);
11185
11186 skb_push(skb, skb->data - skb->nh.raw);
11187
11188@@ -307,7 +308,7 @@
11189 }
11190
11191 err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
11192- dst_output);
11193+ ip_dst_output);
11194 if (err > 0)
11195 err = inet->recverr ? net_xmit_errno(err) : 0;
11196 if (err)
11197diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c
11198--- linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c 2004-04-28 03:35:40.000000000 +0200
11199+++ linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c 2004-04-29 11:19:32.000000000 +0200
11200@@ -1785,6 +1785,7 @@
11201
11202 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
11203 goto discard_and_relse;
11204+ nf_reset(skb);
11205
11206 if (sk_filter(sk, skb, 0))
11207 goto discard_and_relse;
11208@@ -2670,6 +2671,7 @@
11209 EXPORT_SYMBOL(tcp_v4_connect);
11210 EXPORT_SYMBOL(tcp_v4_do_rcv);
11211 EXPORT_SYMBOL(tcp_v4_lookup_listener);
11212+EXPORT_SYMBOL(tcp_v4_lookup);
11213 EXPORT_SYMBOL(tcp_v4_rebuild_header);
11214 EXPORT_SYMBOL(tcp_v4_remember_stamp);
11215 EXPORT_SYMBOL(tcp_v4_send_check);
11216diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/udp.c linux-2.6.6-rc3/net/ipv4/udp.c
11217--- linux-2.6.6-rc3.org/net/ipv4/udp.c 2004-04-28 03:35:19.000000000 +0200
11218+++ linux-2.6.6-rc3/net/ipv4/udp.c 2004-04-29 11:19:32.000000000 +0200
11219@@ -1045,6 +1045,7 @@
11220 kfree_skb(skb);
11221 return -1;
11222 }
11223+ nf_reset(skb);
11224
11225 if (up->encap_type) {
11226 /*
11227@@ -1210,6 +1211,7 @@
11228
11229 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
11230 goto drop;
11231+ nf_reset(skb);
11232
11233 /* No socket. Drop packet silently, if checksum is wrong */
11234 if (udp_checksum_complete(skb))
11235@@ -1558,6 +1560,7 @@
11236 EXPORT_SYMBOL(udp_port_rover);
11237 EXPORT_SYMBOL(udp_prot);
11238 EXPORT_SYMBOL(udp_sendmsg);
11239+EXPORT_SYMBOL(udp_v4_lookup);
11240
11241 #ifdef CONFIG_PROC_FS
11242 EXPORT_SYMBOL(udp_proc_register);
11243diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c
11244--- linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-04-28 03:35:08.000000000 +0200
11245+++ linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c 2004-04-29 11:18:03.000000000 +0200
11246@@ -76,6 +76,7 @@
11247 err = -EHOSTUNREACH;
11248 goto error_nolock;
11249 }
11250+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
11251 return NET_XMIT_BYPASS;
11252
11253 error_nolock:
11254@@ -170,6 +171,7 @@
11255 .handler = ipip_rcv,
11256 .err_handler = ipip_err,
11257 .no_policy = 1,
11258+ .xfrm_prot = 1,
11259 };
11260
11261 static int __init ipip_init(void)
11262diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig
11263--- linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig 2004-04-29 11:24:39.000000000 +0200
11264+++ linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig 2004-04-29 11:19:41.000000000 +0200
11265@@ -255,5 +255,29 @@
11266 depends on IP6_NF_IPTABLES
11267 help
11268
11269+config IP6_NF_TARGET_TRACE
11270+ tristate 'TRACE target support'
11271+ depends on IP6_NF_RAW
11272+ help
11273+ The TRACE target allows packets to be traced as those
11274+ matches any subsequent rule in any table/rule. The matched
11275+ rule and the packet is logged with the prefix
11276+
11277+ TRACE: tablename/chainname/rulenum
11278+
11279+ If you want to compile it as a module, say M here and read
11280+ <file:Documentation/modules.txt>. If unsure, say `N'.
11281+ help
11282+
11283+config IP6_NF_MATCH_POLICY
11284+ tristate "IPsec policy match support"
11285+ depends on IP6_NF_IPTABLES && XFRM
11286+ help
11287+ Policy matching allows you to match packets based on the
11288+ IPsec policy that was used during decapsulation/will
11289+ be used during encapsulation.
11290+
11291+ To compile it as a module, choose M here. If unsure, say N.
11292+
11293 endmenu
11294
11295diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc3/net/ipv6/netfilter/Makefile
11296--- linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile 2004-04-29 11:24:39.000000000 +0200
11297+++ linux-2.6.6-rc3/net/ipv6/netfilter/Makefile 2004-04-29 11:19:41.000000000 +0200
11298@@ -29,4 +29,6 @@
11299 obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
11300 obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
11301 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
11302+obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
11303 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
11304+obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
11305diff -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
11306--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-04-28 03:36:34.000000000 +0200
11307+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c 2004-04-29 11:17:15.000000000 +0200
11308@@ -38,6 +38,14 @@
11309 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
11310 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
11311
11312+static const char *hook6names[] = {
11313+ [NF_IP6_PRE_ROUTING] "PREROUTING",
11314+ [NF_IP6_LOCAL_IN] "INPUT",
11315+ [NF_IP6_FORWARD] "FORWARD",
11316+ [NF_IP6_LOCAL_OUT] "OUTPUT",
11317+ [NF_IP6_POST_ROUTING] "POSTROUTING",
11318+};
11319+
11320 /*#define DEBUG_IP_FIREWALL*/
11321 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
11322 /*#define DEBUG_IP_FIREWALL_USER*/
11323@@ -408,6 +416,12 @@
11324
11325 t = ip6t_get_target(e);
11326 IP_NF_ASSERT(t->u.kernel.target);
11327+
11328+ /* The packet traced and the rule isn't an unconditional return/END. */
11329+ if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
11330+ nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
11331+ table->name, e->chainname, e->rulenum);
11332+ }
11333 /* Standard target? */
11334 if (!t->u.kernel.target->target) {
11335 int v;
11336@@ -561,6 +575,29 @@
11337 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
11338 }
11339
11340+static inline int
11341+find_error_target(struct ip6t_entry *s,
11342+ struct ip6t_entry *e,
11343+ char **chainname)
11344+{
11345+ struct ip6t_entry_target *t;
11346+ static struct ip6t_entry *found = NULL;
11347+
11348+ if (s == e) {
11349+ if (!found)
11350+ return 0;
11351+ t = ip6t_get_target(found);
11352+ if (strcmp(t->u.user.name,
11353+ IP6T_ERROR_TARGET) == 0) {
11354+ *chainname = t->data;
11355+ return 1;
11356+ }
11357+ } else
11358+ found = s;
11359+
11360+ return 0;
11361+}
11362+
11363 /* All zeroes == unconditional rule. */
11364 static inline int
11365 unconditional(const struct ip6t_ip6 *ipv6)
11366@@ -580,6 +617,8 @@
11367 mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
11368 {
11369 unsigned int hook;
11370+ char *chainname = NULL;
11371+ u_int32_t rulenum;
11372
11373 /* No recursion; use packet counter to save back ptrs (reset
11374 to 0 as we leave), and comefrom to save source hook bitmask */
11375@@ -593,6 +632,8 @@
11376
11377 /* Set initial back pointer. */
11378 e->counters.pcnt = pos;
11379+ rulenum = 1;
11380+ chainname = (char *) hook6names[hook];
11381
11382 for (;;) {
11383 struct ip6t_standard_target *t
11384@@ -605,6 +646,8 @@
11385 }
11386 e->comefrom
11387 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
11388+ e->rulenum = rulenum++;
11389+ e->chainname = chainname;
11390
11391 /* Unconditional return/END. */
11392 if (e->target_offset == sizeof(struct ip6t_entry)
11393@@ -614,6 +657,10 @@
11394 && unconditional(&e->ipv6)) {
11395 unsigned int oldpos, size;
11396
11397+ /* Set unconditional rulenum to zero. */
11398+ e->rulenum = 0;
11399+ e->counters.bcnt = 0;
11400+
11401 /* Return: backtrack through the last
11402 big jump. */
11403 do {
11404@@ -639,6 +686,11 @@
11405 (newinfo->entries + pos);
11406 } while (oldpos == pos + e->next_offset);
11407
11408+ /* Restore chainname, rulenum. */
11409+ chainname = e->chainname;
11410+ rulenum = e->counters.bcnt;
11411+ e->counters.bcnt = 0;
11412+
11413 /* Move along one */
11414 size = e->next_offset;
11415 e = (struct ip6t_entry *)
11416@@ -654,6 +706,17 @@
11417 /* This a jump; chase it. */
11418 duprintf("Jump rule %u -> %u\n",
11419 pos, newpos);
11420+ e->counters.bcnt = rulenum++;
11421+ rulenum = 1;
11422+ e = (struct ip6t_entry *)
11423+ (newinfo->entries + newpos);
11424+ if (IP6T_ENTRY_ITERATE(newinfo->entries,
11425+ newinfo->size,
11426+ find_error_target,
11427+ e, &chainname) == 0) {
11428+ printk("ip6_tables: table screwed up!\n");
11429+ return 0;
11430+ }
11431 } else {
11432 /* ... this is a fallthru */
11433 newpos = pos + e->next_offset;
11434diff -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
11435--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
11436+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c 2004-04-29 11:17:15.000000000 +0200
11437@@ -0,0 +1,65 @@
11438+/* This is a module which is used for setting
11439+ * the NFC_TRACE flag in the nfcache field of an skb.
11440+ */
11441+#include <linux/module.h>
11442+#include <linux/skbuff.h>
11443+
11444+#include <linux/netfilter_ipv6/ip6_tables.h>
11445+
11446+MODULE_LICENSE("GPL");
11447+
11448+static unsigned int
11449+target(struct sk_buff **pskb,
11450+ unsigned int hooknum,
11451+ const struct net_device *in,
11452+ const struct net_device *out,
11453+ const void *targinfo,
11454+ void *userinfo)
11455+{
11456+ (*pskb)->nfcache |= NFC_TRACE;
11457+ return IP6T_CONTINUE;
11458+}
11459+
11460+static int
11461+checkentry(const char *tablename,
11462+ const struct ip6t_entry *e,
11463+ void *targinfo,
11464+ unsigned int targinfosize,
11465+ unsigned int hook_mask)
11466+{
11467+ if (targinfosize != 0) {
11468+ printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
11469+ targinfosize);
11470+ return 0;
11471+ }
11472+
11473+ if (strcmp(tablename, "raw") != 0) {
11474+ printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
11475+ return 0;
11476+ }
11477+
11478+ return 1;
11479+}
11480+
11481+static struct ip6t_target ip6t_trace_reg = {
11482+ .name = "TRACE",
11483+ .target = target,
11484+ .checkentry = checkentry,
11485+ .me = THIS_MODULE
11486+};
11487+
11488+static int __init init(void)
11489+{
11490+ if (ip6t_register_target(&ip6t_trace_reg))
11491+ return -EINVAL;
11492+
11493+ return 0;
11494+}
11495+
11496+static void __exit fini(void)
11497+{
11498+ ip6t_unregister_target(&ip6t_trace_reg);
11499+}
11500+
11501+module_init(init);
11502+module_exit(fini);
11503diff -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
11504--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-28 03:36:30.000000000 +0200
11505+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c 2004-04-29 11:19:40.000000000 +0200
11506@@ -21,6 +21,39 @@
11507 MODULE_LICENSE("GPL");
11508
11509 static int
11510+match_comm(const struct sk_buff *skb, const char *comm)
11511+{
11512+ struct task_struct *p, *g;
11513+ struct files_struct *files;
11514+ int i;
11515+
11516+ read_lock(&tasklist_lock);
11517+ do_each_thread(g, p) {
11518+ if(strncmp(p->comm, comm, sizeof(p->comm)))
11519+ continue;
11520+
11521+ task_lock(p);
11522+ files = p->files;
11523+ if(files) {
11524+ read_lock(&files->file_lock);
11525+ for (i=0; i < files->max_fds; i++) {
11526+ if (fcheck_files(files, i) ==
11527+ skb->sk->sk_socket->file) {
11528+ read_unlock(&files->file_lock);
11529+ task_unlock(p);
11530+ read_unlock(&tasklist_lock);
11531+ return 1;
11532+ }
11533+ }
11534+ read_unlock(&files->file_lock);
11535+ }
11536+ task_unlock(p);
11537+ } while_each_thread(g, p);
11538+ read_unlock(&tasklist_lock);
11539+ return 0;
11540+}
11541+
11542+static int
11543 match_pid(const struct sk_buff *skb, pid_t pid)
11544 {
11545 struct task_struct *p;
11546@@ -125,6 +158,12 @@
11547 return 0;
11548 }
11549
11550+ if(info->match & IP6T_OWNER_COMM) {
11551+ if (!match_comm(skb, info->comm) ^
11552+ !!(info->invert & IP6T_OWNER_COMM))
11553+ return 0;
11554+ }
11555+
11556 return 1;
11557 }
11558
11559diff -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
11560--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c 1970-01-01 01:00:00.000000000 +0100
11561+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c 2004-04-29 11:19:41.000000000 +0200
11562@@ -0,0 +1,200 @@
11563+/* IP tables module for matching IPsec policy\r
11564+ *\r
11565+ * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>\r
11566+ *\r
11567+ * This program is free software; you can redistribute it and/or modify\r
11568+ * it under the terms of the GNU General Public License version 2 as\r
11569+ * published by the Free Software Foundation.\r
11570+ */\r
11571+\r
11572+#include <linux/kernel.h>\r
11573+#include <linux/config.h>\r
11574+#include <linux/module.h>\r
11575+#include <linux/skbuff.h>\r
11576+#include <linux/init.h>\r
11577+#include <net/xfrm.h>\r
11578+\r
11579+#include <linux/netfilter_ipv6.h>\r
11580+#include <linux/netfilter_ipv6/ip6t_policy.h>\r
11581+#include <linux/netfilter_ipv6/ip6_tables.h>\r
11582+\r
11583+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");\r
11584+MODULE_DESCRIPTION("IPtables IPsec policy matching module");\r
11585+MODULE_LICENSE("GPL");\r
11586+\r
11587+\r
11588+static inline int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,\r
11589+ struct in6_addr addr2)\r
11590+{\r
11591+ int i;\r
11592+\r
11593+ for (i = 0; i < 16; i++) {\r
11594+ if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=\r
11595+ (addr2.s6_addr[i] & mask.s6_addr[i]))\r
11596+ return 1;\r
11597+ }\r
11598+ return 0;\r
11599+}\r
11600+\r
11601+\r
11602+static inline int\r
11603+match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)\r
11604+{\r
11605+#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))\r
11606+ \r
11607+ struct in6_addr xfrm_saddr, xfrm_daddr;\r
11608+ \r
11609+ if ((e->match.saddr\r
11610+ && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))\r
11611+ ^ e->invert.saddr ) ||\r
11612+ (e->match.daddr\r
11613+ && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))\r
11614+ ^ e->invert.daddr ) ||\r
11615+ MISMATCH(proto, x->id.proto) ||\r
11616+ MISMATCH(mode, x->props.mode) ||\r
11617+ MISMATCH(spi, x->id.spi) ||\r
11618+ MISMATCH(reqid, x->props.reqid))\r
11619+ return 0;\r
11620+ return 1;\r
11621+}\r
11622+\r
11623+static int\r
11624+match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
11625+{\r
11626+ const struct ip6t_policy_elem *e;\r
11627+ struct sec_path *sp = skb->sp;\r
11628+ int strict = info->flags & POLICY_MATCH_STRICT;\r
11629+ int i, pos;\r
11630+\r
11631+ if (sp == NULL)\r
11632+ return -1;\r
11633+ if (strict && info->len != sp->len)\r
11634+ return 0;\r
11635+\r
11636+ for (i = sp->len - 1; i >= 0; i--) {\r
11637+ pos = strict ? i - sp->len + 1 : 0;\r
11638+ if (pos >= info->len)\r
11639+ return 0;\r
11640+ e = &info->pol[pos];\r
11641+\r
11642+ if (match_xfrm_state(sp->x[i].xvec, e)) {\r
11643+ if (!strict)\r
11644+ return 1;\r
11645+ } else if (strict)\r
11646+ return 0;\r
11647+ }\r
11648+\r
11649+ return strict ? 1 : 0;\r
11650+}\r
11651+\r
11652+static int\r
11653+match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
11654+{\r
11655+ const struct ip6t_policy_elem *e;\r
11656+ struct dst_entry *dst = skb->dst;\r
11657+ int strict = info->flags & POLICY_MATCH_STRICT;\r
11658+ int i, pos;\r
11659+\r
11660+ if (dst->xfrm == NULL)\r
11661+ return -1;\r
11662+\r
11663+ for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {\r
11664+ pos = strict ? i : 0;\r
11665+ if (pos >= info->len)\r
11666+ return 0;\r
11667+ e = &info->pol[pos];\r
11668+\r
11669+ if (match_xfrm_state(dst->xfrm, e)) {\r
11670+ if (!strict)\r
11671+ return 1;\r
11672+ } else if (strict)\r
11673+ return 0;\r
11674+ }\r
11675+\r
11676+ return strict ? 1 : 0;\r
11677+}\r
11678+\r
11679+static int match(const struct sk_buff *skb,\r
11680+ const struct net_device *in,\r
11681+ const struct net_device *out,\r
11682+ const void *matchinfo,\r
11683+ int offset,\r
11684+ const void *hdr,\r
11685+ u_int16_t datalen,\r
11686+ int *hotdrop)\r
11687+{\r
11688+ const struct ip6t_policy_info *info = matchinfo;\r
11689+ int ret;\r
11690+\r
11691+ if (info->flags & POLICY_MATCH_IN)\r
11692+ ret = match_policy_in(skb, info);\r
11693+ else\r
11694+ ret = match_policy_out(skb, info);\r
11695+\r
11696+ if (ret < 0) {\r
11697+ if (info->flags & POLICY_MATCH_NONE)\r
11698+ ret = 1;\r
11699+ else\r
11700+ ret = 0;\r
11701+ } else if (info->flags & POLICY_MATCH_NONE)\r
11702+ ret = 0;\r
11703+\r
11704+ return ret;\r
11705+}\r
11706+\r
11707+static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,\r
11708+ void *matchinfo, unsigned int matchsize,\r
11709+ unsigned int hook_mask)\r
11710+{\r
11711+ struct ip6t_policy_info *info = matchinfo;\r
11712+\r
11713+ if (matchsize != IP6T_ALIGN(sizeof(*info))) {\r
11714+ printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",\r
11715+ matchsize, IP6T_ALIGN(sizeof(*info)));\r
11716+ return 0;\r
11717+ }\r
11718+ if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {\r
11719+ printk(KERN_ERR "ip6t_policy: neither incoming nor "\r
11720+ "outgoing policy selected\n");\r
11721+ return 0;\r
11722+ }\r
11723+ if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)\r
11724+ && info->flags & POLICY_MATCH_OUT) {\r
11725+ printk(KERN_ERR "ip6t_policy: output policy not valid in "\r
11726+ "PRE_ROUTING and INPUT\n");\r
11727+ return 0;\r
11728+ }\r
11729+ if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)\r
11730+ && info->flags & POLICY_MATCH_IN) {\r
11731+ printk(KERN_ERR "ip6t_policy: input policy not valid in "\r
11732+ "POST_ROUTING and OUTPUT\n");\r
11733+ return 0;\r
11734+ }\r
11735+ if (info->len > POLICY_MAX_ELEM) {\r
11736+ printk(KERN_ERR "ip6t_policy: too many policy elements\n");\r
11737+ return 0;\r
11738+ }\r
11739+\r
11740+ return 1;\r
11741+}\r
11742+\r
11743+static struct ip6t_match policy_match =\r
11744+{\r
11745+ .name = "policy",\r
11746+ .match = match,\r
11747+ .checkentry = checkentry,\r
11748+ .me = THIS_MODULE,\r
11749+};\r
11750+\r
11751+static int __init init(void)\r
11752+{\r
11753+ return ip6t_register_match(&policy_match);\r
11754+}\r
11755+\r
11756+static void __exit fini(void)\r
11757+{\r
11758+ ip6t_unregister_match(&policy_match);\r
11759+}\r
11760+\r
11761+module_init(init);\r
11762+module_exit(fini);\r
11763diff -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
11764--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c 2004-04-28 03:35:07.000000000 +0200
11765+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c 2004-04-29 11:17:15.000000000 +0200
11766@@ -58,7 +58,7 @@
11767 0,
11768 sizeof(struct ip6t_entry),
11769 sizeof(struct ip6t_standard),
11770- 0, { 0, 0 }, { } },
11771+ 0, NULL, 0, { 0, 0 }, { } },
11772 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11773 -NF_ACCEPT - 1 } },
11774 /* FORWARD */
11775@@ -66,7 +66,7 @@
11776 0,
11777 sizeof(struct ip6t_entry),
11778 sizeof(struct ip6t_standard),
11779- 0, { 0, 0 }, { } },
11780+ 0, NULL, 0, { 0, 0 }, { } },
11781 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11782 -NF_ACCEPT - 1 } },
11783 /* LOCAL_OUT */
11784@@ -74,7 +74,7 @@
11785 0,
11786 sizeof(struct ip6t_entry),
11787 sizeof(struct ip6t_standard),
11788- 0, { 0, 0 }, { } },
11789+ 0, NULL, 0, { 0, 0 }, { } },
11790 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11791 -NF_ACCEPT - 1 } }
11792 },
11793@@ -83,7 +83,7 @@
11794 0,
11795 sizeof(struct ip6t_entry),
11796 sizeof(struct ip6t_error),
11797- 0, { 0, 0 }, { } },
11798+ 0, NULL, 0, { 0, 0 }, { } },
11799 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11800 { } },
11801 "ERROR"
11802diff -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
11803--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c 2004-04-28 03:35:43.000000000 +0200
11804+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c 2004-04-29 11:17:15.000000000 +0200
11805@@ -73,7 +73,7 @@
11806 0,
11807 sizeof(struct ip6t_entry),
11808 sizeof(struct ip6t_standard),
11809- 0, { 0, 0 }, { } },
11810+ 0, NULL, 0, { 0, 0 }, { } },
11811 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11812 -NF_ACCEPT - 1 } },
11813 /* LOCAL_IN */
11814@@ -81,7 +81,7 @@
11815 0,
11816 sizeof(struct ip6t_entry),
11817 sizeof(struct ip6t_standard),
11818- 0, { 0, 0 }, { } },
11819+ 0, NULL, 0, { 0, 0 }, { } },
11820 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11821 -NF_ACCEPT - 1 } },
11822 /* FORWARD */
11823@@ -89,7 +89,7 @@
11824 0,
11825 sizeof(struct ip6t_entry),
11826 sizeof(struct ip6t_standard),
11827- 0, { 0, 0 }, { } },
11828+ 0, NULL, 0, { 0, 0 }, { } },
11829 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11830 -NF_ACCEPT - 1 } },
11831 /* LOCAL_OUT */
11832@@ -97,7 +97,7 @@
11833 0,
11834 sizeof(struct ip6t_entry),
11835 sizeof(struct ip6t_standard),
11836- 0, { 0, 0 }, { } },
11837+ 0, NULL, 0, { 0, 0 }, { } },
11838 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11839 -NF_ACCEPT - 1 } },
11840 /* POST_ROUTING */
11841@@ -105,7 +105,7 @@
11842 0,
11843 sizeof(struct ip6t_entry),
11844 sizeof(struct ip6t_standard),
11845- 0, { 0, 0 }, { } },
11846+ 0, NULL, 0, { 0, 0 }, { } },
11847 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11848 -NF_ACCEPT - 1 } }
11849 },
11850@@ -114,7 +114,7 @@
11851 0,
11852 sizeof(struct ip6t_entry),
11853 sizeof(struct ip6t_error),
11854- 0, { 0, 0 }, { } },
11855+ 0, NULL, 0, { 0, 0 }, { } },
11856 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11857 { } },
11858 "ERROR"
11859diff -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
11860--- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c 2004-04-28 03:36:19.000000000 +0200
11861+++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c 2004-04-29 11:17:15.000000000 +0200
11862@@ -52,7 +52,7 @@
11863 0,
11864 sizeof(struct ip6t_entry),
11865 sizeof(struct ip6t_standard),
11866- 0, { 0, 0 }, { } },
11867+ 0, NULL, 0, { 0, 0 }, { } },
11868 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11869 -NF_ACCEPT - 1 } },
11870 /* LOCAL_OUT */
11871@@ -60,7 +60,7 @@
11872 0,
11873 sizeof(struct ip6t_entry),
11874 sizeof(struct ip6t_standard),
11875- 0, { 0, 0 }, { } },
11876+ 0, NULL, 0, { 0, 0 }, { } },
11877 { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11878 -NF_ACCEPT - 1 } },
11879 },
11880@@ -69,7 +69,7 @@
11881 0,
11882 sizeof(struct ip6t_entry),
11883 sizeof(struct ip6t_error),
11884- 0, { 0, 0 }, { } },
11885+ 0, NULL, 0, { 0, 0 }, { } },
11886 { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11887 { } },
11888 "ERROR"
11889diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c linux-2.6.6-rc3/net/xfrm/xfrm_input.c
11890--- linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c 2004-04-28 03:35:05.000000000 +0200
11891+++ linux-2.6.6-rc3/net/xfrm/xfrm_input.c 2004-04-29 11:18:03.000000000 +0200
11892@@ -29,6 +29,9 @@
11893 if (!sp)
11894 return NULL;
11895
11896+#ifdef CONFIG_NETFILTER
11897+ sp->decap_done = 0;
11898+#endif
11899 sp->len = 0;
11900 if (src) {
11901 int i;
11902diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc3/net/xfrm/xfrm_policy.c
11903--- linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c 2004-04-28 03:35:48.000000000 +0200
11904+++ linux-2.6.6-rc3/net/xfrm/xfrm_policy.c 2004-04-29 11:18:06.000000000 +0200
11905@@ -21,6 +21,7 @@
11906 #include <linux/workqueue.h>
11907 #include <linux/notifier.h>
11908 #include <linux/netdevice.h>
11909+#include <linux/netfilter.h>
11910 #include <net/xfrm.h>
11911 #include <net/ip.h>
11912
11913@@ -908,6 +909,7 @@
11914
11915 if (_decode_session(skb, &fl, family) < 0)
11916 return 0;
11917+ nf_nat_decode_session(skb, &fl, family);
11918
11919 /* First, check used SA against their selectors. */
11920 if (skb->sp) {
This page took 1.650734 seconds and 4 git commands to generate.