]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.6-rc1-patch-o-matic-ng-extra-20040415.patch
- obsolete
[packages/kernel.git] / 2.6.6-rc1-patch-o-matic-ng-extra-20040415.patch
1 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter.h linux-2.6.6-rc1/include/linux/netfilter.h
2 --- linux-2.6.6-rc1.org/include/linux/netfilter.h       2004-04-16 08:59:08.000000000 +0200
3 +++ linux-2.6.6-rc1/include/linux/netfilter.h   2004-04-16 09:17:13.000000000 +0200
4 @@ -137,12 +137,14 @@
5  /* This is gross, but inline doesn't cut it for avoiding the function
6     call in fast path: gcc doesn't inline (needs value tracking?). --RR */
7  #ifdef CONFIG_NETFILTER_DEBUG
8 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
9 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
10 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
11 +(!(cond)                                                               \
12 + ? (okfn)(skb)                                                                 \
13 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
14  #define NF_HOOK_THRESH nf_hook_slow
15  #else
16 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
17 -(list_empty(&nf_hooks[(pf)][(hook)])                                   \
18 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
19 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)])                                \
20   ? (okfn)(skb)                                                         \
21   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
22  #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)     \
23 @@ -150,6 +152,8 @@
24   ? (okfn)(skb)                                                         \
25   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
26  #endif
27 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
28 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
29  
30  int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
31                  struct net_device *indev, struct net_device *outdev,
32 @@ -182,7 +186,24 @@
33  
34  #else /* !CONFIG_NETFILTER */
35  #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
36 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
37  #endif /*CONFIG_NETFILTER*/
38  
39 +#ifdef CONFIG_XFRM
40 +#ifdef CONFIG_IP_NF_NAT_NEEDED
41 +struct flowi;
42 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
43 +
44 +static inline void
45 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
46 +{
47 +       if (family == AF_INET)
48 +               nf_nat_decode_session4(skb, fl);
49 +}
50 +#else /* CONFIG_IP_NF_NAT_NEEDED */
51 +#define nf_nat_decode_session(skb,fl,family)
52 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
53 +#endif /* CONFIG_XFRM */
54 +
55  #endif /*__KERNEL__*/
56  #endif /*__LINUX_NETFILTER_H*/
57 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack.h
58 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h     2004-04-16 08:59:08.000000000 +0200
59 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-16 09:18:58.000000000 +0200
60 @@ -64,6 +64,10 @@
61  };
62  
63  /* Add protocol helper include file here */
64 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
65 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
66 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
67 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
68  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
69  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
70  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
71 @@ -71,6 +75,10 @@
72  /* per expectation: application helper private data */
73  union ip_conntrack_expect_help {
74         /* insert conntrack helper private data (expect) here */
75 +       struct ip_ct_talk_expect exp_talk_info;
76 +       struct ip_ct_rsh_expect exp_rsh_info;
77 +       struct ip_ct_mms_expect exp_mms_info;
78 +       struct ip_ct_h225_expect exp_h225_info;
79         struct ip_ct_amanda_expect exp_amanda_info;
80         struct ip_ct_ftp_expect exp_ftp_info;
81         struct ip_ct_irc_expect exp_irc_info;
82 @@ -85,6 +93,10 @@
83  /* per conntrack: application helper private data */
84  union ip_conntrack_help {
85         /* insert conntrack helper private data (master) here */
86 +       struct ip_ct_talk_master ct_talk_info;
87 +       struct ip_ct_rsh_master ct_rsh_info;
88 +       struct ip_ct_mms_master ct_mms_info;
89 +       struct ip_ct_h225_master ct_h225_info;
90         struct ip_ct_ftp_master ct_ftp_info;
91         struct ip_ct_irc_master ct_irc_info;
92  };
93 @@ -207,6 +219,10 @@
94         } nat;
95  #endif /* CONFIG_IP_NF_NAT_NEEDED */
96  
97 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
98 +       unsigned long mark;
99 +#endif
100 +
101  };
102  
103  /* get master conntrack via master expectation */
104 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_h323.h
105 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h        1970-01-01 01:00:00.000000000 +0100
106 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_h323.h    2004-04-16 09:17:05.000000000 +0200
107 @@ -0,0 +1,31 @@
108 +#ifndef _IP_CONNTRACK_H323_H
109 +#define _IP_CONNTRACK_H323_H
110 +/* H.323 connection tracking. */
111 +
112 +#ifdef __KERNEL__
113 +/* Protects H.323 related data */
114 +#include <linux/netfilter_ipv4/lockhelp.h>
115 +DECLARE_LOCK_EXTERN(ip_h323_lock);
116 +#endif
117 +
118 +/* Default H.225 port */
119 +#define H225_PORT      1720
120 +
121 +/* This structure is per expected connection */
122 +struct ip_ct_h225_expect {
123 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
124 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
125 +       unsigned int offset;            /* offset of the address in the payload */
126 +};
127 +
128 +/* This structure exists only once per master */
129 +struct ip_ct_h225_master {
130 +       int is_h225;                            /* H.225 or H.245 connection */
131 +#ifdef CONFIG_IP_NF_NAT_NEEDED
132 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
133 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
134 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
135 +#endif
136 +};
137 +
138 +#endif /* _IP_CONNTRACK_H323_H */
139 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_mms.h
140 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
141 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_mms.h     2004-04-16 09:17:32.000000000 +0200
142 @@ -0,0 +1,31 @@
143 +#ifndef _IP_CONNTRACK_MMS_H
144 +#define _IP_CONNTRACK_MMS_H
145 +/* MMS tracking. */
146 +
147 +#ifdef __KERNEL__
148 +#include <linux/netfilter_ipv4/lockhelp.h>
149 +
150 +DECLARE_LOCK_EXTERN(ip_mms_lock);
151 +
152 +#define MMS_PORT                         1755
153 +#define MMS_SRV_MSG_ID                   196610
154 +
155 +#define MMS_SRV_MSG_OFFSET               36
156 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
157 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
158 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
159 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
160 +#endif
161 +
162 +/* This structure is per expected connection */
163 +struct ip_ct_mms_expect {
164 +       u_int32_t len;
165 +       u_int32_t padding;
166 +       u_int16_t port;
167 +};
168 +
169 +/* This structure exists only once per master */
170 +struct ip_ct_mms_master {
171 +};
172 +
173 +#endif /* _IP_CONNTRACK_MMS_H */
174 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
175 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h      1970-01-01 01:00:00.000000000 +0100
176 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_quake3.h  2004-04-16 09:18:43.000000000 +0200
177 @@ -0,0 +1,21 @@
178 +#ifndef _IP_CT_QUAKE3
179 +#define _IP_CT_QUAKE3
180 +
181 +/* Don't confuse with 27960, often used as the Server Port */
182 +#define QUAKE3_MASTER_PORT 27950
183 +
184 +struct quake3_search {
185 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
186 +       const char *pattern;
187 +       size_t plen;
188 +}; 
189 +
190 +/* This structure is per expected connection */
191 +struct ip_ct_quake3_expect {
192 +};
193 +
194 +/* This structure exists only once per master */
195 +struct ip_ct_quake3_master {
196 +};
197 +
198 +#endif /* _IP_CT_QUAKE3 */
199 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
200 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
201 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rpc.h     2004-04-16 09:18:44.000000000 +0200
202 @@ -0,0 +1,68 @@
203 +/* RPC extension for IP connection tracking, Version 2.2
204 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
205 + *     - original rpc tracking module
206 + *     - "recent" connection handling for kernel 2.3+ netfilter
207 + *
208 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
209 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
210 + *
211 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
212 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
213 + *     - extended matching to support filtering on procedures
214 + *
215 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
216 + *
217 + *     This program is free software; you can redistribute it and/or
218 + *     modify it under the terms of the GNU General Public License
219 + *     as published by the Free Software Foundation; either version
220 + *     2 of the License, or (at your option) any later version.
221 + **
222 + */
223 +
224 +#include <asm/param.h>
225 +#include <linux/sched.h>
226 +#include <linux/timer.h>
227 +#include <linux/stddef.h>
228 +#include <linux/list.h>
229 +
230 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
231 +
232 +#ifndef _IP_CONNTRACK_RPC_H
233 +#define _IP_CONNTRACK_RPC_H
234 +
235 +#define RPC_PORT       111
236 +
237 +
238 +/* Datum in RPC packets are encoded in XDR */
239 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
240 +
241 +/* Fast timeout, to deny DoS atacks */
242 +#define EXP (60 * HZ)
243 +
244 +/* Normal timeouts */
245 +#define EXPIRES (180 * HZ)
246 +
247 +/* For future conections RPC, using client's cache bindings
248 + * I'll use ip_conntrack_lock to lock these lists      */
249 +
250 +/* This identifies each request and stores protocol */
251 +struct request_p {
252 +       struct list_head list;
253 +
254 +       u_int32_t xid;   
255 +       u_int32_t ip;
256 +       u_int16_t port;
257 +       
258 +       /* Protocol */
259 +       u_int16_t proto;
260 +
261 +       struct timer_list timeout;
262 +};
263 +
264 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
265 +                               u_int32_t ip, u_int32_t port) {
266 +       return (p->xid == xid && p->ip == ip && p->port);
267 +
268 +}
269 +
270 +#endif /* _IP_CONNTRACK_RPC_H */
271 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
272 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
273 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_rsh.h     2004-04-16 09:18:45.000000000 +0200
274 @@ -0,0 +1,35 @@
275 +/* RSH extension for IP connection tracking, Version 1.0
276 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
277 + * based on HW's ip_conntrack_irc.c     
278 + *
279 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
280 + *
281 + *      This program is free software; you can redistribute it and/or
282 + *      modify it under the terms of the GNU General Public License
283 + *      as published by the Free Software Foundation; either version
284 + *      2 of the License, or (at your option) any later version.
285 + */
286 +#ifndef _IP_CONNTRACK_RSH_H
287 +#define _IP_CONNTRACK_RSH_H
288 +
289 +#ifdef __KERNEL__
290 +#include <linux/netfilter_ipv4/lockhelp.h>
291 +
292 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
293 +#endif
294 +
295 +
296 +#define RSH_PORT       514
297 +
298 +/* This structure is per expected connection */
299 +struct ip_ct_rsh_expect
300 +{
301 +       u_int16_t port;
302 +};
303 +
304 +/* This structure exists only once per master */
305 +struct ip_ct_rsh_master {
306 +};
307 +
308 +#endif /* _IP_CONNTRACK_RSH_H */
309 +
310 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_talk.h
311 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h        1970-01-01 01:00:00.000000000 +0100
312 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_talk.h    2004-04-16 09:18:58.000000000 +0200
313 @@ -0,0 +1,152 @@
314 +#ifndef _IP_CONNTRACK_TALK_H
315 +#define _IP_CONNTRACK_TALK_H
316 +/* TALK tracking. */
317 +
318 +#ifdef __KERNEL__
319 +#include <linux/in.h>
320 +#include <linux/netfilter_ipv4/lockhelp.h>
321 +
322 +/* Protects talk part of conntracks */
323 +DECLARE_LOCK_EXTERN(ip_talk_lock);
324 +#endif
325 +
326 +
327 +#define TALK_PORT      517
328 +#define NTALK_PORT     518
329 +
330 +/* talk structures and constants from <protocols/talkd.h> */
331 +
332 +/*
333 + * 4.3BSD struct sockaddr
334 + */
335 +struct talk_addr {
336 +       u_int16_t ta_family;
337 +       u_int16_t ta_port;
338 +       u_int32_t ta_addr;
339 +       u_int32_t ta_junk1;
340 +       u_int32_t ta_junk2;
341 +};
342 +
343 +#define        TALK_OLD_NSIZE  9
344 +#define        TALK_NSIZE      12
345 +#define        TALK_TTY_NSIZE  16
346 +
347 +/*
348 + * Client->server request message formats.
349 + */
350 +struct talk_msg {
351 +       u_char  type;           /* request type, see below */
352 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
353 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
354 +       u_char  pad;
355 +       u_int32_t id_num;       /* message id */
356 +       int32_t pid;            /* caller's process id */
357 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
358 +       struct  talk_addr addr;         /* old (4.3) style */
359 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
360 +};
361 +
362 +struct ntalk_msg {
363 +       u_char  vers;           /* protocol version */
364 +       u_char  type;           /* request type, see below */
365 +       u_char  answer;         /* not used */
366 +       u_char  pad;
367 +       u_int32_t id_num;       /* message id */
368 +       struct  talk_addr addr;         /* old (4.3) style */
369 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
370 +       int32_t pid;            /* caller's process id */
371 +       char    l_name[TALK_NSIZE];/* caller's name */
372 +       char    r_name[TALK_NSIZE];/* callee's name */
373 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
374 +};
375 +
376 +struct ntalk2_msg {
377 +       u_char  vers;           /* talk protocol version    */
378 +       u_char  type;           /* request type             */
379 +       u_char  answer;         /*  */
380 +       u_char  extended;       /* !0 if additional parts   */
381 +       u_int32_t id_num;       /* message id number (dels) */
382 +       struct  talk_addr addr;         /* target address   */
383 +       struct  talk_addr ctl_addr;     /* reply to address */
384 +       int32_t pid;            /* caller's process id */
385 +       char    l_name[TALK_NSIZE];  /* caller's name */
386 +       char    r_name[TALK_NSIZE];  /* callee's name */
387 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
388 +};
389 +
390 +/*
391 + * Server->client response message formats.
392 + */
393 +struct talk_response {
394 +       u_char  type;           /* type of request message, see below */
395 +       u_char  answer;         /* response to request message, see below */
396 +       u_char  pad[2];
397 +       u_int32_t id_num;       /* message id */
398 +       struct  talk_addr addr; /* address for establishing conversation */
399 +};
400 +
401 +struct ntalk_response {
402 +       u_char  vers;           /* protocol version */
403 +       u_char  type;           /* type of request message, see below */
404 +       u_char  answer;         /* response to request message, see below */
405 +       u_char  pad;
406 +       u_int32_t id_num;       /* message id */
407 +       struct  talk_addr addr; /* address for establishing conversation */
408 +};
409 +
410 +struct ntalk2_response {
411 +       u_char  vers;           /* protocol version         */
412 +       u_char  type;           /* type of request message  */
413 +       u_char  answer;         /* response to request      */
414 +       u_char  rvers;          /* Version of answering vers*/
415 +       u_int32_t id_num;       /* message id number        */
416 +       struct  talk_addr addr; /* address for connection   */
417 +       /* This is at the end to compatiblize this with NTALK version.   */
418 +       char    r_name[TALK_NSIZE]; /* callee's name            */
419 +};
420 +
421 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
422 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
423 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
424 +
425 +#define        TALK_VERSION    0               /* protocol versions */
426 +#define        NTALK_VERSION   1
427 +#define        NTALK2_VERSION  2
428 +
429 +/* message type values */
430 +#define LEAVE_INVITE   0       /* leave invitation with server */
431 +#define LOOK_UP                1       /* check for invitation by callee */
432 +#define DELETE         2       /* delete invitation by caller */
433 +#define ANNOUNCE       3       /* announce invitation by caller */
434 +/* NTALK2 */
435 +#define REPLY_QUERY    4       /* request reply data from local daemon */
436 +
437 +/* answer values */
438 +#define SUCCESS                0       /* operation completed properly */
439 +#define NOT_HERE       1       /* callee not logged in */
440 +#define FAILED         2       /* operation failed for unexplained reason */
441 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
442 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
443 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
444 +#define        BADVERSION      6       /* request has invalid protocol version */
445 +#define        BADADDR         7       /* request has invalid addr value */
446 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
447 +/* NTALK2 */
448 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
449 +#define TRY_HERE       10      /* Not on this machine, try this      */
450 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
451 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
452 +
453 +/* We don't really need much for talk */
454 +struct ip_ct_talk_expect
455 +{
456 +       /* Port that was to be used */
457 +       u_int16_t port;
458 +};
459 +
460 +/* This structure exists only once per master */
461 +struct ip_ct_talk_master
462 +{
463 +};
464 +
465 +#endif /* _IP_CONNTRACK_TALK_H */
466 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
467 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h       2004-04-15 03:35:20.000000000 +0200
468 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_tuple.h   2004-04-16 09:18:47.000000000 +0200
469 @@ -25,6 +25,9 @@
470         struct {
471                 u_int16_t id;
472         } icmp;
473 +       struct {
474 +               u_int16_t port;
475 +       } sctp;
476  };
477  
478  /* The manipulable part of the tuple. */
479 @@ -55,6 +58,9 @@
480                         struct {
481                                 u_int8_t type, code;
482                         } icmp;
483 +                       struct {
484 +                               u_int16_t port;
485 +                       } sctp;
486                 } u;
487  
488                 /* The protocol. */
489 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h
490 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h     1970-01-01 01:00:00.000000000 +0100
491 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-16 09:15:41.000000000 +0200
492 @@ -0,0 +1,25 @@
493 +#ifndef _IPT_CONNMARK_H_target
494 +#define _IPT_CONNMARK_H_target
495 +
496 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
497 + * by Henrik Nordstrom <hno@marasystems.com>
498 + *
499 + * This program is free software; you can redistribute it and/or modify
500 + * it under the terms of the GNU General Public License as published by
501 + * the Free Software Foundation; either version 2 of the License, or
502 + * (at your option) any later version.
503 + */
504 +
505 +enum {
506 +       IPT_CONNMARK_SET = 0,
507 +       IPT_CONNMARK_SAVE,
508 +       IPT_CONNMARK_RESTORE
509 +};
510 +
511 +struct ipt_connmark_target_info {
512 +       unsigned long mark;
513 +       unsigned long mask;
514 +       u_int8_t mode;
515 +};
516 +
517 +#endif /*_IPT_CONNMARK_H_target*/
518 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h
519 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h       1970-01-01 01:00:00.000000000 +0100
520 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h   2004-04-16 09:15:43.000000000 +0200
521 @@ -0,0 +1,13 @@
522 +#ifndef _IPT_IPMARK_H_target
523 +#define _IPT_IPMARK_H_target
524 +
525 +struct ipt_ipmark_target_info {
526 +       unsigned long andmask;
527 +       unsigned long ormask;
528 +       unsigned int addr;
529 +};
530 +
531 +#define IPT_IPMARK_SRC    0
532 +#define IPT_IPMARK_DST    1
533 +
534 +#endif /*_IPT_IPMARK_H_target*/
535 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_ROUTE.h
536 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_ROUTE.h        1970-01-01 01:00:00.000000000 +0100
537 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_ROUTE.h    2004-04-16 09:15:44.000000000 +0200
538 @@ -0,0 +1,22 @@
539 +/* Header file for iptables ipt_ROUTE target
540 + *
541 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
542 + *
543 + * This software is distributed under GNU GPL v2, 1991
544 + */
545 +#ifndef _IPT_ROUTE_H_target
546 +#define _IPT_ROUTE_H_target
547 +
548 +#define IPT_ROUTE_IFNAMSIZ 16
549 +
550 +struct ipt_route_target_info {
551 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
552 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
553 +       u_int32_t gw;                           /* IP address of gateway */
554 +       u_int8_t  flags;
555 +};
556 +
557 +/* Values for "flags" field */
558 +#define IPT_ROUTE_CONTINUE        0x01
559 +
560 +#endif /*_IPT_ROUTE_H_target*/
561 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_TCPLAG.h
562 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h       1970-01-01 01:00:00.000000000 +0100
563 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_TCPLAG.h   2004-04-16 09:15:55.000000000 +0200
564 @@ -0,0 +1,10 @@
565 +#ifndef _IPT_TCPLAG_H
566 +#define _IPT_TCPLAG_H
567 +
568 +struct ipt_tcplag
569 +{
570 +       unsigned char level;
571 +       unsigned char prefix[ 15 ];
572 +};
573 +
574 +#endif
575 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_XOR.h
576 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h  1970-01-01 01:00:00.000000000 +0100
577 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_XOR.h      2004-04-16 09:16:25.000000000 +0200
578 @@ -0,0 +1,9 @@
579 +#ifndef _IPT_XOR_H
580 +#define _IPT_XOR_H
581 +
582 +struct ipt_XOR_info {
583 +       char            key[30];
584 +       u_int8_t        block_size;
585 +};
586 +
587 +#endif /* _IPT_XOR_H */
588 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h
589 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h     1970-01-01 01:00:00.000000000 +0100
590 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-16 09:16:27.000000000 +0200
591 @@ -0,0 +1,11 @@
592 +#ifndef _IPT_ADDRTYPE_H
593 +#define _IPT_ADDRTYPE_H
594 +
595 +struct ipt_addrtype_info {
596 +       u_int16_t       source;         /* source-type mask */
597 +       u_int16_t       dest;           /* dest-type mask */
598 +       int             invert_source;
599 +       int             invert_dest;
600 +};
601 +
602 +#endif
603 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_connmark.h
604 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h     1970-01-01 01:00:00.000000000 +0100
605 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-16 09:15:41.000000000 +0200
606 @@ -0,0 +1,18 @@
607 +#ifndef _IPT_CONNMARK_H
608 +#define _IPT_CONNMARK_H
609 +
610 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
611 + * by Henrik Nordstrom <hno@marasystems.com>
612 + *
613 + * This program is free software; you can redistribute it and/or modify
614 + * it under the terms of the GNU General Public License as published by
615 + * the Free Software Foundation; either version 2 of the License, or
616 + * (at your option) any later version.
617 + */
618 +
619 +struct ipt_connmark_info {
620 +       unsigned long mark, mask;
621 +       u_int8_t invert;
622 +};
623 +
624 +#endif /*_IPT_CONNMARK_H*/
625 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_policy.h
626 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h       1970-01-01 01:00:00.000000000 +0100
627 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_policy.h   2004-04-16 09:18:18.000000000 +0200
628 @@ -0,0 +1,52 @@
629 +#ifndef _IPT_POLICY_H
630 +#define _IPT_POLICY_H
631 +
632 +#define POLICY_MAX_ELEM        4
633 +
634 +enum ipt_policy_flags
635 +{
636 +       POLICY_MATCH_IN         = 0x1,
637 +       POLICY_MATCH_OUT        = 0x2,
638 +       POLICY_MATCH_NONE       = 0x4,
639 +       POLICY_MATCH_STRICT     = 0x8,
640 +};
641 +
642 +enum ipt_policy_modes
643 +{
644 +       POLICY_MODE_TRANSPORT,
645 +       POLICY_MODE_TUNNEL
646 +};
647 +
648 +struct ipt_policy_spec
649 +{
650 +       u_int8_t        saddr:1,
651 +                       daddr:1,
652 +                       proto:1,
653 +                       mode:1,
654 +                       spi:1,
655 +                       reqid:1;
656 +};
657 +
658 +struct ipt_policy_elem
659 +{
660 +       u_int32_t       saddr;
661 +       u_int32_t       smask;
662 +       u_int32_t       daddr;
663 +       u_int32_t       dmask;
664 +       u_int32_t       spi;
665 +       u_int32_t       reqid;
666 +       u_int8_t        proto;
667 +       u_int8_t        mode;
668 +
669 +       struct ipt_policy_spec  match;
670 +       struct ipt_policy_spec  invert;
671 +};
672 +
673 +struct ipt_policy_info
674 +{
675 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
676 +       u_int16_t flags;
677 +       u_int16_t len;
678 +};
679 +
680 +#endif /* _IPT_POLICY_H */
681 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_rpc.h
682 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_rpc.h  1970-01-01 01:00:00.000000000 +0100
683 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_rpc.h      2004-04-16 09:18:44.000000000 +0200
684 @@ -0,0 +1,35 @@
685 +/* RPC extension for IP netfilter matching, Version 2.2
686 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
687 + *     - original rpc tracking module
688 + *     - "recent" connection handling for kernel 2.3+ netfilter
689 + *
690 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
691 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
692 + *
693 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
694 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
695 + *     - extended matching to support filtering on procedures
696 + *
697 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
698 + *
699 + *     This program is free software; you can redistribute it and/or
700 + *     modify it under the terms of the GNU General Public License
701 + *     as published by the Free Software Foundation; either version
702 + *     2 of the License, or (at your option) any later version.
703 + **
704 + */
705 +
706 +#ifndef _IPT_RPC_H
707 +#define _IPT_RPC_H
708 +
709 +struct ipt_rpc_data;
710 +
711 +struct ipt_rpc_info {
712 +       int inverse;
713 +       int strict;
714 +       const char c_procs[1408];
715 +       int i_procs;
716 +       struct ipt_rpc_data *data;
717 +};
718 +
719 +#endif /* _IPT_RPC_H */
720 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_string.h
721 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_string.h       1970-01-01 01:00:00.000000000 +0100
722 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_string.h   2004-04-16 09:19:37.000000000 +0200
723 @@ -0,0 +1,21 @@
724 +#ifndef _IPT_STRING_H
725 +#define _IPT_STRING_H
726 +
727 +/* *** PERFORMANCE TWEAK ***
728 + * Packet size and search string threshold,
729 + * above which sublinear searches is used. */
730 +#define IPT_STRING_HAYSTACK_THRESH     100
731 +#define IPT_STRING_NEEDLE_THRESH       20
732 +
733 +#define BM_MAX_NLEN 256
734 +#define BM_MAX_HLEN 1024
735 +
736 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
737 +
738 +struct ipt_string_info {
739 +    char string[BM_MAX_NLEN];
740 +    u_int16_t invert;
741 +    u_int16_t len;
742 +};
743 +
744 +#endif /* _IPT_STRING_H */
745 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc1/include/linux/netfilter_ipv4.h
746 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4.h  2004-04-16 08:59:08.000000000 +0200
747 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv4.h      2004-04-16 09:17:09.000000000 +0200
748 @@ -7,6 +7,8 @@
749  
750  #include <linux/config.h>
751  #include <linux/netfilter.h>
752 +#include <linux/netdevice.h>
753 +#include <net/protocol.h>
754  
755  /* IP Cache bits. */
756  /* Src IP address. */
757 @@ -85,6 +87,58 @@
758     Returns true or false. */
759  extern int skb_ip_make_writable(struct sk_buff **pskb,
760                                 unsigned int writable_len);
761 +
762 +#ifdef CONFIG_XFRM
763 +#include <net/route.h>
764 +#include <net/xfrm.h>
765 +
766 +static inline int nf_hook_input_cond(struct sk_buff *skb)
767 +{
768 +       return !skb->sp || skb->sp->decap_done;
769 +}
770 +
771 +static inline int
772 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
773 +{
774 +       return skb->sp && !skb->sp->decap_done
775 +              && (!ipprot || !ipprot->xfrm_prot);
776 +}
777 +
778 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
779 +{
780 +       return skb->sp && !skb->sp->decap_done
781 +              && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
782 +}
783 +
784 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
785 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
786 +#else /* CONFIG_XFRM */
787 +static inline int nf_hook_input_cond(struct sk_buff *skb)
788 +{
789 +       return 1;
790 +}
791 +
792 +static inline int
793 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
794 +{
795 +       return 0;
796 +}
797 +
798 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
799 +{
800 +       return 0;
801 +}
802 +
803 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
804 +{
805 +       return 0;
806 +}
807 +
808 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
809 +{
810 +       return 0; 
811 +}
812 +#endif /* CONFIG_XFRM */
813  #endif /*__KERNEL__*/
814  
815  #endif /*__LINUX_IP_NETFILTER_H*/
816 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_ROUTE.h
817 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h       1970-01-01 01:00:00.000000000 +0100
818 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_ROUTE.h   2004-04-16 09:15:44.000000000 +0200
819 @@ -0,0 +1,22 @@
820 +/* Header file for iptables ip6t_ROUTE target
821 + *
822 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
823 + *
824 + * This software is distributed under GNU GPL v2, 1991
825 + */
826 +#ifndef _IPT_ROUTE_H_target
827 +#define _IPT_ROUTE_H_target
828 +
829 +#define IP6T_ROUTE_IFNAMSIZ 16
830 +
831 +struct ip6t_route_target_info {
832 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
833 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
834 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
835 +       u_int8_t  flags;
836 +};
837 +
838 +/* Values for "flags" field */
839 +#define IP6T_ROUTE_CONTINUE        0x01
840 +
841 +#endif /*_IP6T_ROUTE_H_target*/
842 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_owner.h
843 --- linux-2.6.6-rc1.org/include/linux/netfilter_ipv6/ip6t_owner.h       2004-04-15 03:35:08.000000000 +0200
844 +++ linux-2.6.6-rc1/include/linux/netfilter_ipv6/ip6t_owner.h   2004-04-16 09:18:17.000000000 +0200
845 @@ -6,12 +6,14 @@
846  #define IP6T_OWNER_GID 0x02
847  #define IP6T_OWNER_PID 0x04
848  #define IP6T_OWNER_SID 0x08
849 +#define IP6T_OWNER_COMM 0x10
850  
851  struct ip6t_owner_info {
852      uid_t uid;
853      gid_t gid;
854      pid_t pid;
855      pid_t sid;
856 +    char comm[16];
857      u_int8_t match, invert;    /* flags */
858  };
859  
860 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/ip.h linux-2.6.6-rc1/include/net/ip.h
861 --- linux-2.6.6-rc1.org/include/net/ip.h        2004-04-15 03:35:18.000000000 +0200
862 +++ linux-2.6.6-rc1/include/net/ip.h    2004-04-16 09:17:07.000000000 +0200
863 @@ -30,6 +30,8 @@
864  #include <linux/netdevice.h>
865  #include <linux/inetdevice.h>
866  #include <linux/in_route.h>
867 +#include <linux/netfilter.h>
868 +#include <linux/netfilter_ipv4.h>
869  #include <net/route.h>
870  #include <net/arp.h>
871  
872 @@ -48,6 +50,7 @@
873  #define IPSKB_TRANSLATED       2
874  #define IPSKB_FORWARDED                4
875  #define IPSKB_XFRM_TUNNEL_SIZE 8
876 +#define IPSKB_XFRM_TRANSFORMED 16
877  };
878  
879  struct ipcm_cookie
880 @@ -212,6 +215,12 @@
881                 __ip_select_ident(iph, dst, more);
882  }
883  
884 +extern inline int ip_dst_output(struct sk_buff *skb)
885 +{
886 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
887 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
888 +}
889 +
890  /*
891   *     Map a multicast IP onto multicast MAC for type ethernet.
892   */
893 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/protocol.h linux-2.6.6-rc1/include/net/protocol.h
894 --- linux-2.6.6-rc1.org/include/net/protocol.h  2004-04-15 03:34:36.000000000 +0200
895 +++ linux-2.6.6-rc1/include/net/protocol.h      2004-04-16 09:17:09.000000000 +0200
896 @@ -39,6 +39,7 @@
897         int                     (*handler)(struct sk_buff *skb);
898         void                    (*err_handler)(struct sk_buff *skb, u32 info);
899         int                     no_policy;
900 +       int                     xfrm_prot;
901  };
902  
903  #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
904 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/tcp.h linux-2.6.6-rc1/include/net/tcp.h
905 --- linux-2.6.6-rc1.org/include/net/tcp.h       2004-04-15 03:33:55.000000000 +0200
906 +++ linux-2.6.6-rc1/include/net/tcp.h   2004-04-16 09:18:14.000000000 +0200
907 @@ -162,6 +162,7 @@
908  extern void tcp_bucket_unlock(struct sock *sk);
909  extern int tcp_port_rover;
910  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
911 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
912  
913  /* These are AF independent. */
914  static __inline__ int tcp_bhashfn(__u16 lport)
915 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/udp.h linux-2.6.6-rc1/include/net/udp.h
916 --- linux-2.6.6-rc1.org/include/net/udp.h       2004-04-15 03:35:20.000000000 +0200
917 +++ linux-2.6.6-rc1/include/net/udp.h   2004-04-16 09:18:14.000000000 +0200
918 @@ -74,6 +74,8 @@
919  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
920  extern int     udp_disconnect(struct sock *sk, int flags);
921  
922 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
923 +
924  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
925  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
926  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
927 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/xfrm.h linux-2.6.6-rc1/include/net/xfrm.h
928 --- linux-2.6.6-rc1.org/include/net/xfrm.h      2004-04-15 03:35:36.000000000 +0200
929 +++ linux-2.6.6-rc1/include/net/xfrm.h  2004-04-16 09:17:09.000000000 +0200
930 @@ -540,6 +540,9 @@
931  {
932         atomic_t                refcnt;
933         int                     len;
934 +#ifdef CONFIG_NETFILTER
935 +       int                     decap_done;
936 +#endif
937         struct sec_decap_state  x[XFRM_MAX_DEPTH];
938  };
939  
940 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/core/netfilter.c linux-2.6.6-rc1/net/core/netfilter.c
941 --- linux-2.6.6-rc1.org/net/core/netfilter.c    2004-04-16 08:59:08.000000000 +0200
942 +++ linux-2.6.6-rc1/net/core/netfilter.c        2004-04-16 09:17:13.000000000 +0200
943 @@ -27,6 +27,8 @@
944  #include <linux/icmp.h>
945  #include <net/sock.h>
946  #include <net/route.h>
947 +#include <net/xfrm.h>
948 +#include <net/ip.h>
949  #include <linux/ip.h>
950  
951  /* In this code, we can be waiting indefinitely for userspace to
952 @@ -638,7 +640,6 @@
953  #ifdef CONFIG_IP_ROUTE_FWMARK
954                 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
955  #endif
956 -               fl.proto = iph->protocol;
957                 if (ip_route_output_key(&rt, &fl) != 0)
958                         return -1;
959  
960 @@ -665,6 +666,20 @@
961         if ((*pskb)->dst->error)
962                 return -1;
963  
964 +#ifdef CONFIG_XFRM
965 +       if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
966 +               struct xfrm_policy_afinfo *afinfo;
967 +
968 +               afinfo = xfrm_policy_get_afinfo(AF_INET);
969 +               if (afinfo != NULL) {
970 +                       afinfo->decode_session(*pskb, &fl);
971 +                       xfrm_policy_put_afinfo(afinfo);
972 +                       if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
973 +                               return -1;
974 +               }
975 +       }
976 +#endif
977 +
978         /* Change in oif may mean change in hh_len. */
979         hh_len = (*pskb)->dst->dev->hard_header_len;
980         if (skb_headroom(*pskb) < hh_len) {
981 @@ -682,6 +697,71 @@
982         return 0;
983  }
984  
985 +#ifdef CONFIG_XFRM
986 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
987 +{
988 +       skb->sp->decap_done = 1;
989 +       dst_release(skb->dst);
990 +       skb->dst = NULL;
991 +       nf_reset(skb);
992 +       return netif_rx(skb);
993 +}
994 +
995 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
996 +{
997 +       __skb_push(skb, skb->data - skb->nh.raw);
998 +       /* Fix header len and checksum if last xfrm was transport mode */
999 +       if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
1000 +               skb->nh.iph->tot_len = htons(skb->len);
1001 +               ip_send_check(skb->nh.iph);
1002 +       }
1003 +       return nf_rcv_postxfrm_nonlocal(skb);
1004 +}
1005 +
1006 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1007 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1008 +#include <linux/netfilter_ipv4/ip_nat.h>
1009 +
1010 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
1011 +{
1012 +       struct ip_conntrack *ct;
1013 +       struct ip_conntrack_tuple *t;
1014 +       struct ip_nat_info_manip *m;
1015 +       unsigned int i;
1016 +
1017 +       if (skb->nfct == NULL)
1018 +               return;
1019 +       ct = (struct ip_conntrack *)skb->nfct->master;
1020 +
1021 +       for (i = 0; i < ct->nat.info.num_manips; i++) {
1022 +               m = &ct->nat.info.manips[i];
1023 +               t = &ct->tuplehash[m->direction].tuple;
1024 +
1025 +               switch (m->hooknum) {
1026 +               case NF_IP_PRE_ROUTING:
1027 +                       if (m->maniptype != IP_NAT_MANIP_DST)
1028 +                               break;
1029 +                       fl->fl4_dst = t->dst.ip;
1030 +                       if (t->dst.protonum == IPPROTO_TCP ||
1031 +                           t->dst.protonum == IPPROTO_UDP)
1032 +                               fl->fl_ip_dport = t->dst.u.tcp.port;
1033 +                       break;
1034 +#ifdef CONFIG_IP_NF_NAT_LOCAL
1035 +               case NF_IP_LOCAL_IN:
1036 +                       if (m->maniptype != IP_NAT_MANIP_SRC)
1037 +                               break;
1038 +                       fl->fl4_src = t->src.ip;
1039 +                       if (t->dst.protonum == IPPROTO_TCP ||
1040 +                           t->dst.protonum == IPPROTO_UDP)
1041 +                               fl->fl_ip_sport = t->src.u.tcp.port;
1042 +                       break;
1043 +#endif
1044 +               }
1045 +       }
1046 +}
1047 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
1048 +#endif
1049 +
1050  int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
1051  {
1052         struct sk_buff *nskb;
1053 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ah4.c linux-2.6.6-rc1/net/ipv4/ah4.c
1054 --- linux-2.6.6-rc1.org/net/ipv4/ah4.c  2004-04-15 03:35:37.000000000 +0200
1055 +++ linux-2.6.6-rc1/net/ipv4/ah4.c      2004-04-16 09:17:09.000000000 +0200
1056 @@ -145,6 +145,7 @@
1057                 err = -EHOSTUNREACH;
1058                 goto error_nolock;
1059         }
1060 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1061         return NET_XMIT_BYPASS;
1062  
1063  error:
1064 @@ -343,6 +344,7 @@
1065         .handler        =       xfrm4_rcv,
1066         .err_handler    =       ah4_err,
1067         .no_policy      =       1,
1068 +       .xfrm_prot      =       1,
1069  };
1070  
1071  static int __init ah4_init(void)
1072 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/esp4.c linux-2.6.6-rc1/net/ipv4/esp4.c
1073 --- linux-2.6.6-rc1.org/net/ipv4/esp4.c 2004-04-15 03:35:04.000000000 +0200
1074 +++ linux-2.6.6-rc1/net/ipv4/esp4.c     2004-04-16 09:17:09.000000000 +0200
1075 @@ -199,6 +199,7 @@
1076                 err = -EHOSTUNREACH;
1077                 goto error_nolock;
1078         }
1079 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1080         return NET_XMIT_BYPASS;
1081  
1082  error:
1083 @@ -576,6 +577,7 @@
1084         .handler        =       xfrm4_rcv,
1085         .err_handler    =       esp4_err,
1086         .no_policy      =       1,
1087 +       .xfrm_prot      =       1,
1088  };
1089  
1090  static int __init esp4_init(void)
1091 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/igmp.c linux-2.6.6-rc1/net/ipv4/igmp.c
1092 --- linux-2.6.6-rc1.org/net/ipv4/igmp.c 2004-04-15 03:36:01.000000000 +0200
1093 +++ linux-2.6.6-rc1/net/ipv4/igmp.c     2004-04-16 09:17:07.000000000 +0200
1094 @@ -342,7 +342,7 @@
1095         pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
1096  
1097         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
1098 -                      dst_output);
1099 +                      ip_dst_output);
1100  }
1101  
1102  static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
1103 @@ -672,7 +672,7 @@
1104         ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
1105  
1106         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1107 -                      dst_output);
1108 +                      ip_dst_output);
1109  }
1110  
1111  static void igmp_gq_timer_expire(unsigned long data)
1112 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ip_forward.c linux-2.6.6-rc1/net/ipv4/ip_forward.c
1113 --- linux-2.6.6-rc1.org/net/ipv4/ip_forward.c   2004-04-15 03:33:50.000000000 +0200
1114 +++ linux-2.6.6-rc1/net/ipv4/ip_forward.c       2004-04-16 09:17:07.000000000 +0200
1115 @@ -51,7 +51,7 @@
1116         if (unlikely(opt->optlen))
1117                 ip_forward_options(skb);
1118  
1119 -       return dst_output(skb);
1120 +       return ip_dst_output(skb);
1121  }
1122  
1123  int ip_forward(struct sk_buff *skb)
1124 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ip_input.c linux-2.6.6-rc1/net/ipv4/ip_input.c
1125 --- linux-2.6.6-rc1.org/net/ipv4/ip_input.c     2004-04-16 08:59:08.000000000 +0200
1126 +++ linux-2.6.6-rc1/net/ipv4/ip_input.c 2004-04-16 09:17:13.000000000 +0200
1127 @@ -206,10 +206,6 @@
1128  
1129         __skb_pull(skb, ihl);
1130  
1131 -       /* Free reference early: we don't need it any more, and it may
1132 -           hold ip_conntrack module loaded indefinitely. */
1133 -       nf_reset(skb);
1134 -
1135          /* Point into the IP datagram, just past the header. */
1136          skb->h.raw = skb->data;
1137  
1138 @@ -224,6 +220,13 @@
1139         resubmit:
1140                 hash = protocol & (MAX_INET_PROTOS - 1);
1141                 raw_sk = sk_head(&raw_v4_htable[hash]);
1142 +               ipprot = inet_protos[hash];
1143 +               smp_read_barrier_depends();
1144 +
1145 +               if (nf_xfrm_local_done(skb, ipprot)) {
1146 +                       nf_rcv_postxfrm_local(skb);
1147 +                       goto out;
1148 +               }
1149  
1150                 /* If there maybe a raw socket we must check - if not we
1151                  * don't care less
1152 @@ -231,14 +234,15 @@
1153                 if (raw_sk)
1154                         raw_v4_input(skb, skb->nh.iph, hash);
1155  
1156 -               if ((ipprot = inet_protos[hash]) != NULL) {
1157 +               if (ipprot != NULL) {
1158                         int ret;
1159  
1160 -                       smp_read_barrier_depends();
1161 -                       if (!ipprot->no_policy &&
1162 -                           !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1163 -                               kfree_skb(skb);
1164 -                               goto out;
1165 +                       if (!ipprot->no_policy) {
1166 +                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1167 +                                       kfree_skb(skb);
1168 +                                       goto out;
1169 +                               }
1170 +                               nf_reset(skb);
1171                         }
1172                         ret = ipprot->handler(skb);
1173                         if (ret < 0) {
1174 @@ -279,8 +283,8 @@
1175                         return 0;
1176         }
1177  
1178 -       return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1179 -                      ip_local_deliver_finish);
1180 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1181 +                           ip_local_deliver_finish, nf_hook_input_cond(skb));
1182  }
1183  
1184  static inline int ip_rcv_finish(struct sk_buff *skb)
1185 @@ -297,6 +301,9 @@
1186                         goto drop; 
1187         }
1188  
1189 +       if (nf_xfrm_nonlocal_done(skb))
1190 +               return nf_rcv_postxfrm_nonlocal(skb);
1191 +
1192  #ifdef CONFIG_NET_CLS_ROUTE
1193         if (skb->dst->tclassid) {
1194                 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
1195 @@ -418,8 +425,8 @@
1196                 }
1197         }
1198  
1199 -       return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1200 -                      ip_rcv_finish);
1201 +       return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1202 +                           ip_rcv_finish, nf_hook_input_cond(skb));
1203  
1204  inhdr_error:
1205         IP_INC_STATS_BH(IpInHdrErrors);
1206 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ip_output.c linux-2.6.6-rc1/net/ipv4/ip_output.c
1207 --- linux-2.6.6-rc1.org/net/ipv4/ip_output.c    2004-04-15 03:36:01.000000000 +0200
1208 +++ linux-2.6.6-rc1/net/ipv4/ip_output.c        2004-04-16 09:17:07.000000000 +0200
1209 @@ -123,6 +123,15 @@
1210         return ttl;
1211  }
1212  
1213 +#ifdef CONFIG_NETFILTER
1214 +/* out-of-line copy is only required with netfilter */
1215 +int ip_dst_output(struct sk_buff *skb)
1216 +{
1217 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1218 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1219 +}
1220 +#endif
1221 +
1222  /* 
1223   *             Add an ip header to a skbuff and send it out.
1224   *
1225 @@ -165,7 +174,7 @@
1226  
1227         /* Send it out. */
1228         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1229 -                      dst_output);
1230 +                      ip_dst_output);
1231  }
1232  
1233  static inline int ip_finish_output2(struct sk_buff *skb)
1234 @@ -283,7 +292,7 @@
1235                 return ip_finish_output(skb);
1236  }
1237  
1238 -int ip_output(struct sk_buff *skb)
1239 +static inline int ip_output2(struct sk_buff *skb)
1240  {
1241         IP_INC_STATS(IpOutRequests);
1242  
1243 @@ -294,6 +303,16 @@
1244                 return ip_finish_output(skb);
1245  }
1246  
1247 +int ip_output(struct sk_buff *skb)
1248 +{
1249 +       int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
1250 +
1251 +       if (transformed)
1252 +               nf_reset(skb);
1253 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1254 +                           skb->dst->dev, ip_output2, transformed);
1255 +}
1256 +
1257  int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
1258  {
1259         struct sock *sk = skb->sk;
1260 @@ -387,7 +406,7 @@
1261         skb->priority = sk->sk_priority;
1262  
1263         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1264 -                      dst_output);
1265 +                      ip_dst_output);
1266  
1267  no_route:
1268         IP_INC_STATS(IpOutNoRoutes);
1269 @@ -1177,7 +1196,7 @@
1270  
1271         /* Netfilter gets whole the not fragmented skb. */
1272         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
1273 -                     skb->dst->dev, dst_output);
1274 +                     skb->dst->dev, ip_dst_output);
1275         if (err) {
1276                 if (err > 0)
1277                         err = inet->recverr ? net_xmit_errno(err) : 0;
1278 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ipcomp.c linux-2.6.6-rc1/net/ipv4/ipcomp.c
1279 --- linux-2.6.6-rc1.org/net/ipv4/ipcomp.c       2004-04-15 03:35:37.000000000 +0200
1280 +++ linux-2.6.6-rc1/net/ipv4/ipcomp.c   2004-04-16 09:17:09.000000000 +0200
1281 @@ -231,6 +231,7 @@
1282                 err = -EHOSTUNREACH;
1283                 goto error_nolock;
1284         }
1285 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1286         err = NET_XMIT_BYPASS;
1287  
1288  out_exit:
1289 @@ -407,6 +408,7 @@
1290         .handler        =       xfrm4_rcv,
1291         .err_handler    =       ipcomp4_err,
1292         .no_policy      =       1,
1293 +       .xfrm_prot      =       1,
1294  };
1295  
1296  static int __init ipcomp4_init(void)
1297 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ipip.c linux-2.6.6-rc1/net/ipv4/ipip.c
1298 --- linux-2.6.6-rc1.org/net/ipv4/ipip.c 2004-04-16 08:59:08.000000000 +0200
1299 +++ linux-2.6.6-rc1/net/ipv4/ipip.c     2004-04-16 09:17:09.000000000 +0200
1300 @@ -478,6 +478,11 @@
1301  
1302         read_lock(&ipip_lock);
1303         if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
1304 +               /* IPIP packets decapsulated by IPsec missed netfilter hooks */
1305 +               if (nf_xfrm_local_done(skb, NULL)) {
1306 +                       nf_rcv_postxfrm_local(skb);
1307 +                       return 0;
1308 +               }
1309                 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1310                         kfree_skb(skb);
1311                         return 0;
1312 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/ipmr.c linux-2.6.6-rc1/net/ipv4/ipmr.c
1313 --- linux-2.6.6-rc1.org/net/ipv4/ipmr.c 2004-04-15 03:34:48.000000000 +0200
1314 +++ linux-2.6.6-rc1/net/ipv4/ipmr.c     2004-04-16 09:17:07.000000000 +0200
1315 @@ -1120,7 +1120,7 @@
1316         if (unlikely(opt->optlen))
1317                 ip_forward_options(skb);
1318  
1319 -       return dst_output(skb);
1320 +       return ip_dst_output(skb);
1321  }
1322  
1323  /*
1324 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc1/net/ipv4/netfilter/Kconfig
1325 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/Kconfig      2004-04-16 08:59:09.000000000 +0200
1326 +++ linux-2.6.6-rc1/net/ipv4/netfilter/Kconfig  2004-04-16 09:19:38.000000000 +0200
1327 @@ -206,6 +206,11 @@
1328  
1329           To compile it as a module, choose M here.  If unsure, say N.
1330  
1331 +config IP_NF_MATCH_UNCLEAN
1332 +       tristate  'unclean match support (EXPERIMENTAL)'
1333 +       depends on EXPERIMENTAL && IP_NF_IPTABLES
1334 +         help
1335 +
1336  config IP_NF_MATCH_TTL
1337         tristate "TTL match support"
1338         depends on IP_NF_IPTABLES
1339 @@ -510,6 +515,38 @@
1340  
1341           To compile it as a module, choose M here.  If unsure, say N.
1342  
1343 +config IP_NF_TARGET_TARPIT
1344 +       tristate "TARPIT target support"
1345 +       depends on IP_NF_IPTABLES
1346 +       ---help---
1347 +         Adds a TARPIT target to iptables, which captures and holds
1348 +         incoming TCP connections using no local per-connection resources.
1349 +         Connections are accepted, but immediately switched to the persist
1350 +         state (0 byte window), in which the remote side stops sending data
1351 +         and asks to continue every 60-240 seconds.  Attempts to close the
1352 +         connection are ignored, forcing the remote side to time out the
1353 +         connection in 12-24 minutes.
1354 +
1355 +         This offers similar functionality to LaBrea
1356 +         <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
1357 +         hardware or IPs.  Any TCP port that you would normally DROP or REJECT
1358 +         can instead become a tarpit.
1359 +
1360 +         To tarpit connections to TCP port 80 destined for the current machine:
1361 +
1362 +           iptables -A INPUT -p tcp -m tcp --dport 80 -j TARPIT
1363 +
1364 +         To significantly slow down Code Red/Nimda-style scans of unused
1365 +         address space, forward unused ip addresses to a Linux box not acting
1366 +         as a router (e.g. "ip route 10.0.0.0 255.0.0.0 ip.of.linux.box" on a Cisco),
1367 +         enable IP forwarding on the Linux box, and add:
1368 +
1369 +           iptables -A FORWARD -p tcp -j TARPIT
1370 +           iptables -A FORWARD -j DROP
1371 +
1372 +         You probably don't want the conntrack module loaded while you are using
1373 +         TARPIT, or you will be using resources per connection.
1374 +
1375  config IP_NF_TARGET_TCPMSS
1376         tristate "TCPMSS target support"
1377         depends on IP_NF_IPTABLES
1378 @@ -706,5 +743,114 @@
1379         depends on IP_NF_IPTABLES
1380           help
1381  
1382 +config IP_NF_CONNTRACK_MARK
1383 +       bool  'Connection mark tracking support'
1384 +config IP_NF_TARGET_CONNMARK
1385 +       tristate  'CONNMARK target support'
1386 +       depends on IP_NF_MANGLE
1387 +config IP_NF_MATCH_CONNMARK
1388 +       tristate  ' Connection mark match support'
1389 +       depends on IP_NF_IPTABLES
1390 +         help
1391 +
1392 +config IP_NF_TARGET_IPMARK
1393 +       tristate  'IPMARK target support'
1394 +       depends on IP_NF_MANGLE
1395 +         help
1396 +
1397 +config IP_NF_TARGET_ROUTE
1398 +       tristate  'ROUTE target support'
1399 +       depends on IP_NF_MANGLE
1400 +         help
1401 +
1402 +config IP_NF_TARGET_TCPLAG
1403 +       tristate  'TCPLAG target support'
1404 +       depends on IP_NF_IPTABLES
1405 +         help
1406 +
1407 +config IP_NF_TARGET_XOR
1408 +       tristate  'XOR target support'
1409 +       depends on IP_NF_MANGLE
1410 +         help
1411 +
1412 +config IP_NF_MATCH_ADDRTYPE
1413 +       tristate  'address type match support'
1414 +       depends on IP_NF_IPTABLES
1415 +         help
1416 +
1417 +config IP_NF_NAT_H323
1418 +       tristate
1419 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1420 +       default IP_NF_NAT if IP_NF_H323=y
1421 +       default m if IP_NF_H323=m
1422 +
1423 +config IP_NF_H323
1424 +       tristate  'H.323 (netmeeting) support'
1425 +       depends on IP_NF_CONNTRACK
1426 +         help
1427 +
1428 +config IP_NF_NAT_MMS
1429 +       tristate
1430 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1431 +       default IP_NF_NAT if IP_NF_MMS=y
1432 +       default m if IP_NF_MMS=m
1433 +
1434 +config IP_NF_MMS
1435 +       tristate  'MMS protocol support'
1436 +       depends on IP_NF_CONNTRACK
1437 +         help
1438 +
1439 +config IP_NF_MATCH_POLICY
1440 +       tristate "IPsec policy match support"
1441 +       depends on IP_NF_IPTABLES && XFRM
1442 +       help
1443 +         Policy matching allows you to match packets based on the
1444 +         IPsec policy that was used during decapsulation/will
1445 +         be used during encapsulation.
1446 +
1447 +         To compile it as a module, choose M here.  If unsure, say N.
1448 +         help
1449 +
1450 +config IP_NF_NAT_QUAKE3
1451 +       tristate
1452 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1453 +       default IP_NF_NAT if IP_NF_QUAKE3=y
1454 +       default m if IP_NF_QUAKE3=m
1455 +
1456 +config IP_NF_QUAKE3
1457 +       tristate "Quake3 protocol support"
1458 +       depends on IP_NF_CONNTRACK
1459 +         help
1460 +
1461 +config IP_NF_MATCH_RPC
1462 +       tristate  'RPC match support'
1463 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1464 +         help
1465 +
1466 +config IP_NF_RSH
1467 +       tristate  'RSH protocol support'
1468 +       depends on IP_NF_CONNTRACK
1469 +         help
1470 +
1471 +config IP_NF_CT_PROTO_SCTP
1472 +       tristate  'SCTP protocol connection tracking support'
1473 +       depends on IP_NF_CONNTRACK
1474 +         help
1475 +
1476 +config IP_NF_NAT_TALK
1477 +       tristate
1478 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1479 +       default IP_NF_NAT if IP_NF_TALK=y
1480 +       default m if IP_NF_TALK=m
1481 +config IP_NF_TALK
1482 +       tristate  'talk protocol support'
1483 +       depends on IP_NF_CONNTRACK
1484 +         help
1485 +
1486 +config IP_NF_MATCH_STRING
1487 +       tristate  'String match support'
1488 +       depends on IP_NF_IPTABLES
1489 +         help
1490 +
1491  endmenu
1492  
1493 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc1/net/ipv4/netfilter/Makefile
1494 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/Makefile     2004-04-16 08:59:09.000000000 +0200
1495 +++ linux-2.6.6-rc1/net/ipv4/netfilter/Makefile 2004-04-16 09:19:38.000000000 +0200
1496 @@ -19,10 +19,39 @@
1497  # connection tracking
1498  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1499  
1500 +# talk protocol support
1501 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1502 +ifdef CONFIG_IP_NF_TALK
1503 +       export-objs += ip_conntrack_talk.o
1504 +endif
1505 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1506 +
1507 +
1508 +# SCTP protocol connection tracking
1509 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
1510
1511 +# H.323 support
1512 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1513 +ifdef CONFIG_IP_NF_H323
1514 +       export-objs += ip_conntrack_h323.o
1515 +endif
1516 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1517 +
1518 +
1519  # connection tracking helpers
1520 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1521 +ifdef CONFIG_IP_NF_NAT_QUAKE3
1522 +       export-objs += ip_conntrack_quake3.o
1523 +endif
1524 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1525 +ifdef CONFIG_IP_NF_MMS
1526 +       export-objs += ip_conntrack_mms.o
1527 +endif
1528  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1529  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1530  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1531 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1532 +
1533  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1534  
1535  # NAT helpers 
1536 @@ -30,6 +59,8 @@
1537  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1538  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1539  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1540 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1541 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1542  
1543  # generic IP tables 
1544  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1545 @@ -41,6 +72,9 @@
1546  obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1547  
1548  # matches
1549 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1550 +export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
1551 +
1552  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1553  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1554  obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1555 @@ -87,14 +121,19 @@
1556  obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1557  
1558  
1559 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
1560 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
1561  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1562  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1563 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
1564  obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1565  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1566  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1567 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
1568  obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1569  
1570  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1571 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
1572  
1573  # targets
1574  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
1575 @@ -102,18 +141,24 @@
1576  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
1577  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
1578  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
1579 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
1580  obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
1581  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
1582  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
1583 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
1584  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
1585  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
1586  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1587  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1588  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1589 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
1590 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
1591 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
1592  obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1593  obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1594  obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1595  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1596 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
1597  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1598  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
1599  
1600 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_core.c
1601 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_core.c  2004-04-16 08:59:08.000000000 +0200
1602 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_core.c      2004-04-16 09:15:41.000000000 +0200
1603 @@ -717,6 +717,9 @@
1604                  __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1605                  conntrack->master = expected;
1606                  expected->sibling = conntrack;
1607 +#if CONFIG_IP_NF_CONNTRACK_MARK
1608 +               conntrack->mark = expected->expectant->mark;
1609 +#endif
1610                  LIST_DELETE(&ip_conntrack_expect_list, expected);
1611                  expected->expectant->expecting--;
1612                  nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1613 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_h323.c
1614 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_h323.c  1970-01-01 01:00:00.000000000 +0100
1615 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_h323.c      2004-04-16 09:17:05.000000000 +0200
1616 @@ -0,0 +1,308 @@
1617 +/* 
1618 + * H.323 'brute force' extension for H.323 connection tracking. 
1619 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
1620 + *
1621 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
1622 + * (http://www.coritel.it/projects/sofia/nat/)
1623 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
1624 + * the unregistered helpers to the conntrack entries.
1625 + */
1626 +
1627 +
1628 +#include <linux/module.h>
1629 +#include <linux/netfilter.h>
1630 +#include <linux/ip.h>
1631 +#include <net/checksum.h>
1632 +#include <net/tcp.h>
1633 +
1634 +#include <linux/netfilter_ipv4/lockhelp.h>
1635 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1636 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
1637 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1638 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
1639 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
1640 +
1641 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
1642 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
1643 +MODULE_LICENSE("GPL");
1644 +
1645 +DECLARE_LOCK(ip_h323_lock);
1646 +struct module *ip_conntrack_h323 = THIS_MODULE;
1647 +
1648 +#if 0
1649 +#define DEBUGP printk
1650 +#else
1651 +#define DEBUGP(format, args...)
1652 +#endif
1653 +
1654 +/* FIXME: This should be in userspace.  Later. */
1655 +static int h245_help(const struct iphdr *iph, size_t len,
1656 +                    struct ip_conntrack *ct,
1657 +                    enum ip_conntrack_info ctinfo)
1658 +{
1659 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
1660 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
1661 +       unsigned char *data_limit;
1662 +       u_int32_t tcplen = len - iph->ihl * 4;
1663 +       u_int32_t datalen = tcplen - tcph->doff * 4;
1664 +       int dir = CTINFO2DIR(ctinfo);
1665 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
1666 +       struct ip_conntrack_expect expect, *exp = &expect;
1667 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
1668 +       u_int16_t data_port;
1669 +       u_int32_t data_ip;
1670 +       unsigned int i;
1671 +
1672 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1673 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
1674 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
1675 +
1676 +       /* Can't track connections formed before we registered */
1677 +       if (!info)
1678 +               return NF_ACCEPT;
1679 +               
1680 +       /* Until there's been traffic both ways, don't look in packets. */
1681 +       if (ctinfo != IP_CT_ESTABLISHED
1682 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1683 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
1684 +               return NF_ACCEPT;
1685 +       }
1686 +
1687 +       /* Not whole TCP header or too short packet? */
1688 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
1689 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
1690 +               return NF_ACCEPT;
1691 +       }
1692 +
1693 +       /* Checksum invalid?  Ignore. */
1694 +       /* FIXME: Source route IP option packets --RR */
1695 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1696 +                             csum_partial((char *)tcph, tcplen, 0))) {
1697 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
1698 +                      tcph, tcplen, NIPQUAD(iph->saddr),
1699 +                      NIPQUAD(iph->daddr));
1700 +               return NF_ACCEPT;
1701 +       }
1702 +
1703 +       data_limit = (unsigned char *) data + datalen;
1704 +       /* bytes: 0123   45
1705 +                 ipadrr port */
1706 +       for (i = 0; data < (data_limit - 5); data++, i++) {
1707 +               data_ip = *((u_int32_t *)data);
1708 +               if (data_ip == iph->saddr) {
1709 +                       data_port = *((u_int16_t *)(data + 4));
1710 +                       memset(&expect, 0, sizeof(expect));
1711 +                       /* update the H.225 info */
1712 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
1713 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
1714 +                               NIPQUAD(iph->saddr), ntohs(data_port));
1715 +                       LOCK_BH(&ip_h323_lock);
1716 +                       info->is_h225 = H225_PORT + 1;
1717 +                       exp_info->port = data_port;
1718 +                       exp_info->dir = dir;
1719 +                       exp_info->offset = i;
1720 +
1721 +                       exp->seq = ntohl(tcph->seq) + i;
1722 +                   
1723 +                       exp->tuple = ((struct ip_conntrack_tuple)
1724 +                               { { ct->tuplehash[!dir].tuple.src.ip,
1725 +                                   { 0 } },
1726 +                                 { data_ip,
1727 +                                   { .tcp = { data_port } },
1728 +                                   IPPROTO_UDP }});
1729 +                       exp->mask = ((struct ip_conntrack_tuple)
1730 +                               { { 0xFFFFFFFF, { 0 } },
1731 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
1732 +       
1733 +                       exp->expectfn = NULL;
1734 +                       
1735 +                       /* Ignore failure; should only happen with NAT */
1736 +                       ip_conntrack_expect_related(ct, exp);
1737 +
1738 +                       UNLOCK_BH(&ip_h323_lock);
1739 +               }
1740 +       }
1741 +
1742 +       return NF_ACCEPT;
1743 +
1744 +}
1745 +
1746 +/* H.245 helper is not registered! */
1747 +static struct ip_conntrack_helper h245 = 
1748 +       { { NULL, NULL },
1749 +          "H.245",                             /* name */
1750 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
1751 +          NULL,                                        /* module */
1752 +          8,                                   /* max_ expected */
1753 +          240,                                 /* timeout */
1754 +          { { 0, { 0 } },                      /* tuple */
1755 +            { 0, { 0 }, IPPROTO_TCP } },
1756 +          { { 0, { 0xFFFF } },                 /* mask */
1757 +            { 0, { 0 }, 0xFFFF } },
1758 +          h245_help                            /* helper */
1759 +       };
1760 +
1761 +static int h225_expect(struct ip_conntrack *ct)
1762 +{
1763 +       WRITE_LOCK(&ip_conntrack_lock);
1764 +       ct->helper = &h245;
1765 +       DEBUGP("h225_expect: helper for %p added\n", ct);
1766 +       WRITE_UNLOCK(&ip_conntrack_lock);
1767 +       
1768 +       return NF_ACCEPT;       /* unused */
1769 +}
1770 +
1771 +/* FIXME: This should be in userspace.  Later. */
1772 +static int h225_help(const struct iphdr *iph, size_t len,
1773 +                    struct ip_conntrack *ct,
1774 +                    enum ip_conntrack_info ctinfo)
1775 +{
1776 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
1777 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
1778 +       unsigned char *data_limit;
1779 +       u_int32_t tcplen = len - iph->ihl * 4;
1780 +       u_int32_t datalen = tcplen - tcph->doff * 4;
1781 +       int dir = CTINFO2DIR(ctinfo);
1782 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
1783 +       struct ip_conntrack_expect expect, *exp = &expect;
1784 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
1785 +       u_int16_t data_port;
1786 +       u_int32_t data_ip;
1787 +       unsigned int i;
1788 +       
1789 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1790 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
1791 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
1792 +
1793 +       /* Can't track connections formed before we registered */
1794 +       if (!info)
1795 +               return NF_ACCEPT;
1796 +
1797 +       /* Until there's been traffic both ways, don't look in packets. */
1798 +       if (ctinfo != IP_CT_ESTABLISHED
1799 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1800 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
1801 +               return NF_ACCEPT;
1802 +       }
1803 +
1804 +       /* Not whole TCP header or too short packet? */
1805 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
1806 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
1807 +               return NF_ACCEPT;
1808 +       }
1809 +
1810 +       /* Checksum invalid?  Ignore. */
1811 +       /* FIXME: Source route IP option packets --RR */
1812 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1813 +                             csum_partial((char *)tcph, tcplen, 0))) {
1814 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
1815 +                      tcph, tcplen, NIPQUAD(iph->saddr),
1816 +                      NIPQUAD(iph->daddr));
1817 +               return NF_ACCEPT;
1818 +       }
1819 +       
1820 +       data_limit = (unsigned char *) data + datalen;
1821 +       /* bytes: 0123   45
1822 +                 ipadrr port */
1823 +       for (i = 0; data < (data_limit - 5); data++, i++) {
1824 +               data_ip = *((u_int32_t *)data);
1825 +               if (data_ip == iph->saddr) {
1826 +                       data_port = *((u_int16_t *)(data + 4));
1827 +                       if (data_port == tcph->source) {
1828 +                               /* Signal address */
1829 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
1830 +                                       NIPQUAD(iph->saddr));
1831 +                               /* Update the H.225 info so that NAT can mangle the address/port
1832 +                                  even when we have no expected connection! */
1833 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1834 +                               LOCK_BH(&ip_h323_lock);
1835 +                               info->dir = dir;
1836 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
1837 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
1838 +                               UNLOCK_BH(&ip_h323_lock);
1839 +#endif
1840 +                       } else {
1841 +                               memset(&expect, 0, sizeof(expect));
1842 +
1843 +                               /* update the H.225 info */
1844 +                               LOCK_BH(&ip_h323_lock);
1845 +                               info->is_h225 = H225_PORT;
1846 +                               exp_info->port = data_port;
1847 +                               exp_info->dir = dir;
1848 +                               exp_info->offset = i;
1849 +
1850 +                               exp->seq = ntohl(tcph->seq) + i;
1851 +
1852 +                               exp->tuple = ((struct ip_conntrack_tuple)
1853 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
1854 +                                           { 0 } },
1855 +                                         { data_ip,
1856 +                                           { .tcp = { data_port } },
1857 +                                           IPPROTO_TCP }});
1858 +                               exp->mask = ((struct ip_conntrack_tuple)
1859 +                                       { { 0xFFFFFFFF, { 0 } },
1860 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
1861 +       
1862 +                               exp->expectfn = h225_expect;
1863 +                               
1864 +                               /* Ignore failure */
1865 +                               ip_conntrack_expect_related(ct, exp);
1866 +
1867 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
1868 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
1869 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
1870 +
1871 +                               UNLOCK_BH(&ip_h323_lock);
1872 +                       }  
1873 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1874 +               } else if (data_ip == iph->daddr) {
1875 +                       data_port = *((u_int16_t *)(data + 4));
1876 +                       if (data_port == tcph->dest) {
1877 +                               /* Signal address */
1878 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
1879 +                                       NIPQUAD(iph->daddr));
1880 +                               /* Update the H.225 info so that NAT can mangle the address/port
1881 +                                  even when we have no expected connection! */
1882 +                               LOCK_BH(&ip_h323_lock);
1883 +                               info->dir = dir;
1884 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
1885 +                               info->offset[IP_CT_DIR_REPLY] = i;
1886 +                               UNLOCK_BH(&ip_h323_lock);
1887 +                       }
1888 +#endif
1889 +               }
1890 +       }
1891 +
1892 +       return NF_ACCEPT;
1893 +
1894 +}
1895 +
1896 +static struct ip_conntrack_helper h225 = 
1897 +       { { NULL, NULL },
1898 +         "H.225",                                      /* name */
1899 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
1900 +         THIS_MODULE,                                  /* module */
1901 +         2,                                            /* max_expected */
1902 +         240,                                          /* timeout */
1903 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
1904 +           { 0, { 0 }, IPPROTO_TCP } },
1905 +         { { 0, { 0xFFFF } },                          /* mask */
1906 +           { 0, { 0 }, 0xFFFF } },
1907 +         h225_help                                     /* helper */
1908 +       };
1909 +
1910 +static int __init init(void)
1911 +{
1912 +       return ip_conntrack_helper_register(&h225);
1913 +}
1914 +
1915 +static void __exit fini(void)
1916 +{
1917 +       /* Unregister H.225 helper */   
1918 +       ip_conntrack_helper_unregister(&h225);
1919 +}
1920 +
1921 +EXPORT_SYMBOL(ip_h323_lock);
1922 +
1923 +module_init(init);
1924 +module_exit(fini);
1925 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_mms.c
1926 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_mms.c   1970-01-01 01:00:00.000000000 +0100
1927 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_mms.c       2004-04-16 09:17:32.000000000 +0200
1928 @@ -0,0 +1,308 @@
1929 +/* MMS extension for IP connection tracking
1930 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
1931 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
1932 + *
1933 + * ip_conntrack_mms.c v0.3 2002-09-22
1934 + *
1935 + *      This program is free software; you can redistribute it and/or
1936 + *      modify it under the terms of the GNU General Public License
1937 + *      as published by the Free Software Foundation; either version
1938 + *      2 of the License, or (at your option) any later version.
1939 + *
1940 + *      Module load syntax:
1941 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
1942 + *
1943 + *      Please give the ports of all MMS servers You wish to connect to.
1944 + *      If you don't specify ports, the default will be TCP port 1755.
1945 + *
1946 + *      More info on MMS protocol, firewalls and NAT:
1947 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
1948 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
1949 + *
1950 + *      The SDP project people are reverse-engineering MMS:
1951 + *      http://get.to/sdp
1952 + */
1953 +
1954 +#include <linux/config.h>
1955 +#include <linux/module.h>
1956 +#include <linux/netfilter.h>
1957 +#include <linux/ip.h>
1958 +#include <linux/ctype.h>
1959 +#include <net/checksum.h>
1960 +#include <net/tcp.h>
1961 +
1962 +#include <linux/netfilter_ipv4/lockhelp.h>
1963 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1964 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
1965 +
1966 +DECLARE_LOCK(ip_mms_lock);
1967 +struct module *ip_conntrack_mms = THIS_MODULE;
1968 +
1969 +#define MAX_PORTS 8
1970 +static int ports[MAX_PORTS];
1971 +static int ports_c;
1972 +#ifdef MODULE_PARM
1973 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
1974 +#endif
1975 +
1976 +#if 0 
1977 +#define DEBUGP printk
1978 +#else
1979 +#define DEBUGP(format, args...)
1980 +#endif
1981 +
1982 +EXPORT_SYMBOL(ip_mms_lock);
1983 +
1984 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
1985 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
1986 +MODULE_LICENSE("GPL");
1987 +
1988 +/* #define isdigit(c) (c >= '0' && c <= '9') */
1989 +
1990 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
1991 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
1992 +{
1993 +       int i;
1994 +       for (i = 0; i < unicode_size; ++i) {
1995 +               string[i] = (char)(unicode[i]);
1996 +       }
1997 +       string[unicode_size] = 0x00;
1998 +}
1999 +
2000 +__inline static int atoi(char *s) 
2001 +{
2002 +       int i=0;
2003 +       while (isdigit(*s)) {
2004 +               i = i*10 + *(s++) - '0';
2005 +       }
2006 +       return i;
2007 +}
2008 +
2009 +/* convert ip address string like "192.168.0.10" to unsigned int */
2010 +__inline static u_int32_t asciiiptoi(char *s)
2011 +{
2012 +       unsigned int i, j, k;
2013 +
2014 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
2015 +               i+=atoi(s);
2016 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
2017 +                       ;
2018 +       }
2019 +       i+=atoi(s);
2020 +       return ntohl(i);
2021 +}
2022 +
2023 +int parse_mms(const char *data, 
2024 +             const unsigned int datalen,
2025 +             u_int32_t *mms_ip,
2026 +             u_int16_t *mms_proto,
2027 +             u_int16_t *mms_port,
2028 +             char **mms_string_b,
2029 +             char **mms_string_e,
2030 +             char **mms_padding_e)
2031 +{
2032 +       int unicode_size, i;
2033 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
2034 +       char getlengthstring[28];
2035 +       
2036 +       for(unicode_size=0; 
2037 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2038 +           unicode_size++)
2039 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
2040 +                       return -1; /* out of bounds - incomplete packet */
2041 +       
2042 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2043 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2044 +       
2045 +       /* IP address ? */
2046 +       *mms_ip = asciiiptoi(tempstring+2);
2047 +       
2048 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2049 +               
2050 +       /* protocol ? */
2051 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
2052 +               *mms_proto = IPPROTO_TCP;
2053 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2054 +               *mms_proto = IPPROTO_UDP;
2055 +
2056 +       /* port ? */
2057 +       *mms_port = atoi(tempstring+7+i);
2058 +
2059 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
2060 +          unicode string, one to the end of the string, and one to the end 
2061 +          of the packet, since we must keep track of the number of bytes 
2062 +          between end of the unicode string and the end of packet (padding) */
2063 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2064 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2065 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2066 +       return 0;
2067 +}
2068 +
2069 +
2070 +/* FIXME: This should be in userspace.  Later. */
2071 +static int help(const struct iphdr *iph, size_t len,
2072 +               struct ip_conntrack *ct,
2073 +               enum ip_conntrack_info ctinfo)
2074 +{
2075 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2076 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2077 +       const char *data = (const char *)tcph + tcph->doff * 4;
2078 +       unsigned int tcplen = len - iph->ihl * 4;
2079 +       unsigned int datalen = tcplen - tcph->doff * 4;
2080 +       int dir = CTINFO2DIR(ctinfo);
2081 +       struct ip_conntrack_expect expect, *exp = &expect; 
2082 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2083 +       
2084 +       u_int32_t mms_ip;
2085 +       u_int16_t mms_proto;
2086 +       char mms_proto_string[8];
2087 +       u_int16_t mms_port;
2088 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
2089 +            
2090 +       /* Until there's been traffic both ways, don't look in packets. */
2091 +       if (ctinfo != IP_CT_ESTABLISHED
2092 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2093 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2094 +               return NF_ACCEPT;
2095 +       }
2096 +
2097 +       /* Not whole TCP header? */
2098 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2099 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2100 +               return NF_ACCEPT;
2101 +       }
2102 +
2103 +       /* Checksum invalid?  Ignore. */
2104 +       /* FIXME: Source route IP option packets --RR */
2105 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2106 +           csum_partial((char *)tcph, tcplen, 0))) {
2107 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2108 +                      tcph, tcplen, NIPQUAD(iph->saddr),
2109 +                      NIPQUAD(iph->daddr));
2110 +               return NF_ACCEPT;
2111 +       }
2112 +       
2113 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2114 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
2115 +          the client has already sent a packet to the server with the server's hostname 
2116 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
2117 +          server will break the connection if this doesn't correspond to its own host 
2118 +          header. The client can also connect to an IP address; if it's the server's IP
2119 +          address, it will not break the connection. When doing DNAT on a connection 
2120 +          where the client uses a server's IP address, the nat module should detect
2121 +          this and change this string accordingly to the DNATed address. This should
2122 +          probably be done by checking for an IP address, then storing it as a member
2123 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2124 +          */
2125 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
2126 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2127 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
2128 +                      (u8)*(data+36), (u8)*(data+37), 
2129 +                      (u8)*(data+38), (u8)*(data+39),
2130 +                      datalen);
2131 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2132 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
2133 +                       if(net_ratelimit())
2134 +                               /* FIXME: more verbose debugging ? */
2135 +                               printk(KERN_WARNING
2136 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
2137 +
2138 +               memset(&expect, 0, sizeof(expect));
2139 +
2140 +               sprintf(mms_proto_string, "(%u)", mms_proto);
2141 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2142 +                      mms_proto == IPPROTO_TCP ? "TCP"
2143 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2144 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2145 +                      NIPQUAD(mms_ip),
2146 +                      mms_port);
2147 +               
2148 +               /* it's possible that the client will just ask the server to tunnel
2149 +                  the stream over the same TCP session (from port 1755): there's 
2150 +                  shouldn't be a need to add an expectation in that case, but it
2151 +                  makes NAT packet mangling so much easier */
2152 +               LOCK_BH(&ip_mms_lock);
2153 +
2154 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2155 +               
2156 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2157 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
2158 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
2159 +               exp_mms_info->port    = mms_port;
2160 +               
2161 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2162 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2163 +               
2164 +               exp->tuple = ((struct ip_conntrack_tuple)
2165 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2166 +                             { mms_ip,
2167 +                               { .tcp = { (__u16) ntohs(mms_port) } },
2168 +                               mms_proto } }
2169 +                            );
2170 +               exp->mask  = ((struct ip_conntrack_tuple)
2171 +                            { { 0xFFFFFFFF, { 0 } },
2172 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2173 +               exp->expectfn = NULL;
2174 +               ip_conntrack_expect_related(ct, &expect);
2175 +               UNLOCK_BH(&ip_mms_lock);
2176 +       }
2177 +
2178 +       return NF_ACCEPT;
2179 +}
2180 +
2181 +static struct ip_conntrack_helper mms[MAX_PORTS];
2182 +static char mms_names[MAX_PORTS][10];
2183 +
2184 +/* Not __exit: called from init() */
2185 +static void fini(void)
2186 +{
2187 +       int i;
2188 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2189 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2190 +                               ports[i]);
2191 +               ip_conntrack_helper_unregister(&mms[i]);
2192 +       }
2193 +}
2194 +
2195 +static int __init init(void)
2196 +{
2197 +       int i, ret;
2198 +       char *tmpname;
2199 +
2200 +       if (ports[0] == 0)
2201 +               ports[0] = MMS_PORT;
2202 +
2203 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2204 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2205 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2206 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
2207 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
2208 +               mms[i].mask.dst.protonum = 0xFFFF;
2209 +               mms[i].max_expected = 1;
2210 +               mms[i].timeout = 0;
2211 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2212 +               mms[i].me = THIS_MODULE;
2213 +               mms[i].help = help;
2214 +
2215 +               tmpname = &mms_names[i][0];
2216 +               if (ports[i] == MMS_PORT)
2217 +                       sprintf(tmpname, "mms");
2218 +               else
2219 +                       sprintf(tmpname, "mms-%d", ports[i]);
2220 +               mms[i].name = tmpname;
2221 +
2222 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
2223 +                               ports[i]);
2224 +               ret = ip_conntrack_helper_register(&mms[i]);
2225 +
2226 +               if (ret) {
2227 +                       fini();
2228 +                       return ret;
2229 +               }
2230 +               ports_c++;
2231 +       }
2232 +       return 0;
2233 +}
2234 +
2235 +module_init(init);
2236 +module_exit(fini);
2237 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
2238 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c    1970-01-01 01:00:00.000000000 +0100
2239 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_proto_sctp.c        2004-04-16 09:18:47.000000000 +0200
2240 @@ -0,0 +1,529 @@
2241 +/*
2242 + * Connection tracking protocol helper module for SCTP.
2243 + * 
2244 + * SCTP is defined in RFC 2960. References to various sections in this code 
2245 + * are to this RFC.
2246 + * 
2247 + * This program is free software; you can redistribute it and/or modify
2248 + * it under the terms of the GNU General Public License version 2 as
2249 + * published by the Free Software Foundation.
2250 + */
2251 +
2252 +#include <linux/types.h>
2253 +#include <linux/sched.h>
2254 +#include <linux/timer.h>
2255 +#include <linux/netfilter.h>
2256 +#include <linux/module.h>
2257 +#include <linux/in.h>
2258 +#include <linux/ip.h>
2259 +#include <linux/sctp.h>
2260 +#include <linux/string.h>
2261 +
2262 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2263 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2264 +#include <linux/netfilter_ipv4/lockhelp.h>
2265 +
2266 +#if 0
2267 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
2268 +#else
2269 +#define DEBUGP(format, args...)
2270 +#endif
2271 +
2272 +/* Protects conntrack->proto.sctp */
2273 +static DECLARE_RWLOCK(sctp_lock);
2274 +
2275 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
2276 +   closely.  They're more complex. --RR 
2277 +
2278 +   And so for me for SCTP :D -Kiran */
2279 +
2280 +static const char *sctp_conntrack_names[] = {
2281 +       "NONE",
2282 +       "CLOSED",
2283 +       "COOKIE_WAIT",
2284 +       "COOKIE_ECHOED",
2285 +       "ESTABLISHED",
2286 +       "SHUTDOWN_SENT",
2287 +       "SHUTDOWN_RECD",
2288 +       "SHUTDOWN_ACK_SENT",
2289 +};
2290 +
2291 +#define SECS  * HZ
2292 +#define MINS  * 60 SECS
2293 +#define HOURS * 60 MINS
2294 +#define DAYS  * 24 HOURS
2295 +
2296 +unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
2297 +unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
2298 +unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
2299 +unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
2300 +unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
2301 +unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
2302 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
2303 +
2304 +static unsigned long * sctp_timeouts[]
2305 += { 0,                                     /* SCTP_CONNTRACK_NONE  */
2306 +    &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
2307 +    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
2308 +    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
2309 +    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
2310 +    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
2311 +    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
2312 +    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
2313 + };
2314 +
2315 +#define sNO SCTP_CONNTRACK_NONE
2316 +#define        sCL SCTP_CONNTRACK_CLOSED
2317 +#define        sCW SCTP_CONNTRACK_COOKIE_WAIT
2318 +#define        sCE SCTP_CONNTRACK_COOKIE_ECHOED
2319 +#define        sES SCTP_CONNTRACK_ESTABLISHED
2320 +#define        sSS SCTP_CONNTRACK_SHUTDOWN_SENT
2321 +#define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
2322 +#define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
2323 +#define        sIV SCTP_CONNTRACK_MAX
2324 +
2325 +/* 
2326 +       These are the descriptions of the states:
2327 +
2328 +NOTE: These state names are tantalizingly similar to the states of an 
2329 +SCTP endpoint. But the interpretation of the states is a little different,
2330 +considering that these are the states of the connection and not of an end 
2331 +point. Please note the subtleties. -Kiran
2332 +
2333 +NONE              - Nothing so far.
2334 +COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
2335 +                    an INIT_ACK chunk in the reply direction.
2336 +COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
2337 +ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
2338 +SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
2339 +SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
2340 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
2341 +                    to that of the SHUTDOWN chunk.
2342 +CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
2343 +                    the SHUTDOWN chunk. Connection is closed.
2344 +*/
2345 +
2346 +/* TODO
2347 + - I have assumed that the first INIT is in the original direction. 
2348 + This messes things when an INIT comes in the reply direction in CLOSED
2349 + state.
2350 + - Check the error type in the reply dir before transitioning from 
2351 +cookie echoed to closed.
2352 + - Sec 5.2.4 of RFC 2960
2353 + - Multi Homing support.
2354 +*/
2355 +
2356 +/* SCTP conntrack state transitions */
2357 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
2358 +       {
2359 +/*     ORIGINAL        */
2360 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
2361 +/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
2362 +/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
2363 +/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
2364 +/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
2365 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
2366 +/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
2367 +/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
2368 +/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
2369 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
2370 +       },
2371 +       {
2372 +/*     REPLY   */
2373 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
2374 +/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
2375 +/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
2376 +/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
2377 +/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
2378 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
2379 +/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
2380 +/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
2381 +/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
2382 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
2383 +       }
2384 +};
2385 +
2386 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
2387 +                            unsigned int dataoff,
2388 +                            struct ip_conntrack_tuple *tuple)
2389 +{
2390 +       sctp_sctphdr_t hdr;
2391 +
2392 +       DEBUGP(__FUNCTION__);
2393 +       DEBUGP("\n");
2394 +
2395 +       /* Actually only need first 8 bytes. */
2396 +       if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
2397 +               return 0;
2398 +
2399 +       tuple->src.u.sctp.port = hdr.source;
2400 +       tuple->dst.u.sctp.port = hdr.dest;
2401 +
2402 +       return 1;
2403 +}
2404 +
2405 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
2406 +                            const struct ip_conntrack_tuple *orig)
2407 +{
2408 +       DEBUGP(__FUNCTION__);
2409 +       DEBUGP("\n");
2410 +
2411 +       tuple->src.u.sctp.port = orig->dst.u.sctp.port;
2412 +       tuple->dst.u.sctp.port = orig->src.u.sctp.port;
2413 +       return 1;
2414 +}
2415 +
2416 +/* Print out the per-protocol part of the tuple. */
2417 +static unsigned int sctp_print_tuple(char *buffer,
2418 +                                    const struct ip_conntrack_tuple *tuple)
2419 +{
2420 +       DEBUGP(__FUNCTION__);
2421 +       DEBUGP("\n");
2422 +
2423 +       return sprintf(buffer, "sport=%hu dport=%hu ",
2424 +                      ntohs(tuple->src.u.sctp.port),
2425 +                      ntohs(tuple->dst.u.sctp.port));
2426 +}
2427 +
2428 +/* Print out the private part of the conntrack. */
2429 +static unsigned int sctp_print_conntrack(char *buffer,
2430 +                                        const struct ip_conntrack *conntrack)
2431 +{
2432 +       enum sctp_conntrack state;
2433 +
2434 +       DEBUGP(__FUNCTION__);
2435 +       DEBUGP("\n");
2436 +
2437 +       READ_LOCK(&sctp_lock);
2438 +       state = conntrack->proto.sctp.state;
2439 +       READ_UNLOCK(&sctp_lock);
2440 +
2441 +       return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
2442 +}
2443 +
2444 +#define for_each_sctp_chunk(skb, sch, offset, count)   \
2445 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0;       \
2446 +       offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch));    \
2447 +       offset += (htons(sch.length) + 3) & ~3, count++)
2448 +
2449 +/* Some validity checks to make sure the chunks are fine */
2450 +static int do_basic_checks(struct ip_conntrack *conntrack,
2451 +                          const struct sk_buff *skb,
2452 +                          char *map)
2453 +{
2454 +       u_int32_t offset, count;
2455 +       sctp_chunkhdr_t sch;
2456 +       int flag;
2457 +
2458 +       DEBUGP(__FUNCTION__);
2459 +       DEBUGP("\n");
2460 +
2461 +       flag = 0;
2462 +
2463 +       for_each_sctp_chunk (skb, sch, offset, count) {
2464 +               DEBUGP("Chunk Num: %d  Type: %d\n", count, sch.type);
2465 +
2466 +               if (sch.type == SCTP_CID_INIT 
2467 +                       || sch.type == SCTP_CID_INIT_ACK
2468 +                       || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
2469 +                       flag = 1;
2470 +               }
2471 +
2472 +               /* Cookie Ack/Echo chunks not the first OR 
2473 +                  Init / Init Ack / Shutdown compl chunks not the only chunks */
2474 +               if ((sch.type == SCTP_CID_COOKIE_ACK 
2475 +                       || sch.type == SCTP_CID_COOKIE_ECHO
2476 +                       || flag)
2477 +                    && count !=0 ) {
2478 +                       DEBUGP("Basic checks failed\n");
2479 +                       return 1;
2480 +               }
2481 +
2482 +               if (map) {
2483 +                       set_bit (sch.type, (void *)map);
2484 +               }
2485 +       }
2486 +
2487 +       DEBUGP("Basic checks passed\n");
2488 +       return 0;
2489 +}
2490 +
2491 +static int new_state(enum ip_conntrack_dir dir,
2492 +                    enum sctp_conntrack cur_state,
2493 +                    int chunk_type)
2494 +{
2495 +       int i;
2496 +
2497 +       DEBUGP(__FUNCTION__);
2498 +       DEBUGP("\n");
2499 +
2500 +       DEBUGP("Chunk type: %d\n", chunk_type);
2501 +
2502 +       switch (chunk_type) {
2503 +               case SCTP_CID_INIT: 
2504 +                       DEBUGP("SCTP_CID_INIT\n");
2505 +                       i = 0; break;
2506 +               case SCTP_CID_INIT_ACK: 
2507 +                       DEBUGP("SCTP_CID_INIT_ACK\n");
2508 +                       i = 1; break;
2509 +               case SCTP_CID_ABORT: 
2510 +                       DEBUGP("SCTP_CID_ABORT\n");
2511 +                       i = 2; break;
2512 +               case SCTP_CID_SHUTDOWN: 
2513 +                       DEBUGP("SCTP_CID_SHUTDOWN\n");
2514 +                       i = 3; break;
2515 +               case SCTP_CID_SHUTDOWN_ACK: 
2516 +                       DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
2517 +                       i = 4; break;
2518 +               case SCTP_CID_ERROR: 
2519 +                       DEBUGP("SCTP_CID_ERROR\n");
2520 +                       i = 5; break;
2521 +               case SCTP_CID_COOKIE_ECHO: 
2522 +                       DEBUGP("SCTP_CID_COOKIE_ECHO\n");
2523 +                       i = 6; break;
2524 +               case SCTP_CID_COOKIE_ACK: 
2525 +                       DEBUGP("SCTP_CID_COOKIE_ACK\n");
2526 +                       i = 7; break;
2527 +               case SCTP_CID_SHUTDOWN_COMPLETE: 
2528 +                       DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
2529 +                       i = 8; break;
2530 +               default:
2531 +                       /* Other chunks like DATA, SACK, HEARTBEAT and
2532 +                       its ACK do not cause a change in state */
2533 +                       DEBUGP("Unknown chunk type, Will stay in %s\n", 
2534 +                                               sctp_conntrack_names[cur_state]);
2535 +                       return cur_state;
2536 +       }
2537 +
2538 +       DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
2539 +                       dir, sctp_conntrack_names[cur_state], chunk_type,
2540 +                       sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
2541 +
2542 +       return sctp_conntracks[dir][i][cur_state];
2543 +}
2544 +
2545 +/* Returns verdict for packet, or -1 for invalid. */
2546 +static int sctp_packet(struct ip_conntrack *conntrack,
2547 +                      const struct sk_buff *skb,
2548 +                      enum ip_conntrack_info ctinfo)
2549 +{
2550 +       enum sctp_conntrack newconntrack, oldsctpstate;
2551 +       sctp_sctphdr_t sctph;
2552 +       sctp_chunkhdr_t sch;
2553 +       u_int32_t offset, count;
2554 +       char map[256 / sizeof (char)] = {0};
2555 +
2556 +       DEBUGP(__FUNCTION__);
2557 +       DEBUGP("\n");
2558 +
2559 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
2560 +               return -1;
2561 +
2562 +       if (do_basic_checks(conntrack, skb, map) != 0)
2563 +               return -1;
2564 +
2565 +       /* Check the verification tag (Sec 8.5) */
2566 +       if (!test_bit(SCTP_CID_INIT, (void *)map)
2567 +               && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
2568 +               && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
2569 +               && !test_bit(SCTP_CID_ABORT, (void *)map)
2570 +               && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
2571 +               && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
2572 +               DEBUGP("Verification tag check failed\n");
2573 +               return -1;
2574 +       }
2575 +
2576 +       oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
2577 +       for_each_sctp_chunk (skb, sch, offset, count) {
2578 +               WRITE_LOCK(&sctp_lock);
2579 +
2580 +               /* Special cases of Verification tag check (Sec 8.5.1) */
2581 +               if (sch.type == SCTP_CID_INIT) {
2582 +                       /* Sec 8.5.1 (A) */
2583 +                       if (sctph.vtag != 0) {
2584 +                               WRITE_UNLOCK(&sctp_lock);
2585 +                               return -1;
2586 +                       }
2587 +               } else if (sch.type == SCTP_CID_ABORT) {
2588 +                       /* Sec 8.5.1 (B) */
2589 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
2590 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
2591 +                                                       [1 - CTINFO2DIR(ctinfo)])) {
2592 +                               WRITE_UNLOCK(&sctp_lock);
2593 +                               return -1;
2594 +                       }
2595 +               } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
2596 +                       /* Sec 8.5.1 (C) */
2597 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
2598 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
2599 +                                                       [1 - CTINFO2DIR(ctinfo)] 
2600 +                                       && (sch.flags & 1))) {
2601 +                               WRITE_UNLOCK(&sctp_lock);
2602 +                               return -1;
2603 +                       }
2604 +               } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
2605 +                       /* Sec 8.5.1 (D) */
2606 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
2607 +                               WRITE_UNLOCK(&sctp_lock);
2608 +                               return -1;
2609 +                       }
2610 +               }
2611 +
2612 +               oldsctpstate = conntrack->proto.sctp.state;
2613 +               newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
2614 +
2615 +               /* Invalid */
2616 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
2617 +                       DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
2618 +                              CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
2619 +                       WRITE_UNLOCK(&sctp_lock);
2620 +                       return -1;
2621 +               }
2622 +
2623 +               /* If it is an INIT or an INIT ACK note down the vtag */
2624 +               if (sch.type == SCTP_CID_INIT 
2625 +                       || sch.type == SCTP_CID_INIT_ACK) {
2626 +                       sctp_inithdr_t inithdr;
2627 +
2628 +                       if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
2629 +                               &inithdr, sizeof(inithdr)) != 0) {
2630 +                                       WRITE_UNLOCK(&sctp_lock);
2631 +                                       return -1;
2632 +                       }
2633 +                       DEBUGP("Setting vtag %x for dir %d\n", 
2634 +                                       inithdr.init_tag, CTINFO2DIR(ctinfo));
2635 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
2636 +               }
2637 +
2638 +               conntrack->proto.sctp.state = newconntrack;
2639 +               WRITE_UNLOCK(&sctp_lock);
2640 +       }
2641 +
2642 +       ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
2643 +
2644 +       if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
2645 +               && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
2646 +               && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
2647 +               DEBUGP("Setting assured bit\n");
2648 +               set_bit(IPS_ASSURED_BIT, &conntrack->status);
2649 +       }
2650 +
2651 +       return NF_ACCEPT;
2652 +}
2653 +
2654 +/* Called when a new connection for this protocol found. */
2655 +static int sctp_new(struct ip_conntrack *conntrack, 
2656 +                   const struct sk_buff *skb)
2657 +{
2658 +       enum sctp_conntrack newconntrack;
2659 +       sctp_sctphdr_t sctph;
2660 +       sctp_chunkhdr_t sch;
2661 +       u_int32_t offset, count;
2662 +       char map[256 / sizeof (char)] = {0};
2663 +
2664 +       DEBUGP(__FUNCTION__);
2665 +       DEBUGP("\n");
2666 +
2667 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
2668 +               return -1;
2669 +
2670 +       if (do_basic_checks(conntrack, skb, map) != 0)
2671 +               return -1;
2672 +
2673 +       /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
2674 +       if ((test_bit (SCTP_CID_ABORT, (void *)map))
2675 +               || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
2676 +               || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
2677 +               return -1;
2678 +       }
2679 +
2680 +       newconntrack = SCTP_CONNTRACK_MAX;
2681 +       for_each_sctp_chunk (skb, sch, offset, count) {
2682 +               /* Don't need lock here: this conntrack not in circulation yet */
2683 +               newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
2684 +                                               SCTP_CONNTRACK_NONE, sch.type);
2685 +
2686 +               /* Invalid: delete conntrack */
2687 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
2688 +                       DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
2689 +                       return 0;
2690 +               }
2691 +
2692 +               /* Copy the vtag into the state info */
2693 +               if (sch.type == SCTP_CID_INIT) {
2694 +                       if (sctph.vtag == 0) {
2695 +                               sctp_inithdr_t inithdr;
2696 +
2697 +                               if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t), 
2698 +                                       &inithdr, sizeof(inithdr)) != 0) {
2699 +                                               return -1;
2700 +                               }
2701 +
2702 +                               DEBUGP("Setting vtag %x for new conn\n", 
2703 +                                       inithdr.init_tag);
2704 +
2705 +                               conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
2706 +                                                               inithdr.init_tag;
2707 +                       } else {
2708 +                               /* Sec 8.5.1 (A) */
2709 +                               return -1;
2710 +                       }
2711 +               }
2712 +               /* If it is a shutdown ack OOTB packet, we expect a return
2713 +                  shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
2714 +               else {
2715 +                       DEBUGP("Setting vtag %x for new conn OOTB\n", 
2716 +                               sctph.vtag);
2717 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
2718 +               }
2719 +
2720 +               conntrack->proto.sctp.state = newconntrack;
2721 +       }
2722 +
2723 +       return 1;
2724 +}
2725 +
2726 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
2727 +                               const struct sk_buff *skb)
2728 +{
2729 +       /* To be implemented */
2730 +       return 0;
2731 +}
2732 +
2733 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
2734 +       .list            = { NULL, NULL }, 
2735 +       .proto           = IPPROTO_SCTP, 
2736 +       .name            = "sctp",
2737 +       .pkt_to_tuple    = sctp_pkt_to_tuple, 
2738 +       .invert_tuple    = sctp_invert_tuple, 
2739 +       .print_tuple     = sctp_print_tuple, 
2740 +       .print_conntrack = sctp_print_conntrack,
2741 +       .packet          = sctp_packet, 
2742 +       .new             = sctp_new, 
2743 +       .destroy         = NULL, 
2744 +       .exp_matches_pkt = sctp_exp_matches_pkt, 
2745 +       .me              = THIS_MODULE 
2746 +};
2747 +
2748 +int __init init(void)
2749 +{
2750 +       int ret;
2751 +
2752 +       ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
2753 +       DEBUGP("SCTP conntrack module loading %s\n", 
2754 +                                       ret ? "failed": "succeeded");
2755 +       return ret;
2756 +}
2757 +
2758 +void __exit fini(void)
2759 +{
2760 +       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
2761 +       DEBUGP("SCTP conntrack module unloaded\n");
2762 +}
2763 +
2764 +module_init(init);
2765 +module_exit(fini);
2766 +
2767 +MODULE_LICENSE("GPL");
2768 +MODULE_AUTHOR("Kiran Kumar Immidi");
2769 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
2770 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_quake3.c
2771 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_quake3.c        1970-01-01 01:00:00.000000000 +0100
2772 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_quake3.c    2004-04-16 09:18:43.000000000 +0200
2773 @@ -0,0 +1,156 @@
2774 +/* Quake3 extension for IP connection tracking
2775 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2776 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
2777 + *
2778 + * ip_conntrack_quake3.c v0.04 2002-08-31
2779 + *
2780 + *      This program is free software; you can redistribute it and/or
2781 + *      modify it under the terms of the GNU General Public License
2782 + *      as published by the Free Software Foundation; either version
2783 + *      2 of the License, or (at your option) any later version.
2784 + *
2785 + *      Module load syntax:
2786 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
2787 + *
2788 + *      please give the ports of all Quake3 master servers You wish to 
2789 + *      connect to. If you don't specify ports, the default will be UDP 
2790 + *      port 27950.
2791 + *
2792 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
2793 + */
2794 +
2795 +#include <linux/module.h>
2796 +#include <linux/ip.h>
2797 +#include <linux/udp.h>
2798 +
2799 +#include <linux/netfilter.h>
2800 +#include <linux/netfilter_ipv4/ip_tables.h>
2801 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2802 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
2803 +
2804 +struct module *ip_conntrack_quake3 = THIS_MODULE;
2805 +
2806 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2807 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
2808 +MODULE_LICENSE("GPL");
2809 +
2810 +#define MAX_PORTS 8
2811 +static int ports[MAX_PORTS];
2812 +static int ports_c = 0;
2813 +#ifdef MODULE_PARM
2814 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2815 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
2816 +#endif
2817 +
2818 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
2819 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
2820 +#if 0 
2821 +#define DEBUGP printk
2822 +#else
2823 +#define DEBUGP(format, args...)
2824 +#endif
2825 +
2826 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
2827 +
2828 +static int quake3_help(const struct iphdr *iph, size_t len,
2829 +       struct ip_conntrack *ct,
2830 +       enum ip_conntrack_info ctinfo)
2831 +{
2832 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
2833 +       int dir = CTINFO2DIR(ctinfo);
2834 +       struct ip_conntrack_expect exp;
2835 +       int i;
2836 +       
2837 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
2838 +       if (ctinfo != IP_CT_ESTABLISHED
2839 +           && ctinfo != IP_CT_IS_REPLY) {
2840 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
2841 +               return NF_ACCEPT;
2842 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
2843 +       
2844 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
2845 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
2846 +                   i+6 < ntohs(udph->len);
2847 +                   i+=7) {
2848 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
2849 +                              i, ntohs(udph->len),
2850 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
2851 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
2852 +
2853 +                       memset(&exp, 0, sizeof(exp));
2854 +
2855 +                       exp.tuple = ((struct ip_conntrack_tuple)
2856 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2857 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
2858 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
2859 +                                        IPPROTO_UDP } }
2860 +                                   );
2861 +                       exp.mask  = ((struct ip_conntrack_tuple)
2862 +                                    { { 0xFFFFFFFF, { 0 } },
2863 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
2864 +                       exp.expectfn = NULL;
2865 +
2866 +                       ip_conntrack_expect_related(ct, &exp);
2867 +               }
2868 +
2869 +       }
2870 +       
2871 +       return(NF_ACCEPT);
2872 +}
2873 +
2874 +static struct ip_conntrack_helper quake3[MAX_PORTS];
2875 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
2876 +
2877 +static void fini(void)
2878 +{
2879 +       int i;
2880 +
2881 +       for(i = 0 ; (i < ports_c); i++) {
2882 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
2883 +                                       ports[i]);
2884 +               ip_conntrack_helper_unregister(&quake3[i]);
2885 +       } 
2886 +}
2887 +
2888 +static int __init init(void)
2889 +{
2890 +       int i, ret;
2891 +       char *tmpname;
2892 +
2893 +       if(!ports[0])
2894 +               ports[0]=QUAKE3_MASTER_PORT;
2895 +
2896 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
2897 +               /* Create helper structure */
2898 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
2899 +
2900 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
2901 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
2902 +               quake3[i].mask.dst.protonum = 0xFFFF;
2903 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
2904 +               quake3[i].help = quake3_help;
2905 +               quake3[i].me = THIS_MODULE;
2906 +
2907 +               tmpname = &quake3_names[i][0];
2908 +               if (ports[i] == QUAKE3_MASTER_PORT)
2909 +                       sprintf(tmpname, "quake3");
2910 +               else
2911 +                       sprintf(tmpname, "quake3-%d", i);
2912 +               quake3[i].name = tmpname;
2913 +               
2914 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
2915 +                      ports[i]);
2916 +
2917 +               ret=ip_conntrack_helper_register(&quake3[i]);
2918 +               if(ret) {
2919 +                       fini();
2920 +                       return(ret);
2921 +               }
2922 +               ports_c++;
2923 +       }
2924 +
2925 +       return(0);
2926 +}
2927 +
2928 +module_init(init);
2929 +module_exit(fini);
2930 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
2931 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c       1970-01-01 01:00:00.000000000 +0100
2932 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c   2004-04-16 09:18:44.000000000 +0200
2933 @@ -0,0 +1,508 @@
2934 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
2935 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2936 + *     - original rpc tracking module
2937 + *     - "recent" connection handling for kernel 2.3+ netfilter
2938 + *
2939 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2940 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2941 + *
2942 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2943 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
2944 + *     - extended matching to support filtering on procedures
2945 + *
2946 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
2947 + *
2948 + *     This program is free software; you can redistribute it and/or
2949 + *     modify it under the terms of the GNU General Public License
2950 + *     as published by the Free Software Foundation; either version
2951 + *     2 of the License, or (at your option) any later version.
2952 + **
2953 + *     Module load syntax:
2954 + *     insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
2955 + *
2956 + *     Please give the ports of all RPC servers you wish to connect to.
2957 + *     If you don't specify ports, the default will be port 111.
2958 + **
2959 + *     Note to all:
2960 + *
2961 + *     RPCs should not be exposed to the internet - ask the Pentagon;
2962 + *
2963 + *       "The unidentified crackers pleaded guilty in July to charges
2964 + *        of juvenile delinquency stemming from a string of Pentagon
2965 + *        network intrusions in February.
2966 + *
2967 + *        The youths, going by the names TooShort and Makaveli, used
2968 + *        a common server security hole to break in, according to
2969 + *        Dane Jasper, owner of the California Internet service
2970 + *        provider, Sonic. They used the hole, known as the 'statd'
2971 + *        exploit, to attempt more than 800 break-ins, Jasper said."
2972 + *
2973 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
2974 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
2975 + **
2976 + */
2977 +
2978 +#include <linux/module.h>
2979 +#include <linux/netfilter.h>
2980 +#include <linux/ip.h>
2981 +#include <net/checksum.h>
2982 +#include <net/tcp.h>
2983 +
2984 +#include <asm/param.h>
2985 +#include <linux/sched.h>
2986 +#include <linux/timer.h>
2987 +#include <linux/stddef.h>
2988 +#include <linux/list.h>
2989 +
2990 +#include <linux/netfilter_ipv4/lockhelp.h>
2991 +#include <linux/netfilter_ipv4/ip_tables.h>
2992 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2993 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
2994 +
2995 +#define MAX_PORTS 8
2996 +static int ports[MAX_PORTS];
2997 +static int ports_n_c = 0;
2998 +
2999 +#ifdef MODULE_PARM
3000 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3001 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3002 +#endif
3003 +
3004 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3005 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
3006 +MODULE_LICENSE("GPL");
3007 +
3008 +#if 0
3009 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
3010 +                                       format, ## args)
3011 +#else
3012 +#define DEBUGP(format, args...)
3013 +#endif
3014 +
3015 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
3016 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
3017 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
3018 +#include <linux/netfilter_ipv4/listhelp.h>
3019 +
3020 +/* For future conections RPC, using client's cache bindings
3021 + * I'll use ip_conntrack_lock to lock these lists         */
3022 +
3023 +LIST_HEAD(request_p_list_tcp);
3024 +
3025 +
3026 +static void delete_request_p(unsigned long request_p_ul) 
3027 +{
3028 +       struct request_p *p = (void *)request_p_ul;
3029 +       
3030 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3031 +       LIST_DELETE(&request_p_list_tcp, p);
3032 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3033 +       kfree(p);
3034 +       return;
3035 +}
3036 +
3037 +
3038 +static void req_cl(struct request_p * r)
3039 +{
3040 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3041 +       del_timer(&r->timeout);
3042 +       LIST_DELETE(&request_p_list_tcp, r);
3043 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3044 +       kfree(r);
3045 +       return;
3046 +}
3047 +
3048 +
3049 +static void clean_request(struct list_head *list)
3050 +{
3051 +       struct list_head *first = list->prev;
3052 +       struct list_head *temp = list->next;
3053 +       struct list_head *aux;
3054 +
3055 +       if (list_empty(list))
3056 +               return;
3057 +
3058 +       while (first != temp) {
3059 +               aux = temp->next;
3060 +               req_cl((struct request_p *)temp);
3061 +               temp = aux;     
3062 +       }
3063 +       req_cl((struct request_p *)temp);
3064 +       return;
3065 +}
3066 +
3067 +
3068 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3069 +                    u_int16_t port)
3070 +{
3071 +       struct request_p *req_p;
3072 +       
3073 +       /* Verifies if entry already exists */
3074 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3075 +       req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3076 +               struct request_p *, xid, ip, port);
3077 +
3078 +       if (req_p) {
3079 +               /* Refresh timeout */
3080 +               if (del_timer(&req_p->timeout)) {
3081 +                       req_p->timeout.expires = jiffies + EXP;
3082 +                       add_timer(&req_p->timeout);     
3083 +               } 
3084 +               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3085 +               return; 
3086 +
3087 +       }
3088 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3089 +       
3090 +       /* Allocate new request_p */
3091 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3092 +       if (!req_p) {
3093 +               DEBUGP("can't allocate request_p\n");
3094 +               return;                 
3095 +       }
3096 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
3097 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3098 +                       NULL }}); 
3099 +      
3100 +       /* Initialize timer */
3101 +       init_timer(&req_p->timeout);
3102 +       req_p->timeout.function = delete_request_p;
3103 +       add_timer(&req_p->timeout); 
3104 +
3105 +       /* Put in list */
3106 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3107 +       list_prepend(&request_p_list_tcp, req_p);
3108 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
3109 +       return; 
3110 +
3111 +}
3112 +
3113 +
3114 +static int check_rpc_packet(const u_int32_t *data,
3115 +                       int dir, struct ip_conntrack *ct,
3116 +                       struct list_head request_p_list)
3117 +{
3118 +       struct request_p *req_p;
3119 +       u_int32_t xid;
3120 +       struct ip_conntrack_expect expect, *exp = &expect;
3121 +
3122 +        /* Translstion's buffer for XDR */
3123 +        u_int16_t port_buf;
3124 +
3125 +
3126 +       /* Get XID */
3127 +       xid = *data;
3128 +
3129 +       /* This does sanity checking on RPC payloads,
3130 +        * and permits only the RPC "get port" (3)
3131 +        * in authorised procedures in client
3132 +        * communications with the portmapper.
3133 +        */
3134 +
3135 +       /* perform direction dependant RPC work */
3136 +       if (dir == IP_CT_DIR_ORIGINAL) {
3137 +
3138 +               data += 5;
3139 +
3140 +               /* Get RPC requestor */
3141 +               if (IXDR_GET_INT32(data) != 3) {
3142 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3143 +                       return NF_ACCEPT;
3144 +               }
3145 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3146 +
3147 +               data++;
3148 +
3149 +               /* Jump Credentials and Verfifier */
3150 +               data += IXDR_GET_INT32(data) + 2;
3151 +               data += IXDR_GET_INT32(data) + 2;
3152 +
3153 +               /* Get RPC procedure */
3154 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3155 +                       (unsigned int)IXDR_GET_INT32(data));
3156 +
3157 +               /* Get RPC protocol and store against client parameters */
3158 +               data = data + 2;
3159 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3160 +                               ct->tuplehash[dir].tuple.src.u.all);
3161 +
3162 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3163 +                       xid, IXDR_GET_INT32(data),
3164 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3165 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
3166 +
3167 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
3168 +                       (unsigned int)IXDR_GET_INT32(data));
3169 +
3170 +       } else {
3171 +
3172 +               /* Check for returning packet's stored counterpart */
3173 +               req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3174 +                                 struct request_p *, xid,
3175 +                                 ct->tuplehash[!dir].tuple.src.ip,
3176 +                                 ct->tuplehash[!dir].tuple.src.u.all);
3177 +
3178 +               /* Drop unexpected packets */
3179 +               if (!req_p) {
3180 +                       DEBUGP("packet is not expected. [skip]\n");
3181 +                       return NF_ACCEPT;
3182 +               }
3183 +
3184 +               /* Verifies if packet is really an RPC reply packet */
3185 +               data = data++;
3186 +               if (IXDR_GET_INT32(data) != 1) {
3187 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
3188 +                       return NF_ACCEPT;
3189 +               }
3190 +
3191 +               /* Is status accept? */
3192 +               data++;
3193 +               if (IXDR_GET_INT32(data)) {
3194 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
3195 +                       return NF_ACCEPT;
3196 +               }
3197 +
3198 +               /* Get Verifier length. Jump verifier */
3199 +               data++;
3200 +               data = data + IXDR_GET_INT32(data) + 2;
3201 +
3202 +               /* Is accpet status "success"? */
3203 +               if (IXDR_GET_INT32(data)) {
3204 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3205 +                       return NF_ACCEPT;
3206 +               }
3207 +
3208 +               /* Get server port number */      
3209 +               data++;
3210 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
3211 +
3212 +               /* If a packet has made it this far then it deserves an
3213 +                * expectation ...  if port == 0, then this service is 
3214 +                * not going to be registered.
3215 +                */
3216 +               if (port_buf) {
3217 +                       DEBUGP("port found: %u\n", port_buf);
3218 +
3219 +                       memset(&expect, 0, sizeof(expect));
3220 +
3221 +                       /* Watch out, Radioactive-Man! */
3222 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3223 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3224 +                       exp->mask.src.ip = 0xffffffff;
3225 +                       exp->mask.dst.ip = 0xffffffff;
3226 +
3227 +                       switch (req_p->proto) {
3228 +                               case IPPROTO_UDP:
3229 +                                       exp->tuple.src.u.udp.port = 0;
3230 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
3231 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
3232 +                                       exp->mask.src.u.udp.port = 0;
3233 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
3234 +                                       exp->mask.dst.protonum = 0xffff;
3235 +                                       break;
3236 +
3237 +                               case IPPROTO_TCP:
3238 +                                       exp->tuple.src.u.tcp.port = 0;
3239 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
3240 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
3241 +                                       exp->mask.src.u.tcp.port = 0;
3242 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
3243 +                                       exp->mask.dst.protonum = 0xffff;
3244 +                                       break;
3245 +                       }
3246 +                       exp->expectfn = NULL;
3247 +
3248 +                       ip_conntrack_expect_related(ct, &expect);
3249 +
3250 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3251 +                               NIPQUAD(exp->tuple.src.ip),
3252 +                               NIPQUAD(exp->tuple.dst.ip),
3253 +                               port_buf, req_p->proto);
3254 +
3255 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3256 +                               NIPQUAD(exp->mask.src.ip),
3257 +                               NIPQUAD(exp->mask.dst.ip),
3258 +                               exp->mask.dst.protonum);
3259 +
3260 +               }
3261 +
3262 +               req_cl(req_p);
3263 +
3264 +               DEBUGP("packet evaluated. [expect]\n");
3265 +               return NF_ACCEPT;
3266 +       }
3267 +
3268 +       return NF_ACCEPT;
3269 +
3270 +}
3271 +
3272 +
3273 +/* RPC TCP helper */
3274 +static int help(const struct iphdr *iph, size_t len,
3275 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3276 +{
3277 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3278 +       const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3279 +       size_t tcplen = len - iph->ihl * 4;
3280 +
3281 +       int dir = CTINFO2DIR(ctinfo);
3282 +       int crp_ret;
3283 +
3284 +
3285 +       DEBUGP("new packet to evaluate ..\n");
3286 +
3287 +       /* This works for packets like handshake packets, ignore */
3288 +       if (len == ((tcph->doff + iph->ihl) * 4)) {
3289 +               DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3290 +               return NF_ACCEPT;
3291 +       }
3292 +
3293 +       /* Until there's been traffic both ways, don't look in packets. */
3294 +       if (ctinfo != IP_CT_ESTABLISHED
3295 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3296 +               DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3297 +               DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3298 +               DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3299 +               return NF_ACCEPT;
3300 +       }
3301 +
3302 +       /* Not whole TCP header? */
3303 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3304 +               DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3305 +               DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3306 +               return NF_ACCEPT;
3307 +       }
3308 +
3309 +       /* FIXME: Source route IP option packets --RR */
3310 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3311 +                        csum_partial((char *) tcph, tcplen, 0))) {
3312 +               DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3313 +                    tcph, tcplen, NIPQUAD(iph->saddr),
3314 +                    NIPQUAD(iph->daddr));
3315 +               DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3316 +               DEBUGP("packet contains a bad checksum. [skip]\n");
3317 +               return NF_ACCEPT;
3318 +       }
3319 +
3320 +       /* perform direction dependant protocol work */
3321 +       if (dir == IP_CT_DIR_ORIGINAL) {
3322 +
3323 +               DEBUGP("packet is from the initiator. [cont]\n");
3324 +
3325 +               /* Tests if packet len is ok */
3326 +               if ((tcplen - (tcph->doff * 4)) != 60) {
3327 +                       DEBUGP("packet length is not correct. [skip]\n");
3328 +                       return NF_ACCEPT;
3329 +               }
3330 +
3331 +       } else {
3332 +
3333 +               DEBUGP("packet is from the receiver. [cont]\n");
3334 +
3335 +               /* Tests if packet len is ok */
3336 +               if ((tcplen - (tcph->doff * 4)) != 32) {
3337 +                       DEBUGP("packet length is not correct. [skip]\n");
3338 +                       return NF_ACCEPT;
3339 +               }
3340 +       }
3341 +
3342 +       /* Get to the data */
3343 +       data++;
3344 +
3345 +       /* Check the RPC data */
3346 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
3347 +
3348 +       return crp_ret;
3349 +
3350 +}
3351 +
3352 +
3353 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3354 +
3355 +static void fini(void);
3356 +
3357 +
3358 +static int __init init(void)
3359 +{
3360 +       int port, ret;
3361 +       static char name[10];
3362 +
3363 +
3364 +       /* If no port given, default to standard RPC port */
3365 +       if (ports[0] == 0)
3366 +               ports[0] = RPC_PORT;
3367 +
3368 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3369 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3370 +
3371 +                if (ports[port] == RPC_PORT)
3372 +                        sprintf(name, "rpc");
3373 +                else
3374 +                        sprintf(name, "rpc-%d", port);
3375 +
3376 +               rpc_helpers[port].name = name;
3377 +               rpc_helpers[port].me = THIS_MODULE;
3378 +               rpc_helpers[port].max_expected = 1;
3379 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3380 +               rpc_helpers[port].timeout = 0;
3381 +
3382 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
3383 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
3384 +
3385 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
3386 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3387 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3388 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3389 +
3390 +               rpc_helpers[port].help = help;
3391 +
3392 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
3393 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3394 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3395 +                       ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
3396 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
3397 +                       ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
3398 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3399 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
3400 +                       ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
3401 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
3402 +                       ntohs(rpc_helpers[port].mask.src.u.tcp.port));
3403 +
3404 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3405 +
3406 +               if (ret) {
3407 +                       printk("ERROR registering port %d\n",
3408 +                               ports[port]);
3409 +                       fini();
3410 +                       return -EBUSY;
3411 +               }
3412 +               ports_n_c++;
3413 +       }
3414 +       return 0;
3415 +}
3416 +
3417 +
3418 +/* This function is intentionally _NOT_ defined as __exit, because 
3419 + * it is needed by the init function */
3420 +static void fini(void)
3421 +{
3422 +       int port;
3423 +
3424 +       DEBUGP("cleaning request list\n");
3425 +       clean_request(&request_p_list_tcp);
3426 +
3427 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3428 +               DEBUGP("unregistering port %d\n", ports[port]);
3429 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
3430 +       }
3431 +}
3432 +
3433 +
3434 +module_init(init);
3435 +module_exit(fini);
3436 +
3437 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
3438 +EXPORT_SYMBOL(request_p_list_tcp);
3439 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
3440 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
3441 +
3442 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
3443 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c       1970-01-01 01:00:00.000000000 +0100
3444 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rpc_udp.c   2004-04-16 09:18:44.000000000 +0200
3445 @@ -0,0 +1,503 @@
3446 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
3447 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3448 + *     - original rpc tracking module
3449 + *     - "recent" connection handling for kernel 2.3+ netfilter
3450 + *
3451 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3452 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3453 + *
3454 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3455 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
3456 + *     - extended matching to support filtering on procedures
3457 + *
3458 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
3459 + *
3460 + *     This program is free software; you can redistribute it and/or
3461 + *     modify it under the terms of the GNU General Public License
3462 + *     as published by the Free Software Foundation; either version
3463 + *     2 of the License, or (at your option) any later version.
3464 + **
3465 + *     Module load syntax:
3466 + *     insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
3467 + *
3468 + *     Please give the ports of all RPC servers you wish to connect to.
3469 + *     If you don't specify ports, the default will be port 111.
3470 + **
3471 + *     Note to all:
3472 + *
3473 + *     RPCs should not be exposed to the internet - ask the Pentagon;
3474 + *
3475 + *       "The unidentified crackers pleaded guilty in July to charges
3476 + *        of juvenile delinquency stemming from a string of Pentagon
3477 + *        network intrusions in February.
3478 + *
3479 + *        The youths, going by the names TooShort and Makaveli, used
3480 + *        a common server security hole to break in, according to
3481 + *        Dane Jasper, owner of the California Internet service
3482 + *        provider, Sonic. They used the hole, known as the 'statd'
3483 + *        exploit, to attempt more than 800 break-ins, Jasper said."
3484 + *
3485 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3486 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
3487 + **
3488 + */
3489 +
3490 +#include <linux/module.h>
3491 +#include <linux/netfilter.h>
3492 +#include <linux/ip.h>
3493 +#include <net/checksum.h>
3494 +#include <net/udp.h>
3495 +
3496 +#include <asm/param.h>
3497 +#include <linux/sched.h>
3498 +#include <linux/timer.h>
3499 +#include <linux/stddef.h>
3500 +#include <linux/list.h>
3501 +
3502 +#include <linux/netfilter_ipv4/lockhelp.h>
3503 +#include <linux/netfilter_ipv4/ip_tables.h>
3504 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3505 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3506 +
3507 +#define MAX_PORTS 8
3508 +static int ports[MAX_PORTS];
3509 +static int ports_n_c = 0;
3510 +
3511 +#ifdef MODULE_PARM
3512 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3513 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3514 +#endif
3515 +
3516 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3517 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
3518 +MODULE_LICENSE("GPL");
3519 +
3520 +#if 0
3521 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
3522 +                                       format, ## args)
3523 +#else
3524 +#define DEBUGP(format, args...)
3525 +#endif
3526 +
3527 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
3528 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
3529 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
3530 +#include <linux/netfilter_ipv4/listhelp.h>
3531 +
3532 +/* For future conections RPC, using client's cache bindings
3533 + * I'll use ip_conntrack_lock to lock these lists           */
3534 +
3535 +LIST_HEAD(request_p_list_udp);
3536 +
3537 +
3538 +static void delete_request_p(unsigned long request_p_ul)
3539 +{
3540 +       struct request_p *p = (void *)request_p_ul;
3541 +       
3542 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3543 +       LIST_DELETE(&request_p_list_udp, p);
3544 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
3545 +       kfree(p);
3546 +       return;
3547 +}
3548 +
3549 +
3550 +static void req_cl(struct request_p * r)
3551 +{
3552 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3553 +       del_timer(&r->timeout);
3554 +       LIST_DELETE(&request_p_list_udp, r);
3555 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
3556 +       kfree(r);
3557 +       return;
3558 +}
3559 +
3560 +
3561 +static void clean_request(struct list_head *list)
3562 +{
3563 +       struct list_head *first = list->prev;
3564 +       struct list_head *temp = list->next;
3565 +       struct list_head *aux;
3566 +
3567 +       if (list_empty(list))
3568 +               return;
3569 +
3570 +       while (first != temp) {
3571 +               aux = temp->next;
3572 +               req_cl((struct request_p *)temp);
3573 +               temp = aux;     
3574 +       }
3575 +       req_cl((struct request_p *)temp);
3576 +       return;
3577 +}
3578 +
3579 +
3580 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3581 +                    u_int16_t port)
3582 +{
3583 +       struct request_p *req_p;
3584 +        
3585 +       /* Verifies if entry already exists */
3586 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3587 +       req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3588 +               struct request_p *, xid, ip, port);
3589 +
3590 +       if (req_p) {
3591 +               /* Refresh timeout */
3592 +               if (del_timer(&req_p->timeout)) {
3593 +                       req_p->timeout.expires = jiffies + EXP;
3594 +                       add_timer(&req_p->timeout);     
3595 +               } 
3596 +               WRITE_UNLOCK(&ipct_rpc_udp_lock);
3597 +               return; 
3598 +
3599 +       }
3600 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
3601 +       
3602 +       /* Allocate new request_p */
3603 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3604 +       if (!req_p) {
3605 +               DEBUGP("can't allocate request_p\n");
3606 +               return;                 
3607 +       }
3608 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
3609 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3610 +                       NULL }}); 
3611 +      
3612 +       /* Initialize timer */
3613 +       init_timer(&req_p->timeout);
3614 +       req_p->timeout.function = delete_request_p;
3615 +       add_timer(&req_p->timeout); 
3616 +
3617 +       /* Put in list */
3618 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3619 +       list_prepend(&request_p_list_udp, req_p);
3620 +       WRITE_UNLOCK(&ipct_rpc_udp_lock); 
3621 +       return; 
3622 +
3623 +}
3624 +
3625 +
3626 +static int check_rpc_packet(const u_int32_t *data,
3627 +                       int dir, struct ip_conntrack *ct,
3628 +                       struct list_head request_p_list)
3629 +{
3630 +       struct request_p *req_p;
3631 +       u_int32_t xid;
3632 +       struct ip_conntrack_expect expect, *exp = &expect;
3633 +
3634 +       /* Translstion's buffer for XDR */
3635 +       u_int16_t port_buf;
3636 +
3637 +
3638 +       /* Get XID */
3639 +       xid = *data;
3640 +
3641 +       /* This does sanity checking on RPC payloads,
3642 +        * and permits only the RPC "get port" (3)
3643 +        * in authorised procedures in client
3644 +        * communications with the portmapper.
3645 +        */
3646 +
3647 +       /* perform direction dependant RPC work */
3648 +       if (dir == IP_CT_DIR_ORIGINAL) {
3649 +
3650 +               data += 5;
3651 +
3652 +               /* Get RPC requestor */
3653 +               if (IXDR_GET_INT32(data) != 3) {
3654 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3655 +                       return NF_ACCEPT;
3656 +               }
3657 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3658 +
3659 +               data++;
3660 +
3661 +               /* Jump Credentials and Verfifier */
3662 +               data = data + IXDR_GET_INT32(data) + 2;
3663 +               data = data + IXDR_GET_INT32(data) + 2;
3664 +
3665 +               /* Get RPC procedure */
3666 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3667 +                       (unsigned int)IXDR_GET_INT32(data));
3668 +
3669 +               /* Get RPC protocol and store against client parameters */
3670 +               data = data + 2;
3671 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3672 +                               ct->tuplehash[dir].tuple.src.u.all);
3673 +
3674 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3675 +                       xid, IXDR_GET_INT32(data),
3676 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3677 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
3678 +
3679 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
3680 +                       (unsigned int)IXDR_GET_INT32(data));
3681 +
3682 +       } else {
3683 +
3684 +               /* Check for returning packet's stored counterpart */
3685 +               req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3686 +                                 struct request_p *, xid,
3687 +                                 ct->tuplehash[!dir].tuple.src.ip,
3688 +                                 ct->tuplehash[!dir].tuple.src.u.all);
3689 +
3690 +               /* Drop unexpected packets */
3691 +               if (!req_p) {
3692 +                       DEBUGP("packet is not expected. [skip]\n");
3693 +                       return NF_ACCEPT;
3694 +               }
3695 +
3696 +               /* Verifies if packet is really an RPC reply packet */
3697 +               data = data++;
3698 +               if (IXDR_GET_INT32(data) != 1) {
3699 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
3700 +                       return NF_ACCEPT;
3701 +               }
3702 +
3703 +               /* Is status accept? */
3704 +               data++;
3705 +               if (IXDR_GET_INT32(data)) {
3706 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
3707 +                       return NF_ACCEPT;
3708 +               }
3709 +
3710 +               /* Get Verifier length. Jump verifier */
3711 +               data++;
3712 +               data = data + IXDR_GET_INT32(data) + 2;
3713 +
3714 +               /* Is accpet status "success"? */
3715 +               if (IXDR_GET_INT32(data)) {
3716 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3717 +                       return NF_ACCEPT;
3718 +               }
3719 +
3720 +               /* Get server port number */      
3721 +               data++;
3722 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
3723 +
3724 +               /* If a packet has made it this far then it deserves an
3725 +                * expectation ...  if port == 0, then this service is 
3726 +                * not going to be registered.
3727 +                */
3728 +               if (port_buf) {
3729 +                       DEBUGP("port found: %u\n", port_buf);
3730 +
3731 +                       memset(&expect, 0, sizeof(expect));
3732 +
3733 +                       /* Watch out, Radioactive-Man! */
3734 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3735 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3736 +                       exp->mask.src.ip = 0xffffffff;
3737 +                       exp->mask.dst.ip = 0xffffffff;
3738 +
3739 +                       switch (req_p->proto) {
3740 +                               case IPPROTO_UDP:
3741 +                                       exp->tuple.src.u.udp.port = 0;
3742 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
3743 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
3744 +                                       exp->mask.src.u.udp.port = 0;
3745 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
3746 +                                       exp->mask.dst.protonum = 0xffff;
3747 +                                       break;
3748 +
3749 +                               case IPPROTO_TCP:
3750 +                                       exp->tuple.src.u.tcp.port = 0;
3751 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
3752 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
3753 +                                       exp->mask.src.u.tcp.port = 0;
3754 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
3755 +                                       exp->mask.dst.protonum = 0xffff;
3756 +                                       break;
3757 +                       }
3758 +                       exp->expectfn = NULL;
3759 +
3760 +                       ip_conntrack_expect_related(ct, &expect);
3761 +
3762 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3763 +                               NIPQUAD(exp->tuple.src.ip),
3764 +                               NIPQUAD(exp->tuple.dst.ip),
3765 +                               port_buf, req_p->proto);
3766 +
3767 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3768 +                               NIPQUAD(exp->mask.src.ip),
3769 +                               NIPQUAD(exp->mask.dst.ip),
3770 +                               exp->mask.dst.protonum);
3771 +
3772 +               }
3773 +
3774 +               req_cl(req_p);
3775 +
3776 +               DEBUGP("packet evaluated. [expect]\n");
3777 +               return NF_ACCEPT;
3778 +       }
3779 +
3780 +       return NF_ACCEPT;
3781 +
3782 +}
3783 +
3784 +
3785 +/* RPC UDP helper */
3786 +static int help(const struct iphdr *iph, size_t len,
3787 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3788 +{
3789 +       struct udphdr *udph = (void *) iph + iph->ihl * 4;
3790 +       const u_int32_t *data = (const u_int32_t *)udph + 2;
3791 +       size_t udplen = len - iph->ihl * 4;
3792 +       int dir = CTINFO2DIR(ctinfo);
3793 +       int crp_ret;
3794 +
3795 +       /* Checksum */
3796 +       const u_int16_t *chsm = (const u_int16_t *)udph + 3;
3797 +
3798 +
3799 +       DEBUGP("new packet to evaluate ..\n");
3800 +
3801 +       /* Not whole UDP header? */
3802 +       if (udplen < sizeof(struct udphdr)) {
3803 +               DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
3804 +               DEBUGP("packet does not contain a complete UDP header. [skip]\n");
3805 +               return NF_ACCEPT;
3806 +       }
3807 +
3808 +       /* FIXME: Source route IP option packets --RR */
3809 +       if (*chsm) {
3810 +               if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
3811 +                   csum_partial((char *)udph, udplen, 0))) {
3812 +                       DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3813 +                       DEBUGP("packet contains a bad checksum. [skip]\n");
3814 +                       return NF_ACCEPT;
3815 +                  } 
3816 +       }
3817 +
3818 +       /* perform direction dependant protocol work */
3819 +       if (dir == IP_CT_DIR_ORIGINAL) {
3820 +
3821 +               DEBUGP("packet is from the initiator. [cont]\n");
3822 +
3823 +               /* Tests if packet len is ok */
3824 +               if ((udplen - sizeof(struct udphdr)) != 56) {
3825 +                       DEBUGP("packet length is not correct. [skip]\n");
3826 +                       return NF_ACCEPT;
3827 +               }
3828 +
3829 +       } else {
3830 +
3831 +               DEBUGP("packet is from the receiver. [cont]\n");
3832 +
3833 +               /* Until there's been traffic both ways, don't look in packets. */
3834 +               if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3835 +                       DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3836 +                       DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3837 +                       DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3838 +                       return NF_ACCEPT;
3839 +               }
3840 +
3841 +               /* Tests if packet len is ok */
3842 +                       if ((udplen - sizeof(struct udphdr)) != 28) {
3843 +                       DEBUGP("packet length is not correct. [skip]\n");
3844 +                       return NF_ACCEPT;
3845 +               }
3846 +
3847 +       }
3848 +
3849 +       /* Get to the data */
3850 +       /* udp *data == *correct */
3851 +
3852 +       /* Check the RPC data */
3853 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
3854 +
3855 +       return crp_ret;
3856 +
3857 +}
3858 +
3859 +
3860 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3861 +
3862 +static void fini(void);
3863 +
3864 +
3865 +static int __init init(void)
3866 +{
3867 +       int port, ret;
3868 +       static char name[10];
3869 +
3870 +
3871 +       /* If no port given, default to standard RPC port */
3872 +       if (ports[0] == 0)
3873 +               ports[0] = RPC_PORT;
3874 +
3875 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3876 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3877 +
3878 +                if (ports[port] == RPC_PORT)
3879 +                        sprintf(name, "rpc");
3880 +                else
3881 +                        sprintf(name, "rpc-%d", port);
3882 +
3883 +               rpc_helpers[port].name = name;
3884 +               rpc_helpers[port].me = THIS_MODULE;
3885 +               rpc_helpers[port].max_expected = 1;
3886 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3887 +               rpc_helpers[port].timeout = 0;
3888 +
3889 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
3890 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
3891 +
3892 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
3893 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3894 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3895 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3896 +
3897 +               rpc_helpers[port].help = help;
3898 +
3899 +               DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
3900 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3901 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3902 +                       ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
3903 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
3904 +                       ntohs(rpc_helpers[port].tuple.src.u.udp.port));
3905 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3906 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
3907 +                       ntohs(rpc_helpers[port].mask.dst.u.udp.port),
3908 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
3909 +                       ntohs(rpc_helpers[port].mask.src.u.udp.port));
3910 +
3911 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3912 +
3913 +               if (ret) {
3914 +                       printk("ERROR registering port %d\n",
3915 +                               ports[port]);
3916 +                       fini();
3917 +                       return -EBUSY;
3918 +               }
3919 +               ports_n_c++;
3920 +       }
3921 +       return 0;
3922 +}
3923 +
3924 +
3925 +/* This function is intentionally _NOT_ defined as __exit, because 
3926 + * it is needed by the init function */
3927 +static void fini(void)
3928 +{
3929 +       int port;
3930 +
3931 +       DEBUGP("cleaning request list\n");
3932 +       clean_request(&request_p_list_udp);
3933 +
3934 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3935 +               DEBUGP("unregistering port %d\n", ports[port]);
3936 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
3937 +       }
3938 +}
3939 +
3940 +
3941 +module_init(init);
3942 +module_exit(fini);
3943 +
3944 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
3945 +EXPORT_SYMBOL(request_p_list_udp);
3946 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
3947 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
3948 +
3949 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rsh.c
3950 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_rsh.c   1970-01-01 01:00:00.000000000 +0100
3951 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_rsh.c       2004-04-16 09:18:45.000000000 +0200
3952 @@ -0,0 +1,331 @@
3953 +/* RSH extension for IP connection tracking, Version 1.0
3954 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3955 + * based on HW's ip_conntrack_irc.c    
3956 + *
3957 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
3958 + *
3959 + *      This program is free software; you can redistribute it and/or
3960 + *      modify it under the terms of the GNU General Public License
3961 + *      as published by the Free Software Foundation; either version
3962 + *      2 of the License, or (at your option) any later version.
3963 + **
3964 + *     Module load syntax:
3965 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
3966 + *     
3967 + *     please give the ports of all RSH servers You wish to connect to.
3968 + *     If You don't specify ports, the default will be port 514
3969 + **
3970 + *      Note to all:
3971 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
3972 + *        unfortunately I babysit some sysadmins that won't migrate
3973 + *       their legacy crap, in our second tier.
3974 + */
3975 +
3976 +
3977 +/*
3978 + *  Some docco ripped from the net to teach me all there is to know about
3979 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
3980 + *  this module).
3981 + *
3982 + *  I have no idea what "unix rshd man pages" these guys have .. but that
3983 + *  is some pretty detailed docco!
3984 + **
3985 + *
3986 + *  4. Of the rsh protocol.
3987 + *  -----------------------
3988 + * 
3989 + *   The rshd listens on TCP port #514. The following info is from the unix
3990 + *   rshd man pages :
3991 + * 
3992 + *   "Service Request Protocol
3993 + * 
3994 + *    When the rshd daemon receives a service request, it initiates the
3995 + *    following protocol:
3996 + * 
3997 + *     1. The rshd daemon checks the source port number for the request.
3998 + *        If the port number is not in the range 0 through 1023, the rshd daemon
3999 + *        terminates the connection.
4000 + * 
4001 + *     2. The rshd daemon reads characters from the socket up to a null byte.
4002 + *        The string read is interpreted as an ASCII number (base 10). If this
4003 + *        number is nonzero, the rshd daemon interprets it as the port number
4004 + *        of a secondary stream to be used as standard error. A second connection
4005 + *        is created to the specified port on the client host. The source port
4006 + *        on the local host is in the range 0 through 1023.
4007 + * 
4008 + *     3. The rshd daemon uses the source address of the initial connection
4009 + *        request to determine the name of the client host. If the name cannot
4010 + *        be determined, the rshd daemon uses the dotted decimal representation
4011 + *        of the client host's address.
4012 + * 
4013 + *     4. The rshd daemon retrieves the following information from the initial
4014 + *        socket:
4015 + * 
4016 + *         * A null-terminated string of at most 16 bytes interpreted as
4017 + *           the user name of the user on the client host.
4018 + * 
4019 + *         * A null-terminated string of at most 16 bytes interpreted as
4020 + *           the user name to be used on the local server host.
4021 + * 
4022 + *         * Another null-terminated string interpreted as a command line
4023 + *           to be passed to a shell on the local server host.
4024 + * 
4025 + *     5. The rshd daemon attempts to validate the user using the following steps:
4026 + * 
4027 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
4028 + *            file and tries to switch to the home directory (using the chdir
4029 + *            subroutine). If either the lookup or the directory change fails,
4030 + *            the rshd daemon terminates the connection.
4031 + * 
4032 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
4033 + *            the /etc/hosts.equiv file to see if the name of the client
4034 + *            workstation is listed. If the client workstation is listed as an
4035 + *            equivalent host, the rshd daemon validates the user.
4036 + * 
4037 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4038 + *            authenticate the user by checking the .rhosts file.
4039 + * 
4040 + *         d. If either the $HOME/.rhosts authentication fails or the
4041 + *            client host is not an equivalent host, the rshd daemon
4042 + *            terminates the connection.
4043 + * 
4044 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
4045 + *        on the initial connection and passes the command line to the user's
4046 + *        local login shell. The shell then inherits the network connections
4047 + *        established by the rshd daemon."
4048 + * 
4049 + */
4050 +
4051 +
4052 +#include <linux/module.h>
4053 +#include <linux/netfilter.h>
4054 +#include <linux/ip.h>
4055 +#include <net/checksum.h>
4056 +#include <net/tcp.h>
4057 +
4058 +#include <linux/netfilter_ipv4/lockhelp.h>
4059 +#include <linux/netfilter_ipv4/ip_tables.h>
4060 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4061 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4062 +
4063 +#define MAX_PORTS 8
4064 +static int ports[MAX_PORTS];
4065 +static int ports_n_c = 0;
4066 +
4067 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4068 +MODULE_DESCRIPTION("RSH connection tracking module");
4069 +MODULE_LICENSE("GPL");
4070 +#ifdef MODULE_PARM
4071 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4072 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4073 +#endif
4074 +
4075 +DECLARE_LOCK(ip_rsh_lock);
4076 +struct module *ip_conntrack_rsh = THIS_MODULE;
4077 +
4078 +#if 0
4079 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4080 +                                       format, ## args)
4081 +#else
4082 +#define DEBUGP(format, args...)
4083 +#endif
4084 +
4085 +
4086 +
4087 +/* FIXME: This should be in userspace.  Later. */
4088 +static int help(const struct iphdr *iph, size_t len,
4089 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4090 +{
4091 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4092 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4093 +       const char *data = (const char *) tcph + tcph->doff * 4;
4094 +       u_int32_t tcplen = len - iph->ihl * 4;
4095 +       int dir = CTINFO2DIR(ctinfo);
4096 +        struct ip_conntrack_expect expect, *exp = &expect;
4097 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4098 +       u_int16_t port;
4099 +       int maxoctet;
4100 +
4101 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
4102 +        *  original array size used in rshd/glibc) -- is there a
4103 +        *  vulnerability in rshd.c in the looped port *= 10?
4104 +        */
4105 +
4106 +
4107 +       DEBUGP("entered\n");
4108 +
4109 +       /* bail if packet is not from RSH client */
4110 +       if (dir == IP_CT_DIR_REPLY)
4111 +               return NF_ACCEPT;
4112 +
4113 +       /* Until there's been traffic both ways, don't look in packets. */
4114 +       if (ctinfo != IP_CT_ESTABLISHED
4115 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4116 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
4117 +               return NF_ACCEPT;
4118 +       }
4119 +
4120 +       /* Not whole TCP header? */
4121 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4122 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4123 +               return NF_ACCEPT;
4124 +       }
4125 +
4126 +       /* Checksum invalid?  Ignore. */
4127 +       /* FIXME: Source route IP option packets --RR */
4128 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4129 +                        csum_partial((char *) tcph, tcplen, 0))) {
4130 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4131 +                    tcph, tcplen, NIPQUAD(iph->saddr),
4132 +                    NIPQUAD(iph->daddr));
4133 +               return NF_ACCEPT;
4134 +       }
4135 +
4136 +       /* find the rsh stderr port */
4137 +       maxoctet = 4;
4138 +       port = 0;
4139 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4140 +               if (*data < 0)
4141 +                       return(1);
4142 +               if (*data == 0)
4143 +                       break;
4144 +               if (*data < 48 || *data > 57) {
4145 +                       DEBUGP("these aren't the packets you're looking for ..\n");
4146 +                       return NF_ACCEPT;
4147 +               }
4148 +               port = port * 10 + ( *data - 48 );
4149 +       }
4150 +
4151 +       /* dont relate sessions that try to expose the client */
4152 +       DEBUGP("found port %u\n", port);
4153 +       if (port > 1023) {
4154 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
4155 +               return NF_ACCEPT;
4156 +       }
4157 +
4158 +
4159 +       LOCK_BH(&ip_rsh_lock);
4160 +
4161 +       /*  new(,related) connection is;
4162 +        *          reply + dst (uint)port + src port (0:1023)
4163 +        */
4164 +       memset(&expect, 0, sizeof(expect));
4165 +
4166 +       /*  save some discovered data, in case someone ever wants to write
4167 +        *  a NAT module for this bastard ..
4168 +        */
4169 +       exp_rsh_info->port = port;
4170 +
4171 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4172 +
4173 +
4174 +       /* Watch out, Radioactive-Man! */
4175 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4176 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4177 +       exp->tuple.src.u.tcp.port = 0;
4178 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4179 +       exp->tuple.dst.protonum = IPPROTO_TCP;
4180 +
4181 +       exp->mask.src.ip = 0xffffffff;
4182 +       exp->mask.dst.ip = 0xffffffff;
4183 +
4184 +       exp->mask.src.u.tcp.port = htons(0xfc00);
4185 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
4186 +       exp->mask.dst.protonum = 0xffff;
4187 +
4188 +       exp->expectfn = NULL;
4189 +
4190 +       ip_conntrack_expect_related(ct, &expect);
4191 +
4192 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4193 +               NIPQUAD(exp->tuple.src.ip),
4194 +               ntohs(exp->tuple.src.u.tcp.port),
4195 +               NIPQUAD(exp->tuple.dst.ip),
4196 +               ntohs(exp->tuple.dst.u.tcp.port));
4197 +
4198 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4199 +               NIPQUAD(exp->mask.src.ip),
4200 +               ntohs(exp->mask.src.u.tcp.port),
4201 +               NIPQUAD(exp->mask.dst.ip),
4202 +               ntohs(exp->mask.dst.u.tcp.port));
4203 +       UNLOCK_BH(&ip_rsh_lock);
4204 +
4205 +       return NF_ACCEPT;
4206 +}
4207 +
4208 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4209 +
4210 +static void fini(void);
4211 +
4212 +static int __init init(void)
4213 +{
4214 +       int port, ret;
4215 +       static char name[10];
4216 +
4217 +
4218 +       /* If no port given, default to standard RSH port */
4219 +       if (ports[0] == 0)
4220 +               ports[0] = RSH_PORT;
4221 +
4222 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4223 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4224 +
4225 +                if (ports[port] == RSH_PORT)
4226 +                        sprintf(name, "rsh");
4227 +                else
4228 +                        sprintf(name, "rsh-%d", port);
4229 +
4230 +               rsh_helpers[port].name = name;
4231 +               rsh_helpers[port].me = THIS_MODULE;
4232 +               rsh_helpers[port].max_expected = 1;
4233 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4234 +               rsh_helpers[port].timeout = 0;
4235 +
4236 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4237 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
4238 +
4239 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
4240 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4241 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4242 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4243 +
4244 +               rsh_helpers[port].help = help;
4245 +
4246 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4247 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4248 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
4249 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4250 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4251 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4252 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4253 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
4254 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4255 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
4256 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4257 +
4258 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4259 +
4260 +               if (ret) {
4261 +                       printk("ERROR registering port %d\n",
4262 +                               ports[port]);
4263 +                       fini();
4264 +                       return -EBUSY;
4265 +               }
4266 +               ports_n_c++;
4267 +       }
4268 +       return 0;
4269 +}
4270 +
4271 +/* This function is intentionally _NOT_ defined as __exit, because 
4272 + * it is needed by the init function */
4273 +static void fini(void)
4274 +{
4275 +       int port;
4276 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4277 +               DEBUGP("unregistering port %d\n", ports[port]);
4278 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
4279 +       }
4280 +}
4281 +
4282 +module_init(init);
4283 +module_exit(fini);
4284 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c
4285 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-04-16 08:59:08.000000000 +0200
4286 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-04-16 09:17:11.000000000 +0200
4287 @@ -110,6 +110,9 @@
4288                 len += sprintf(buffer + len, "[ASSURED] ");
4289         len += sprintf(buffer + len, "use=%u ",
4290                        atomic_read(&conntrack->ct_general.use));
4291 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
4292 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
4293 +#endif
4294         len += sprintf(buffer + len, "\n");
4295  
4296         return len;
4297 @@ -633,6 +636,7 @@
4298  EXPORT_SYMBOL(ip_conntrack_alter_reply);
4299  EXPORT_SYMBOL(ip_conntrack_destroyed);
4300  EXPORT_SYMBOL(ip_conntrack_get);
4301 +EXPORT_SYMBOL(__ip_conntrack_confirm);
4302  EXPORT_SYMBOL(need_ip_conntrack);
4303  EXPORT_SYMBOL(ip_conntrack_helper_register);
4304  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
4305 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_talk.c
4306 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_talk.c  1970-01-01 01:00:00.000000000 +0100
4307 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_talk.c      2004-04-16 09:18:58.000000000 +0200
4308 @@ -0,0 +1,360 @@
4309 +/* 
4310 + * talk extension for IP connection tracking. 
4311 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4312 + *
4313 + *      This program is free software; you can redistribute it and/or
4314 + *      modify it under the terms of the GNU General Public License
4315 + *      as published by the Free Software Foundation; either version
4316 + *      2 of the License, or (at your option) any later version.
4317 + **
4318 + *     Module load syntax:
4319 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
4320 + *
4321 + *             talk=[0|1]      disable|enable old talk support
4322 + *            ntalk=[0|1]      disable|enable ntalk support
4323 + *           ntalk2=[0|1]      disable|enable ntalk2 support
4324 + *
4325 + *     The default is talk=1 ntalk=1 ntalk2=1
4326 + *
4327 + *     The helper does not support simultaneous talk requests.
4328 + **
4329 + *
4330 + *             ASCII art on talk protocols
4331 + *     
4332 + *     
4333 + *     caller server               callee server
4334 + *             |     \           /
4335 + *             |       \       /
4336 + *             |         \   /
4337 + *             |           /  
4338 + *             |         /   \
4339 + *           2 |     1 /       \ 3
4340 + *     caller client  ----------- callee client
4341 + *                              4
4342 + *
4343 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
4344 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
4345 + *     3. callee client <-> caller server: LOOK_UP invitation
4346 + *     4. callee client <-> caller client: talk data channel
4347 + *
4348 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
4349 + *      draft-hunter-talk-00.txt
4350 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
4351 + */
4352 +#include <linux/config.h>
4353 +#include <linux/module.h>
4354 +#include <linux/netfilter.h>
4355 +#include <linux/ip.h>
4356 +#include <net/checksum.h>
4357 +#include <net/udp.h>
4358 +
4359 +#include <linux/netfilter_ipv4/lockhelp.h>
4360 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4361 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4362 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4363 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
4364 +
4365 +/* Default all talk protocols are supported */
4366 +static int talk = 1;
4367 +static int ntalk = 1;
4368 +static int ntalk2 = 1;
4369 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
4370 +MODULE_DESCRIPTION("talk connection tracking module");
4371 +MODULE_LICENSE("GPL");
4372 +#ifdef MODULE_PARM
4373 +MODULE_PARM(talk, "i");
4374 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
4375 +MODULE_PARM(ntalk, "i");
4376 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
4377 +MODULE_PARM(ntalk2, "i");
4378 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
4379 +#endif
4380 +
4381 +DECLARE_LOCK(ip_talk_lock);
4382 +struct module *ip_conntrack_talk = THIS_MODULE;
4383 +
4384 +#if 0
4385 +#define DEBUGP printk
4386 +#else
4387 +#define DEBUGP(format, args...)
4388 +#endif
4389 +
4390 +static int talk_expect(struct ip_conntrack *ct);
4391 +static int ntalk_expect(struct ip_conntrack *ct);
4392 +
4393 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
4394 +
4395 +static int talk_help_response(const struct iphdr *iph, size_t len,
4396 +                             struct ip_conntrack *ct,
4397 +                             enum ip_conntrack_info ctinfo,
4398 +                             int talk_port,
4399 +                             u_char mode,
4400 +                             u_char type,
4401 +                             u_char answer,
4402 +                             struct talk_addr *addr)
4403 +{
4404 +       int dir = CTINFO2DIR(ctinfo);
4405 +       struct ip_conntrack_expect expect, *exp = &expect;
4406 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
4407 +
4408 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
4409 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
4410 +               type, answer);
4411 +
4412 +       if (!(answer == SUCCESS && type == mode))
4413 +               return NF_ACCEPT;
4414 +       
4415 +       memset(&expect, 0, sizeof(expect));
4416 +       
4417 +       if (type == ANNOUNCE) {
4418 +
4419 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
4420 +
4421 +               /* update the talk info */
4422 +               LOCK_BH(&ip_talk_lock);
4423 +               exp_talk_info->port = htons(talk_port);
4424 +
4425 +               /* expect callee client -> caller server message */
4426 +               exp->tuple = ((struct ip_conntrack_tuple)
4427 +                       { { ct->tuplehash[dir].tuple.src.ip,
4428 +                           { 0 } },
4429 +                         { ct->tuplehash[dir].tuple.dst.ip,
4430 +                           { .tcp = { htons(talk_port) } },
4431 +                           IPPROTO_UDP }});
4432 +               exp->mask = ((struct ip_conntrack_tuple)
4433 +                       { { 0xFFFFFFFF, { 0 } },
4434 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4435 +               
4436 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
4437 +
4438 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
4439 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
4440 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
4441 +
4442 +               /* Ignore failure; should only happen with NAT */
4443 +               ip_conntrack_expect_related(ct, &expect);
4444 +               UNLOCK_BH(&ip_talk_lock);
4445 +       }
4446 +       if (type == LOOK_UP) {
4447 +
4448 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
4449 +
4450 +               /* update the talk info */
4451 +               LOCK_BH(&ip_talk_lock);
4452 +               exp_talk_info->port = addr->ta_port;
4453 +
4454 +               /* expect callee client -> caller client connection */
4455 +               exp->tuple = ((struct ip_conntrack_tuple)
4456 +                       { { ct->tuplehash[!dir].tuple.src.ip,
4457 +                           { 0 } },
4458 +                         { addr->ta_addr,
4459 +                           { addr->ta_port },
4460 +                           IPPROTO_TCP }});
4461 +               exp->mask = ((struct ip_conntrack_tuple)
4462 +                       { { 0xFFFFFFFF, { 0 } },
4463 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
4464 +               
4465 +               exp->expectfn = NULL;
4466 +               
4467 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
4468 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
4469 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
4470 +
4471 +               /* Ignore failure; should only happen with NAT */
4472 +               ip_conntrack_expect_related(ct, &expect);
4473 +               UNLOCK_BH(&ip_talk_lock);
4474 +       }
4475 +                   
4476 +       return NF_ACCEPT;
4477 +}
4478 +
4479 +/* FIXME: This should be in userspace.  Later. */
4480 +static int talk_help(const struct iphdr *iph, size_t len,
4481 +                    struct ip_conntrack *ct,
4482 +                    enum ip_conntrack_info ctinfo,
4483 +                    int talk_port,
4484 +                    u_char mode)
4485 +{
4486 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
4487 +       const char *data = (const char *)udph + sizeof(struct udphdr);
4488 +       int dir = CTINFO2DIR(ctinfo);
4489 +       size_t udplen;
4490 +
4491 +       DEBUGP("ip_ct_talk_help: help entered\n");
4492 +
4493 +       /* Until there's been traffic both ways, don't look in packets. */
4494 +       if (ctinfo != IP_CT_ESTABLISHED
4495 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4496 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
4497 +               return NF_ACCEPT;
4498 +       }
4499 +
4500 +       /* Not whole UDP header? */
4501 +       udplen = len - iph->ihl * 4;
4502 +       if (udplen < sizeof(struct udphdr)) {
4503 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
4504 +               return NF_ACCEPT;
4505 +       }
4506 +
4507 +       /* Checksum invalid?  Ignore. */
4508 +       /* FIXME: Source route IP option packets --RR */
4509 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4510 +                             csum_partial((char *)udph, udplen, 0))) {
4511 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4512 +                      udph, udplen, NIPQUAD(iph->saddr),
4513 +                      NIPQUAD(iph->daddr));
4514 +               return NF_ACCEPT;
4515 +       }
4516 +       
4517 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4518 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
4519 +
4520 +       if (dir == IP_CT_DIR_ORIGINAL)
4521 +               return NF_ACCEPT;
4522 +               
4523 +       if (talk_port == TALK_PORT
4524 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
4525 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4526 +                                         ((struct talk_response *)data)->type, 
4527 +                                         ((struct talk_response *)data)->answer,
4528 +                                         &(((struct talk_response *)data)->addr));
4529 +       else if (talk_port == NTALK_PORT
4530 +                 && ntalk
4531 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
4532 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
4533 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4534 +                                         ((struct ntalk_response *)data)->type, 
4535 +                                         ((struct ntalk_response *)data)->answer,
4536 +                                         &(((struct ntalk_response *)data)->addr));
4537 +       else if (talk_port == NTALK_PORT
4538 +                && ntalk2
4539 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
4540 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
4541 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4542 +                                         ((struct ntalk2_response *)data)->type, 
4543 +                                         ((struct ntalk2_response *)data)->answer,
4544 +                                         &(((struct ntalk2_response *)data)->addr));
4545 +       else {
4546 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
4547 +                      (unsigned)udplen - sizeof(struct udphdr), 
4548 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
4549 +               return NF_ACCEPT;
4550 +       }
4551 +}
4552 +
4553 +static int lookup_help(const struct iphdr *iph, size_t len,
4554 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4555 +{
4556 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
4557 +}
4558 +
4559 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
4560 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4561 +{
4562 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
4563 +}
4564 +
4565 +static struct ip_conntrack_helper lookup_helpers[2] = 
4566 +       { { { NULL, NULL },
4567 +           "talk",                                     /* name */
4568 +           0,                                          /* flags */
4569 +           NULL,                                       /* module */
4570 +           1,                                          /* max_expected */
4571 +           240,                                        /* timeout */
4572 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
4573 +             { 0, { 0 }, IPPROTO_UDP } },
4574 +           { { 0, { 0xFFFF } },                        /* mask */
4575 +             { 0, { 0 }, 0xFFFF } },
4576 +           lookup_help },                              /* helper */
4577 +          { { NULL, NULL },
4578 +            "ntalk",                                   /* name */
4579 +           0,                                          /* flags */
4580 +           NULL,                                       /* module */
4581 +           1,                                          /* max_expected */
4582 +           240,                                        /* timeout */
4583 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
4584 +             { 0, { 0 }, IPPROTO_UDP } },
4585 +           { { 0, { 0xFFFF } },                        /* mask */
4586 +             { 0, { 0 }, 0xFFFF } },
4587 +           lookup_nhelp }                              /* helper */
4588 +        };
4589 +
4590 +static int talk_expect(struct ip_conntrack *ct)
4591 +{
4592 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
4593 +       WRITE_LOCK(&ip_conntrack_lock);
4594 +       ct->helper = &lookup_helpers[0];
4595 +       WRITE_UNLOCK(&ip_conntrack_lock);
4596 +        
4597 +       return NF_ACCEPT;       /* unused */
4598 +}
4599 +
4600 +static int ntalk_expect(struct ip_conntrack *ct)
4601 +{
4602 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
4603 +       WRITE_LOCK(&ip_conntrack_lock);
4604 +       ct->helper = &lookup_helpers[1];
4605 +       WRITE_UNLOCK(&ip_conntrack_lock);
4606 +        
4607 +       return NF_ACCEPT;       /* unused */
4608 +}
4609 +
4610 +static int help(const struct iphdr *iph, size_t len,
4611 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4612 +{
4613 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
4614 +}
4615 +
4616 +static int nhelp(const struct iphdr *iph, size_t len,
4617 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4618 +{
4619 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
4620 +}
4621 +
4622 +static struct ip_conntrack_helper talk_helpers[2] = 
4623 +       { { { NULL, NULL },
4624 +           "talk",                                     /* name */
4625 +           0,                                          /* flags */
4626 +           THIS_MODULE,                                /* module */
4627 +           1,                                          /* max_expected */
4628 +           240,                                        /* timeout */
4629 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
4630 +             { 0, { 0 }, IPPROTO_UDP } },
4631 +           { { 0, { 0xFFFF } },                        /* mask */
4632 +             { 0, { 0 }, 0xFFFF } },
4633 +           help },                                     /* helper */
4634 +          { { NULL, NULL },
4635 +           "ntalk",                                    /* name */
4636 +           0,                                          /* flags */
4637 +           THIS_MODULE,                                /* module */
4638 +           1,                                          /* max_expected */
4639 +           240,                                        /* timeout */
4640 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
4641 +             { 0, { 0 }, IPPROTO_UDP } },
4642 +           { { 0, { 0xFFFF } },                        /* mask */
4643 +             { 0, { 0 }, 0xFFFF } },
4644 +           nhelp }                                     /* helper */
4645 +       };
4646 +
4647 +static int __init init(void)
4648 +{
4649 +       if (talk > 0)
4650 +               ip_conntrack_helper_register(&talk_helpers[0]);
4651 +       if (ntalk > 0 || ntalk2 > 0)
4652 +               ip_conntrack_helper_register(&talk_helpers[1]);
4653 +               
4654 +       return 0;
4655 +}
4656 +
4657 +static void __exit fini(void)
4658 +{
4659 +       if (talk > 0)
4660 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
4661 +       if (ntalk > 0 || ntalk2 > 0)
4662 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
4663 +}
4664 +
4665 +EXPORT_SYMBOL(ip_talk_lock);
4666 +
4667 +module_init(init);
4668 +module_exit(fini);
4669 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_h323.c
4670 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_h323.c        1970-01-01 01:00:00.000000000 +0100
4671 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_h323.c    2004-04-16 09:17:05.000000000 +0200
4672 @@ -0,0 +1,419 @@
4673 +/* 
4674 + * H.323 'brute force' extension for NAT alteration. 
4675 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4676 + *
4677 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
4678 + * (http://www.coritel.it/projects/sofia/nat.html)
4679 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
4680 + * the unregistered helpers to the conntrack entries.
4681 + */
4682 +
4683 +
4684 +#include <linux/module.h>
4685 +#include <linux/netfilter.h>
4686 +#include <linux/ip.h>
4687 +#include <net/checksum.h>
4688 +#include <net/tcp.h>
4689 +
4690 +#include <linux/netfilter_ipv4/lockhelp.h>
4691 +#include <linux/netfilter_ipv4/ip_nat.h>
4692 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
4693 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
4694 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
4695 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4696 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
4697 +
4698 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
4699 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
4700 +MODULE_LICENSE("GPL");
4701 +
4702 +DECLARE_LOCK_EXTERN(ip_h323_lock);
4703 +struct module *ip_nat_h323 = THIS_MODULE;
4704 +
4705 +#if 0
4706 +#define DEBUGP printk
4707 +#else
4708 +#define DEBUGP(format, args...)
4709 +#endif
4710 +
4711 +/* FIXME: Time out? --RR */
4712 +
4713 +static unsigned int 
4714 +h225_nat_expected(struct sk_buff **pskb,
4715 +                 unsigned int hooknum,
4716 +                 struct ip_conntrack *ct,
4717 +                 struct ip_nat_info *info);
4718 +
4719 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
4720 +                                 struct ip_conntrack_expect *exp,
4721 +                                 struct ip_nat_info *info,
4722 +                                 enum ip_conntrack_info ctinfo,
4723 +                                 unsigned int hooknum,
4724 +                                 struct sk_buff **pskb);
4725 +                 
4726 +static struct ip_nat_helper h245 = 
4727 +       { { NULL, NULL },
4728 +          "H.245",                             /* name */
4729 +         0,                                    /* flags */
4730 +         NULL,                                 /* module */
4731 +         { { 0, { 0 } },                       /* tuple */
4732 +           { 0, { 0 }, IPPROTO_TCP } },
4733 +         { { 0, { 0xFFFF } },                  /* mask */
4734 +           { 0, { 0 }, 0xFFFF } },
4735 +         h225_nat_help,                        /* helper */
4736 +         h225_nat_expected                     /* expectfn */
4737 +       };
4738 +
4739 +static unsigned int
4740 +h225_nat_expected(struct sk_buff **pskb,
4741 +                 unsigned int hooknum,
4742 +                 struct ip_conntrack *ct,
4743 +                 struct ip_nat_info *info)
4744 +{
4745 +       struct ip_nat_multi_range mr;
4746 +       u_int32_t newdstip, newsrcip, newip;
4747 +       u_int16_t port;
4748 +       struct ip_ct_h225_expect *exp_info;
4749 +       struct ip_ct_h225_master *master_info;
4750 +       struct ip_conntrack *master = master_ct(ct);
4751 +       unsigned int is_h225, ret;
4752 +       
4753 +       IP_NF_ASSERT(info);
4754 +       IP_NF_ASSERT(master);
4755 +
4756 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
4757 +
4758 +       DEBUGP("h225_nat_expected: We have a connection!\n");
4759 +       master_info = &ct->master->expectant->help.ct_h225_info;
4760 +       exp_info = &ct->master->help.exp_h225_info;
4761 +
4762 +       LOCK_BH(&ip_h323_lock);
4763 +
4764 +       DEBUGP("master: ");
4765 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4766 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
4767 +       DEBUGP("conntrack: ");
4768 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4769 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
4770 +               /* Make connection go to the client. */
4771 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4772 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4773 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
4774 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
4775 +       } else {
4776 +               /* Make the connection go to the server */
4777 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4778 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4779 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
4780 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
4781 +       }
4782 +       port = exp_info->port;
4783 +       is_h225 = master_info->is_h225 == H225_PORT;
4784 +       UNLOCK_BH(&ip_h323_lock);
4785 +       
4786 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
4787 +               newip = newsrcip;
4788 +       else
4789 +               newip = newdstip;
4790 +
4791 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
4792 +
4793 +       mr.rangesize = 1;
4794 +       /* We don't want to manip the per-protocol, just the IPs... */
4795 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
4796 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
4797 +
4798 +       /* ... unless we're doing a MANIP_DST, in which case, make
4799 +          sure we map to the correct port */
4800 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
4801 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
4802 +               mr.range[0].min = mr.range[0].max
4803 +                       = ((union ip_conntrack_manip_proto)
4804 +                               { .tcp = { port } });
4805 +       }
4806 +
4807 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
4808 +       
4809 +       if (is_h225) {
4810 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
4811 +               /* NAT expectfn called with ip_nat_lock write-locked */
4812 +               info->helper = &h245;
4813 +       }
4814 +       return ret;
4815 +}
4816 +
4817 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
4818 +                                    struct sk_buff **pskb,
4819 +                                    enum ip_conntrack_info ctinfo)
4820 +{
4821 +       struct iphdr *iph = (*pskb)->nh.iph;
4822 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
4823 +       char *data = (char *) tcph + tcph->doff * 4;
4824 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
4825 +       u_int32_t datalen = tcplen - tcph->doff*4;
4826 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
4827 +       u_int32_t newip;
4828 +       u_int16_t port;
4829 +       int i;
4830 +
4831 +       MUST_BE_LOCKED(&ip_h323_lock);
4832 +
4833 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
4834 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
4835 +                       ? "yes" : "no",
4836 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
4837 +                       ? "yes" : "no");
4838 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
4839 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
4840 +               return 1;
4841 +
4842 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
4843 +               info->offset[IP_CT_DIR_ORIGINAL], 
4844 +               info->offset[IP_CT_DIR_REPLY],
4845 +               tcplen);
4846 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4847 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
4848 +
4849 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
4850 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
4851 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
4852 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
4853 +               if (!between(info->seq[i], ntohl(tcph->seq), 
4854 +                            ntohl(tcph->seq) + datalen))
4855 +                       continue;
4856 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
4857 +                            ntohl(tcph->seq) + datalen)) {
4858 +                       /* Partial retransmisison. It's a cracker being funky. */
4859 +                       if (net_ratelimit()) {
4860 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
4861 +                                    info->seq[i],
4862 +                                    ntohl(tcph->seq),
4863 +                                    ntohl(tcph->seq) + datalen);
4864 +                       }
4865 +                       return 0;
4866 +               }
4867 +
4868 +               /* Change address inside packet to match way we're mapping
4869 +                  this connection. */
4870 +               if (i == IP_CT_DIR_ORIGINAL) {
4871 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
4872 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
4873 +               } else {
4874 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
4875 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
4876 +               }
4877 +
4878 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
4879 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
4880 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
4881 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
4882 +
4883 +               /* Modify the packet */
4884 +               *(u_int32_t *)(data + info->offset[i]) = newip;
4885 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
4886 +       
4887 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
4888 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
4889 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
4890 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
4891 +       }
4892 +
4893 +       /* fix checksum information */
4894 +
4895 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
4896 +                                    datalen, 0);
4897 +
4898 +       tcph->check = 0;
4899 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4900 +                                  csum_partial((char *)tcph, tcph->doff*4,
4901 +                                          (*pskb)->csum));
4902 +       ip_send_check(iph);
4903 +
4904 +       return 1;
4905 +}
4906 +
4907 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
4908 +                          struct ip_conntrack *ct,
4909 +                          struct sk_buff **pskb,
4910 +                          enum ip_conntrack_info ctinfo,
4911 +                          struct ip_conntrack_expect *expect)
4912 +{
4913 +       u_int32_t newip;
4914 +       u_int16_t port;
4915 +       struct ip_conntrack_tuple newtuple;
4916 +       struct iphdr *iph = (*pskb)->nh.iph;
4917 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
4918 +       char *data = (char *) tcph + tcph->doff * 4;
4919 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
4920 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
4921 +       int is_h225;
4922 +
4923 +       MUST_BE_LOCKED(&ip_h323_lock);
4924 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
4925 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4926 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
4927 +
4928 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
4929 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
4930 +               /* Partial retransmisison. It's a cracker being funky. */
4931 +               if (net_ratelimit()) {
4932 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
4933 +                            expect->seq,
4934 +                            ntohl(tcph->seq),
4935 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
4936 +               }
4937 +               return 0;
4938 +       }
4939 +
4940 +       /* Change address inside packet to match way we're mapping
4941 +          this connection. */
4942 +       if (info->dir == IP_CT_DIR_REPLY) {
4943 +               /* Must be where client thinks server is */
4944 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4945 +               /* Expect something from client->server */
4946 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4947 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4948 +       } else {
4949 +               /* Must be where server thinks client is */
4950 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4951 +               /* Expect something from server->client */
4952 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4953 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4954 +       }
4955 +
4956 +       is_h225 = (master_info->is_h225 == H225_PORT);
4957 +
4958 +       if (is_h225) {
4959 +               newtuple.dst.protonum = IPPROTO_TCP;
4960 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
4961 +       } else {
4962 +               newtuple.dst.protonum = IPPROTO_UDP;
4963 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
4964 +       }
4965 +       
4966 +       /* Try to get same port: if not, try to change it. */
4967 +       for (port = ntohs(info->port); port != 0; port++) {
4968 +               if (is_h225)
4969 +                       newtuple.dst.u.tcp.port = htons(port);
4970 +               else
4971 +                       newtuple.dst.u.udp.port = htons(port);
4972 +
4973 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
4974 +                       break;
4975 +       }
4976 +       if (port == 0) {
4977 +               DEBUGP("h323_data_fixup: no free port found!\n");
4978 +               return 0;
4979 +       }
4980 +
4981 +       port = htons(port);
4982 +
4983 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
4984 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
4985 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
4986 +
4987 +       /* Modify the packet */
4988 +       *(u_int32_t *)(data + info->offset) = newip;
4989 +       *(u_int16_t *)(data + info->offset + 4) = port;
4990 +       
4991 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
4992 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
4993 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
4994 +
4995 +       /* fix checksum information  */
4996 +       /* FIXME: usually repeated multiple times in the case of H.245! */
4997 +
4998 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
4999 +                                    tcplen - tcph->doff*4, 0);
5000 +
5001 +       tcph->check = 0;
5002 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5003 +                                  csum_partial((char *)tcph, tcph->doff*4,
5004 +                                          (*pskb)->csum));
5005 +       ip_send_check(iph);
5006 +
5007 +       return 1;
5008 +}
5009 +
5010 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5011 +                                 struct ip_conntrack_expect *exp,
5012 +                                 struct ip_nat_info *info,
5013 +                                 enum ip_conntrack_info ctinfo,
5014 +                                 unsigned int hooknum,
5015 +                                 struct sk_buff **pskb)
5016 +{
5017 +       int dir;
5018 +       struct ip_ct_h225_expect *exp_info;
5019 +       
5020 +       /* Only mangle things once: original direction in POST_ROUTING
5021 +          and reply direction on PRE_ROUTING. */
5022 +       dir = CTINFO2DIR(ctinfo);
5023 +       DEBUGP("nat_h323: dir %s at hook %s\n",
5024 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5025 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5026 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5027 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5028 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5029 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5030 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
5031 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5032 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5033 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5034 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5035 +               return NF_ACCEPT;
5036 +       }
5037 +
5038 +       if (!exp) {
5039 +               LOCK_BH(&ip_h323_lock);
5040 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
5041 +                       UNLOCK_BH(&ip_h323_lock);
5042 +                       return NF_DROP;
5043 +               }
5044 +               UNLOCK_BH(&ip_h323_lock);
5045 +               return NF_ACCEPT;
5046 +       }
5047 +               
5048 +       exp_info = &exp->help.exp_h225_info;
5049 +
5050 +       LOCK_BH(&ip_h323_lock);
5051 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
5052 +               UNLOCK_BH(&ip_h323_lock);
5053 +               return NF_DROP;
5054 +       }
5055 +       UNLOCK_BH(&ip_h323_lock);
5056 +
5057 +       return NF_ACCEPT;
5058 +}
5059 +
5060 +static struct ip_nat_helper h225 = 
5061 +       { { NULL, NULL },
5062 +         "H.225",                                      /* name */
5063 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
5064 +         THIS_MODULE,                                  /* module */
5065 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
5066 +           { 0, { 0 }, IPPROTO_TCP } },
5067 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
5068 +           { 0, { 0 }, 0xFFFF } },
5069 +         h225_nat_help,                                /* helper */
5070 +         h225_nat_expected                             /* expectfn */
5071 +       };
5072 +
5073 +static int __init init(void)
5074 +{
5075 +       int ret;
5076 +       
5077 +       ret = ip_nat_helper_register(&h225);
5078 +
5079 +       if (ret != 0)
5080 +               printk("ip_nat_h323: cannot initialize the module!\n");
5081 +
5082 +       return ret;
5083 +}
5084 +
5085 +static void __exit fini(void)
5086 +{
5087 +       ip_nat_helper_unregister(&h225);
5088 +}
5089 +
5090 +module_init(init);
5091 +module_exit(fini);
5092 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_mms.c
5093 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
5094 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_mms.c     2004-04-16 09:17:32.000000000 +0200
5095 @@ -0,0 +1,350 @@
5096 +/* MMS extension for TCP NAT alteration.
5097 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5098 + * based on ip_nat_ftp.c and ip_nat_irc.c
5099 + *
5100 + * ip_nat_mms.c v0.3 2002-09-22
5101 + *
5102 + *      This program is free software; you can redistribute it and/or
5103 + *      modify it under the terms of the GNU General Public License
5104 + *      as published by the Free Software Foundation; either version
5105 + *      2 of the License, or (at your option) any later version.
5106 + *
5107 + *      Module load syntax:
5108 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
5109 + *
5110 + *      Please give the ports of all MMS servers You wish to connect to.
5111 + *      If you don't specify ports, the default will be TCP port 1755.
5112 + *
5113 + *      More info on MMS protocol, firewalls and NAT:
5114 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
5115 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
5116 + *
5117 + *      The SDP project people are reverse-engineering MMS:
5118 + *      http://get.to/sdp
5119 + */
5120 +
5121 +/* FIXME: issue with UDP & fragmentation with this URL: 
5122 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
5123 +   may be related to out-of-order first packets:
5124 +   basically the expectation is set up correctly, then the server sends
5125 +   a first UDP packet which is fragmented plus arrives out-of-order.
5126 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
5127 +   an ICMP unreachable back to the server */
5128 +
5129 +#include <linux/module.h>
5130 +#include <linux/netfilter_ipv4.h>
5131 +#include <linux/ip.h>
5132 +#include <linux/tcp.h>
5133 +#include <net/tcp.h>
5134 +#include <linux/netfilter_ipv4/ip_nat.h>
5135 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5136 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5137 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
5138 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5139 +
5140 +#if 0 
5141 +#define DEBUGP printk
5142 +#define DUMP_BYTES(address, counter)                                \
5143 +({                                                                  \
5144 +       int temp_counter;                                           \
5145 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
5146 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
5147 +       };                                                          \
5148 +       DEBUGP("\n");                                               \
5149 +})
5150 +#else
5151 +#define DEBUGP(format, args...)
5152 +#define DUMP_BYTES(address, counter)
5153 +#endif
5154 +
5155 +#define MAX_PORTS 8
5156 +static int ports[MAX_PORTS];
5157 +static int ports_c = 0;
5158 +
5159 +#ifdef MODULE_PARM
5160 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5161 +#endif
5162 +
5163 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5164 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
5165 +MODULE_LICENSE("GPL");
5166 +
5167 +DECLARE_LOCK_EXTERN(ip_mms_lock);
5168 +
5169 +/* FIXME: Time out? --RR */
5170 +
5171 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
5172 +                          struct ip_conntrack *ct,
5173 +                          struct sk_buff **pskb,
5174 +                          enum ip_conntrack_info ctinfo,
5175 +                          struct ip_conntrack_expect *expect)
5176 +{
5177 +       u_int32_t newip;
5178 +       struct ip_conntrack_tuple t;
5179 +       struct iphdr *iph = (*pskb)->nh.iph;
5180 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5181 +       char *data = (char *)tcph + tcph->doff * 4;
5182 +       int i, j, k, port;
5183 +       u_int16_t mms_proto;
5184 +
5185 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
5186 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
5187 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
5188 +
5189 +       int zero_padding;
5190 +
5191 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
5192 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
5193 +       char proto_string[6];
5194 +       
5195 +       MUST_BE_LOCKED(&ip_mms_lock);
5196 +
5197 +       /* what was the protocol again ? */
5198 +       mms_proto = expect->tuple.dst.protonum;
5199 +       sprintf(proto_string, "%u", mms_proto);
5200 +       
5201 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
5202 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
5203 +              mms_proto == IPPROTO_UDP ? "UDP"
5204 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
5205 +       
5206 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5207 +
5208 +       /* Alter conntrack's expectations. */
5209 +       t = expect->tuple;
5210 +       t.dst.ip = newip;
5211 +       for (port = ct_mms_info->port; port != 0; port++) {
5212 +               t.dst.u.tcp.port = htons(port);
5213 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
5214 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
5215 +                       break;
5216 +               }
5217 +       }
5218 +       
5219 +       if(port == 0)
5220 +               return 0;
5221 +
5222 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
5223 +               NIPQUAD(newip),
5224 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
5225 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
5226 +               port);
5227 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
5228 +       
5229 +       memset(unicode_buffer, 0, sizeof(char)*75);
5230 +
5231 +       for (i=0; i<strlen(buffer); ++i)
5232 +               *(unicode_buffer+i*2)=*(buffer+i);
5233 +       
5234 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
5235 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
5236 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
5237 +       
5238 +       /* add end of packet to it */
5239 +       for (j=0; j<ct_mms_info->padding; ++j) {
5240 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
5241 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
5242 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
5243 +       }
5244 +
5245 +       /* pad with zeroes at the end ? see explanation of weird math below */
5246 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
5247 +       for (k=0; k<zero_padding; ++k)
5248 +               *(unicode_buffer+i*2+j+k)= (char)0;
5249 +       
5250 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
5251 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
5252 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
5253 +       
5254 +       /* explanation, before I forget what I did:
5255 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
5256 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
5257 +          but note that things may have to be padded with zeroes to align by 8 
5258 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
5259 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
5260 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
5261 +       *mms_messageLength = *mms_chunkLenLV*8;
5262 +       
5263 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
5264 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
5265 +       
5266 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
5267 +                                expect->seq - ntohl(tcph->seq),
5268 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
5269 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
5270 +       DUMP_BYTES(unicode_buffer, 60);
5271 +       
5272 +       return 1;
5273 +}
5274 +
5275 +static unsigned int
5276 +mms_nat_expected(struct sk_buff **pskb,
5277 +                 unsigned int hooknum,
5278 +                 struct ip_conntrack *ct,
5279 +                 struct ip_nat_info *info)
5280 +{
5281 +       struct ip_nat_multi_range mr;
5282 +       u_int32_t newdstip, newsrcip, newip;
5283 +
5284 +       struct ip_conntrack *master = master_ct(ct);
5285 +
5286 +       IP_NF_ASSERT(info);
5287 +       IP_NF_ASSERT(master);
5288 +
5289 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
5290 +
5291 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
5292 +
5293 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5294 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5295 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
5296 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5297 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5298 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
5299 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
5300 +
5301 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
5302 +               newip = newsrcip;
5303 +       else
5304 +               newip = newdstip;
5305 +
5306 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
5307 +
5308 +       mr.rangesize = 1;
5309 +       /* We don't want to manip the per-protocol, just the IPs. */
5310 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
5311 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
5312 +
5313 +       return ip_nat_setup_info(ct, &mr, hooknum);
5314 +}
5315 +
5316 +
5317 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
5318 +                        struct ip_conntrack_expect *exp,
5319 +                        struct ip_nat_info *info,
5320 +                        enum ip_conntrack_info ctinfo,
5321 +                        unsigned int hooknum,
5322 +                        struct sk_buff **pskb)
5323 +{
5324 +       struct iphdr *iph = (*pskb)->nh.iph;
5325 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5326 +       unsigned int datalen;
5327 +       int dir;
5328 +       struct ip_ct_mms_expect *ct_mms_info;
5329 +
5330 +       if (!exp)
5331 +               DEBUGP("ip_nat_mms: no exp!!");
5332 +
5333 +       ct_mms_info = &exp->help.exp_mms_info;
5334 +       
5335 +       /* Only mangle things once: original direction in POST_ROUTING
5336 +          and reply direction on PRE_ROUTING. */
5337 +       dir = CTINFO2DIR(ctinfo);
5338 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5339 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5340 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
5341 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5342 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5343 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5344 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5345 +               return NF_ACCEPT;
5346 +       }
5347 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
5348 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5349 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5350 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5351 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5352 +       
5353 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
5354 +       
5355 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
5356 +              exp->seq + ct_mms_info->len,
5357 +              ntohl(tcph->seq),
5358 +              ntohl(tcph->seq) + datalen);
5359 +       
5360 +       LOCK_BH(&ip_mms_lock);
5361 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
5362 +       if (between(exp->seq + ct_mms_info->len,
5363 +           ntohl(tcph->seq),
5364 +           ntohl(tcph->seq) + datalen)) {
5365 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
5366 +                       UNLOCK_BH(&ip_mms_lock);
5367 +                       return NF_DROP;
5368 +               }
5369 +       } else {
5370 +               /* Half a match?  This means a partial retransmisison.
5371 +                  It's a cracker being funky. */
5372 +               if (net_ratelimit()) {
5373 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
5374 +                              exp->seq, ct_mms_info->len,
5375 +                              ntohl(tcph->seq),
5376 +                              ntohl(tcph->seq) + datalen);
5377 +               }
5378 +               UNLOCK_BH(&ip_mms_lock);
5379 +               return NF_DROP;
5380 +       }
5381 +       UNLOCK_BH(&ip_mms_lock);
5382 +       
5383 +       return NF_ACCEPT;
5384 +}
5385 +
5386 +static struct ip_nat_helper mms[MAX_PORTS];
5387 +static char mms_names[MAX_PORTS][10];
5388 +
5389 +/* Not __exit: called from init() */
5390 +static void fini(void)
5391 +{
5392 +       int i;
5393 +
5394 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
5395 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
5396 +               ip_nat_helper_unregister(&mms[i]);
5397 +       }
5398 +}
5399 +
5400 +static int __init init(void)
5401 +{
5402 +       int i, ret = 0;
5403 +       char *tmpname;
5404 +
5405 +       if (ports[0] == 0)
5406 +               ports[0] = MMS_PORT;
5407 +
5408 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
5409 +
5410 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
5411 +
5412 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
5413 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
5414 +               mms[i].mask.dst.protonum = 0xFFFF;
5415 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
5416 +               mms[i].help = mms_nat_help;
5417 +               mms[i].me = THIS_MODULE;
5418 +               mms[i].flags = 0;
5419 +               mms[i].expect = mms_nat_expected;
5420 +
5421 +               tmpname = &mms_names[i][0];
5422 +               if (ports[i] == MMS_PORT)
5423 +                       sprintf(tmpname, "mms");
5424 +               else
5425 +                       sprintf(tmpname, "mms-%d", i);
5426 +               mms[i].name = tmpname;
5427 +
5428 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
5429 +                               ports[i]);
5430 +               ret = ip_nat_helper_register(&mms[i]);
5431 +
5432 +               if (ret) {
5433 +                       printk("ip_nat_mms: error registering "
5434 +                              "helper for port %d\n", ports[i]);
5435 +                       fini();
5436 +                       return ret;
5437 +               }
5438 +               ports_c++;
5439 +       }
5440 +
5441 +       return ret;
5442 +}
5443 +
5444 +module_init(init);
5445 +module_exit(fini);
5446 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_quake3.c
5447 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_quake3.c      1970-01-01 01:00:00.000000000 +0100
5448 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_quake3.c  2004-04-16 09:18:43.000000000 +0200
5449 @@ -0,0 +1,249 @@
5450 +/* Quake3 extension for UDP NAT alteration.
5451 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5452 + * based on ip_nat_ftp.c and ip_nat_tftp.c
5453 + *
5454 + * ip_nat_quake3.c v0.0.3 2002-08-31
5455 + *
5456 + *      This program is free software; you can redistribute it and/or
5457 + *      modify it under the terms of the GNU General Public License
5458 + *      as published by the Free Software Foundation; either version
5459 + *      2 of the License, or (at your option) any later version.
5460 + *
5461 + *      Module load syntax:
5462 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
5463 + *
5464 + *      please give the ports of all Quake3 master servers You wish to
5465 + *      connect to. If you don't specify ports, the default will be UDP
5466 + *      port 27950.
5467 + *
5468 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5469 + *
5470 + *      Notes: 
5471 + *      - If you're one of those people who would try anything to lower
5472 + *        latency while playing Quake (and who isn't :-) ), you may want to
5473 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
5474 + *        outgoing UDP traffic.
5475 + *        This will make ip_conntrack_quake3 add the necessary expectations,
5476 + *        but there will be no overhead for client->server UDP streams. If
5477 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
5478 + *        hook for every packet in the client->server UDP stream.
5479 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
5480 + *        The IP addresses in the master connection payload (=IP addresses
5481 + *        of Quake servers) have no relation with the master server so
5482 + *        DNAT'ing the master connection to a server should not change the
5483 + *        expected connections.
5484 + *      - Not tested due to lack of equipment:
5485 + *        - multiple Quake3 clients behind one MASQUERADE gateway
5486 + *        - what if Quake3 client is running on router too
5487 + */
5488 +
5489 +#include <linux/module.h>
5490 +#include <linux/netfilter_ipv4.h>
5491 +#include <linux/ip.h>
5492 +#include <linux/udp.h>
5493 +
5494 +#include <linux/netfilter.h>
5495 +#include <linux/netfilter_ipv4/ip_tables.h>
5496 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5497 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5498 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5499 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5500 +
5501 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5502 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
5503 +MODULE_LICENSE("GPL");
5504 +
5505 +#define MAX_PORTS 8
5506 +
5507 +static int ports[MAX_PORTS];
5508 +static int ports_c = 0;
5509 +#ifdef MODULE_PARM
5510 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
5511 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5512 +#endif
5513 +
5514 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5515 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5516 +#if 0 
5517 +#define DEBUGP printk
5518 +#else
5519 +#define DEBUGP(format, args...)
5520 +#endif
5521 +
5522 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5523 +
5524 +static unsigned int 
5525 +quake3_nat_help(struct ip_conntrack *ct,
5526 +                struct ip_conntrack_expect *exp,
5527 +                struct ip_nat_info *info,
5528 +                enum ip_conntrack_info ctinfo,
5529 +                unsigned int hooknum,
5530 +                struct sk_buff **pskb)
5531 +{
5532 +       struct iphdr *iph = (*pskb)->nh.iph;
5533 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5534 +       struct ip_conntrack_tuple repl;
5535 +       int dir = CTINFO2DIR(ctinfo);
5536 +       int i;
5537 +       
5538 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
5539 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5540 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5541 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5542 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
5543 +             );
5544 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5545 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5546 +       
5547 +       /* Only mangle things once: original direction in POST_ROUTING
5548 +          and reply direction on PRE_ROUTING. */
5549 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5550 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5551 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
5552 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5553 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5554 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5555 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
5556 +               return NF_ACCEPT;
5557 +       }
5558 +
5559 +       if (!exp) {
5560 +               DEBUGP("no conntrack expectation to modify\n");
5561 +               return NF_ACCEPT;
5562 +       }
5563 +
5564 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
5565 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5566 +                   i+6 < ntohs(udph->len);
5567 +                   i+=7) {
5568 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
5569 +                              i, ntohs(udph->len),
5570 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
5571 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5572 +                       
5573 +                       memset(&repl, 0, sizeof(repl));
5574 +
5575 +                       repl.dst.protonum = IPPROTO_UDP;
5576 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5577 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
5578 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
5579 +                       
5580 +                       ip_conntrack_change_expect(exp, &repl);
5581 +               }
5582 +       }
5583 +       return NF_ACCEPT;
5584 +}
5585 +
5586 +static unsigned int 
5587 +quake3_nat_expected(struct sk_buff **pskb,
5588 +                    unsigned int hooknum,
5589 +                    struct ip_conntrack *ct, 
5590 +                    struct ip_nat_info *info) 
5591 +{
5592 +       const struct ip_conntrack *master = ct->master->expectant;
5593 +       struct ip_nat_multi_range mr;
5594 +       u_int32_t newsrcip, newdstip, newip;
5595 +#if 0 
5596 +       const struct ip_conntrack_tuple *repl =
5597 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
5598 +       struct iphdr *iph = (*pskb)->nh.iph;
5599 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
5600 +#endif
5601 +
5602 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
5603 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5604 +
5605 +       IP_NF_ASSERT(info);
5606 +       IP_NF_ASSERT(master);
5607 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
5608 +       
5609 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5610 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5611 +       
5612 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
5613 +               newip = newsrcip;
5614 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
5615 +                      "newsrc: %u.%u.%u.%u\n",
5616 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5617 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5618 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
5619 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
5620 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
5621 +                      NIPQUAD(newip));
5622 +               
5623 +       } else {
5624 +               newip = newdstip;
5625 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
5626 +                      "newdst: %u.%u.%u.%u\n",
5627 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5628 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5629 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
5630 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
5631 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
5632 +                      NIPQUAD(newip));
5633 +       }
5634 +       
5635 +       mr.rangesize = 1;
5636 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
5637 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
5638 +
5639 +       return ip_nat_setup_info(ct,&mr,hooknum);
5640 +}
5641 +
5642 +static struct ip_nat_helper quake3[MAX_PORTS];
5643 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
5644 +
5645 +static void fini(void)
5646 +{
5647 +       int i;
5648 +       
5649 +       for (i = 0 ; i < ports_c; i++) {
5650 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
5651 +                      ip_nat_helper_unregister(&quake3[i]);
5652 +       }
5653 +}
5654 +
5655 +static int __init init(void)
5656 +       {
5657 +               int i, ret = 0;
5658 +               char *tmpname;
5659 +
5660 +               if (!ports[0])
5661 +                       ports[0] = QUAKE3_MASTER_PORT;
5662 +               
5663 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5664 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
5665 +
5666 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5667 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5668 +                       quake3[i].mask.dst.protonum = 0xFFFF;
5669 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
5670 +                       quake3[i].help = quake3_nat_help;
5671 +                       quake3[i].flags = 0;
5672 +                       quake3[i].me = THIS_MODULE;
5673 +                       quake3[i].expect = quake3_nat_expected;
5674 +                       
5675 +                       tmpname = &quake3_names[i][0];
5676 +                       if (ports[i] == QUAKE3_MASTER_PORT)
5677 +                               sprintf(tmpname, "quake3");
5678 +                       else
5679 +                               sprintf(tmpname, "quake3-%d", i);
5680 +                       quake3[i].name = tmpname;
5681 +                       
5682 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
5683 +                              ports[i], quake3[i].name);
5684 +                       ret = ip_nat_helper_register(&quake3[i]);
5685 +                       
5686 +                       if (ret) {
5687 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
5688 +                                      ports[i]);
5689 +                               fini();
5690 +                               return ret;
5691 +                       }
5692 +                       ports_c++;
5693 +               }
5694 +               return ret;
5695 +       }
5696 +       
5697 +module_init(init);
5698 +module_exit(fini);
5699 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_standalone.c
5700 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_standalone.c  2004-04-15 03:35:20.000000000 +0200
5701 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_standalone.c      2004-04-16 09:17:11.000000000 +0200
5702 @@ -175,6 +175,45 @@
5703         return do_bindings(ct, ctinfo, info, hooknum, pskb);
5704  }
5705  
5706 +struct nat_route_key
5707 +{
5708 +       u_int32_t addr;
5709 +#ifdef CONFIG_XFRM
5710 +       u_int16_t port;
5711 +#endif
5712 +};
5713 +
5714 +static inline void
5715 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
5716 +{
5717 +       struct iphdr *iph = skb->nh.iph;
5718 +
5719 +       key->addr = which ? iph->daddr : iph->saddr;
5720 +#ifdef CONFIG_XFRM
5721 +       key->port = 0;
5722 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
5723 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
5724 +               key->port = ports[which];
5725 +       }
5726 +#endif
5727 +}
5728 +
5729 +static inline int
5730 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
5731 +{
5732 +       struct iphdr *iph = skb->nh.iph;
5733 +
5734 +       if (key->addr != (which ? iph->daddr : iph->saddr))
5735 +               return 1;
5736 +#ifdef CONFIG_XFRM
5737 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
5738 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
5739 +               if (key->port != ports[which])
5740 +                       return 1;
5741 +       }
5742 +#endif
5743 +}
5744 +
5745  static unsigned int
5746  ip_nat_out(unsigned int hooknum,
5747            struct sk_buff **pskb,
5748 @@ -182,6 +221,9 @@
5749            const struct net_device *out,
5750            int (*okfn)(struct sk_buff *))
5751  {
5752 +       struct nat_route_key key;
5753 +       unsigned int ret;
5754 +
5755         /* root is playing with raw sockets. */
5756         if ((*pskb)->len < sizeof(struct iphdr)
5757             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
5758 @@ -204,7 +246,29 @@
5759                         return NF_STOLEN;
5760         }
5761  
5762 -       return ip_nat_fn(hooknum, pskb, in, out, okfn);
5763 +       nat_route_key_get(*pskb, &key, 0);
5764 +       ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
5765 +
5766 +       if (ret != NF_DROP && ret != NF_STOLEN
5767 +           && nat_route_key_compare(*pskb, &key, 0)) {
5768 +               if (ip_route_me_harder(pskb) != 0)
5769 +                       ret = NF_DROP;
5770 +#ifdef CONFIG_XFRM
5771 +               /*
5772 +                * POST_ROUTING hook is called with fixed outfn, we need
5773 +                * to manually confirm the packet and direct it to the
5774 +                * transformers if a policy matches.
5775 +                */
5776 +               else if ((*pskb)->dst->xfrm != NULL) {
5777 +                       ret = ip_conntrack_confirm(*pskb);
5778 +                       if (ret != NF_DROP) {
5779 +                               dst_output(*pskb);
5780 +                               ret = NF_STOLEN;
5781 +                       }
5782 +               }
5783 +#endif
5784 +       }
5785 +       return ret;
5786  }
5787  
5788  #ifdef CONFIG_IP_NF_NAT_LOCAL
5789 @@ -215,7 +279,7 @@
5790                 const struct net_device *out,
5791                 int (*okfn)(struct sk_buff *))
5792  {
5793 -       u_int32_t saddr, daddr;
5794 +       struct nat_route_key key;
5795         unsigned int ret;
5796  
5797         /* root is playing with raw sockets. */
5798 @@ -223,14 +287,14 @@
5799             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
5800                 return NF_ACCEPT;
5801  
5802 -       saddr = (*pskb)->nh.iph->saddr;
5803 -       daddr = (*pskb)->nh.iph->daddr;
5804 -
5805 +       nat_route_key_get(*pskb, &key, 1);
5806         ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
5807 +
5808         if (ret != NF_DROP && ret != NF_STOLEN
5809 -           && ((*pskb)->nh.iph->saddr != saddr
5810 -               || (*pskb)->nh.iph->daddr != daddr))
5811 -               return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
5812 +           && nat_route_key_compare(*pskb, &key, 1)) {
5813 +               if (ip_route_me_harder(pskb) != 0)
5814 +                       ret = NF_DROP;
5815 +       }
5816         return ret;
5817  }
5818  #endif
5819 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_talk.c
5820 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_nat_talk.c        1970-01-01 01:00:00.000000000 +0100
5821 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_nat_talk.c    2004-04-16 09:18:58.000000000 +0200
5822 @@ -0,0 +1,473 @@
5823 +/* 
5824 + * talk extension for UDP NAT alteration. 
5825 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5826 + *
5827 + *      This program is free software; you can redistribute it and/or
5828 + *      modify it under the terms of the GNU General Public License
5829 + *      as published by the Free Software Foundation; either version
5830 + *      2 of the License, or (at your option) any later version.
5831 + **
5832 + *     Module load syntax:
5833 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
5834 + *
5835 + *             talk=[0|1]      disable|enable old talk support
5836 + *            ntalk=[0|1]      disable|enable ntalk support
5837 + *           ntalk2=[0|1]      disable|enable ntalk2 support
5838 + *
5839 + *     The default is talk=1 ntalk=1 ntalk2=1
5840 + *
5841 + *  
5842 + */
5843 +#include <linux/module.h>
5844 +#include <linux/netfilter_ipv4.h>
5845 +#include <linux/ip.h>
5846 +#include <linux/udp.h>
5847 +#include <linux/kernel.h>
5848 +#include <net/tcp.h>
5849 +#include <net/udp.h>
5850 +
5851 +#include <linux/netfilter_ipv4/ip_nat.h>
5852 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5853 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5854 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5855 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5856 +
5857 +/* Default all talk protocols are supported */
5858 +static int talk   = 1;
5859 +static int ntalk  = 1;
5860 +static int ntalk2 = 1;
5861 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5862 +MODULE_DESCRIPTION("talk network address translation module");
5863 +#ifdef MODULE_PARM
5864 +MODULE_PARM(talk, "i");
5865 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5866 +MODULE_PARM(ntalk, "i");
5867 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5868 +MODULE_PARM(ntalk2, "i");
5869 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5870 +#endif
5871 +
5872 +#if 0
5873 +#define DEBUGP printk
5874 +#define IP_NAT_TALK_DEBUG
5875 +#else
5876 +#define DEBUGP(format, args...)
5877 +#endif
5878 +
5879 +/* FIXME: Time out? --RR */
5880 +
5881 +static int
5882 +mangle_packet(struct sk_buff **pskb,
5883 +             struct ip_conntrack *ct,
5884 +             u_int32_t newip,
5885 +             u_int16_t port,
5886 +             struct talk_addr *addr,
5887 +             struct talk_addr *ctl_addr)
5888 +{
5889 +       struct iphdr *iph = (*pskb)->nh.iph;
5890 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5891 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
5892 +
5893 +       /* Fortunately talk sends a structure with the address and
5894 +          port in it. The size of the packet won't change. */
5895 +
5896 +       if (ctl_addr == NULL) {
5897 +               /* response */
5898 +               if (addr->ta_addr == INADDR_ANY)
5899 +                       return 1;
5900 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
5901 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5902 +                      NIPQUAD(newip), ntohs(port));
5903 +               addr->ta_addr = newip;
5904 +               addr->ta_port = port;
5905 +       } else {
5906 +               /* message */
5907 +               if (addr->ta_addr != INADDR_ANY) {
5908 +                       /* Change address inside packet to match way we're mapping
5909 +                          this connection. */
5910 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
5911 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5912 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
5913 +                              ntohs(addr->ta_port));
5914 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5915 +               }
5916 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
5917 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
5918 +                      NIPQUAD(newip), ntohs(port));
5919 +               ctl_addr->ta_addr = newip;
5920 +               ctl_addr->ta_port = port;
5921 +       }
5922 +
5923 +       /* Fix checksums */
5924 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
5925 +       udph->check = 0;
5926 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5927 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
5928 +               
5929 +       ip_send_check(iph);
5930 +       return 1;
5931 +}
5932 +
5933 +static int talk_help_msg(struct ip_conntrack *ct,
5934 +                        struct sk_buff **pskb,
5935 +                        u_char type,
5936 +                        struct talk_addr *addr,
5937 +                        struct talk_addr *ctl_addr)
5938 +{
5939 +       u_int32_t newip;
5940 +       u_int16_t port;
5941 +       
5942 +       unsigned int verdict = NF_ACCEPT;
5943 +
5944 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
5945 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5946 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
5947 +               type);
5948 +
5949 +       /* Change address inside packet to match way we're mapping
5950 +          this connection. */
5951 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5952 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
5953 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
5954 +               NIPQUAD(newip), ntohs(port));
5955 +
5956 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
5957 +               verdict = NF_DROP;
5958 +
5959 +       return verdict;
5960 +}
5961 +
5962 +static int talk_help_response(struct ip_conntrack *ct,
5963 +                             struct ip_conntrack_expect *exp,
5964 +                             struct sk_buff **pskb,
5965 +                             u_char type,
5966 +                             u_char answer,
5967 +                             struct talk_addr *addr)
5968 +{
5969 +       u_int32_t newip;
5970 +       u_int16_t port;
5971 +       struct ip_conntrack_tuple t;
5972 +       struct ip_ct_talk_expect *ct_talk_info;
5973 +
5974 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
5975 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5976 +               type, answer);
5977 +       
5978 +       LOCK_BH(&ip_talk_lock);
5979 +       ct_talk_info = &exp->help.exp_talk_info;
5980 +
5981 +       if (!(answer == SUCCESS 
5982 +             && (type == LOOK_UP || type == ANNOUNCE)
5983 +             && exp != NULL)) {
5984 +               UNLOCK_BH(&ip_talk_lock);
5985 +               return NF_ACCEPT;
5986 +       }
5987 +               
5988 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
5989 +               ntohs(ct_talk_info->port), 
5990 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
5991 +
5992 +       /* Change address inside packet to match way we're mapping
5993 +          this connection. */
5994 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
5995 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
5996 +       /* We can read expect here without conntrack lock, since it's
5997 +          only set in ip_conntrack_talk , with ip_talk_lock held
5998 +          writable */ 
5999 +       t = exp->tuple;
6000 +       t.dst.ip = newip;
6001 +
6002 +       /* Try to get same port: if not, try to change it. */
6003 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
6004 +               if (type == LOOK_UP)
6005 +                       t.dst.u.tcp.port = htons(port);
6006 +               else
6007 +                       t.dst.u.udp.port = htons(port);
6008 +
6009 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
6010 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
6011 +                       break;
6012 +               }
6013 +       }
6014 +       UNLOCK_BH(&ip_talk_lock);
6015 +
6016 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
6017 +               return NF_DROP;
6018 +       
6019 +       return NF_ACCEPT;
6020 +}
6021 +
6022 +static unsigned int talk_help(struct ip_conntrack *ct,
6023 +                             struct ip_conntrack_expect *exp,
6024 +                             struct ip_nat_info *info,
6025 +                             enum ip_conntrack_info ctinfo,
6026 +                             unsigned int hooknum,
6027 +                             struct sk_buff **pskb,
6028 +                             int talk_port)
6029 +{
6030 +       struct iphdr *iph = (*pskb)->nh.iph;
6031 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
6032 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
6033 +       char *data = (char *)udph + sizeof(struct udphdr);
6034 +       int dir;
6035 +
6036 +       /* Only mangle things once: original direction in POST_ROUTING
6037 +          and reply direction on PRE_ROUTING. */
6038 +       dir = CTINFO2DIR(ctinfo);
6039 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6040 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6041 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
6042 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6043 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6044 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6045 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6046 +               return NF_ACCEPT;
6047 +       }
6048 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
6049 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6050 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6051 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6052 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6053 +              NIPQUAD(iph->saddr), ntohs(udph->source),
6054 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
6055 +              talk_port);
6056 +
6057 +       /* Because conntrack does not drop packets, checking must be repeated here... */
6058 +       if (talk_port == TALK_PORT) {
6059 +               if (dir == IP_CT_DIR_ORIGINAL
6060 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
6061 +                       return talk_help_msg(ct, pskb,
6062 +                                            ((struct talk_msg *)data)->type, 
6063 +                                            &(((struct talk_msg *)data)->addr),
6064 +                                            &(((struct talk_msg *)data)->ctl_addr));
6065 +               else if (dir == IP_CT_DIR_REPLY
6066 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6067 +                       return talk_help_response(ct, exp, pskb,
6068 +                                                 ((struct talk_response *)data)->type, 
6069 +                                                 ((struct talk_response *)data)->answer,
6070 +                                                 &(((struct talk_response *)data)->addr));
6071 +               else {  
6072 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
6073 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
6074 +                              (unsigned)udplen - sizeof(struct udphdr), 
6075 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
6076 +                       return NF_DROP;
6077 +               }
6078 +       } else {
6079 +               if (dir == IP_CT_DIR_ORIGINAL) {
6080 +                       if (ntalk
6081 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
6082 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
6083 +                               return talk_help_msg(ct, pskb,
6084 +                                                    ((struct ntalk_msg *)data)->type, 
6085 +                                                    &(((struct ntalk_msg *)data)->addr),
6086 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
6087 +                       else if (ntalk2
6088 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
6089 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
6090 +                                && udplen == sizeof(struct udphdr) 
6091 +                                             + sizeof(struct ntalk2_msg) 
6092 +                                             + ((struct ntalk2_msg *)data)->extended)
6093 +                               return talk_help_msg(ct, pskb,
6094 +                                                    ((struct ntalk2_msg *)data)->type, 
6095 +                                                    &(((struct ntalk2_msg *)data)->addr),
6096 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
6097 +                       else {
6098 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
6099 +                                      (unsigned)udplen - sizeof(struct udphdr), 
6100 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
6101 +                               return NF_DROP;
6102 +                       }
6103 +               } else {
6104 +                       if (ntalk
6105 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6106 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6107 +                               return talk_help_response(ct, exp, pskb,
6108 +                                                         ((struct ntalk_response *)data)->type, 
6109 +                                                         ((struct ntalk_response *)data)->answer,
6110 +                                                         &(((struct ntalk_response *)data)->addr));
6111 +                       else if (ntalk2
6112 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6113 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6114 +                               return talk_help_response(ct, exp, pskb,
6115 +                                                         ((struct ntalk2_response *)data)->type, 
6116 +                                                         ((struct ntalk2_response *)data)->answer,
6117 +                                                         &(((struct ntalk2_response *)data)->addr));
6118 +                       else {
6119 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
6120 +                                      (unsigned)udplen - sizeof(struct udphdr), 
6121 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6122 +                               return NF_DROP;
6123 +                       }
6124 +               }
6125 +       }
6126 +}
6127 +
6128 +static unsigned int help(struct ip_conntrack *ct,
6129 +                        struct ip_conntrack_expect *exp,
6130 +                        struct ip_nat_info *info,
6131 +                        enum ip_conntrack_info ctinfo,
6132 +                        unsigned int hooknum,
6133 +                        struct sk_buff **pskb)
6134 +{
6135 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
6136 +}
6137 +
6138 +static unsigned int nhelp(struct ip_conntrack *ct,
6139 +                         struct ip_conntrack_expect *exp,
6140 +                         struct ip_nat_info *info,
6141 +                         enum ip_conntrack_info ctinfo,
6142 +                         unsigned int hooknum,
6143 +                         struct sk_buff **pskb)
6144 +{
6145 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
6146 +}
6147 +
6148 +static unsigned int
6149 +talk_nat_expected(struct sk_buff **pskb,
6150 +                 unsigned int hooknum,
6151 +                 struct ip_conntrack *ct,
6152 +                 struct ip_nat_info *info);
6153 +
6154 +static struct ip_nat_helper talk_helpers[2] = 
6155 +       { { { NULL, NULL },
6156 +            "talk",                                    /* name */
6157 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
6158 +            THIS_MODULE,                               /* module */
6159 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
6160 +              { 0, { 0 }, IPPROTO_UDP } },
6161 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
6162 +              { 0, { 0 }, 0xFFFF } },
6163 +            help,                                      /* helper */
6164 +            talk_nat_expected },                       /* expectfn */
6165 +         { { NULL, NULL },
6166 +            "ntalk",                                   /* name */
6167 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
6168 +            THIS_MODULE,                                       /* module */
6169 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
6170 +              { 0, { 0 }, IPPROTO_UDP } },
6171 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
6172 +              { 0, { 0 }, 0xFFFF } },
6173 +            nhelp,                                     /* helper */
6174 +            talk_nat_expected }                                /* expectfn */
6175 +       };
6176 +          
6177 +static unsigned int
6178 +talk_nat_expected(struct sk_buff **pskb,
6179 +                 unsigned int hooknum,
6180 +                 struct ip_conntrack *ct,
6181 +                 struct ip_nat_info *info)
6182 +{
6183 +       struct ip_nat_multi_range mr;
6184 +       u_int32_t newdstip, newsrcip, newip;
6185 +       u_int16_t port;
6186 +       unsigned int ret;
6187 +       
6188 +       struct ip_conntrack *master = master_ct(ct);
6189 +
6190 +       IP_NF_ASSERT(info);
6191 +       IP_NF_ASSERT(master);
6192 +
6193 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6194 +
6195 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
6196 +
6197 +       LOCK_BH(&ip_talk_lock);
6198 +       port = ct->master->help.exp_talk_info.port;
6199 +       UNLOCK_BH(&ip_talk_lock);
6200 +
6201 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
6202 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6203 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6204 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6205 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6206 +              ct, master);
6207 +
6208 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
6209 +               /* Callee client -> caller server */
6210 +#ifdef IP_NAT_TALK_DEBUG
6211 +               struct iphdr *iph = (*pskb)->nh.iph;
6212 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
6213 +
6214 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6215 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
6216 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
6217 +#endif
6218 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6219 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6220 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
6221 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6222 +       } else {
6223 +               /* Callee client -> caller client */
6224 +#ifdef IP_NAT_TALK_DEBUG
6225 +               struct iphdr *iph = (*pskb)->nh.iph;
6226 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
6227 +
6228 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6229 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
6230 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
6231 +#endif
6232 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6233 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6234 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
6235 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6236 +       }
6237 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6238 +               newip = newsrcip;
6239 +       else
6240 +               newip = newdstip;
6241 +
6242 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
6243 +
6244 +       mr.rangesize = 1;
6245 +       /* We don't want to manip the per-protocol, just the IPs... */
6246 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6247 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6248 +       
6249 +       /* ... unless we're doing a MANIP_DST, in which case, make
6250 +          sure we map to the correct port */
6251 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6252 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6253 +               mr.range[0].min = mr.range[0].max
6254 +                       = ((union ip_conntrack_manip_proto)
6255 +                               { .udp = { port } });
6256 +       }
6257 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
6258 +
6259 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
6260 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
6261 +               /* NAT expectfn called with ip_nat_lock write-locked */
6262 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
6263 +       }
6264 +       return ret;
6265 +}
6266 +
6267 +static int __init init(void)
6268 +{
6269 +       int ret = 0;
6270 +
6271 +       if (talk > 0) {
6272 +               ret = ip_nat_helper_register(&talk_helpers[0]);
6273 +
6274 +               if (ret != 0)
6275 +                       return ret;
6276 +       }
6277 +       if (ntalk > 0 || ntalk2 > 0) {
6278 +               ret = ip_nat_helper_register(&talk_helpers[1]);
6279 +
6280 +               if (ret != 0 && talk > 0)
6281 +                       ip_nat_helper_unregister(&talk_helpers[0]);
6282 +       }
6283 +       return ret;
6284 +}
6285 +
6286 +static void __exit fini(void)
6287 +{
6288 +       if (talk > 0)
6289 +               ip_nat_helper_unregister(&talk_helpers[0]);
6290 +       if (ntalk > 0 || ntalk2 > 0)
6291 +               ip_nat_helper_unregister(&talk_helpers[1]);
6292 +}
6293 +
6294 +module_init(init);
6295 +module_exit(fini);
6296 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_tables.c
6297 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_tables.c  2004-04-16 08:59:08.000000000 +0200
6298 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_tables.c      2004-04-16 09:17:31.000000000 +0200
6299 @@ -8,6 +8,10 @@
6300   * it under the terms of the GNU General Public License version 2 as
6301   * published by the Free Software Foundation.
6302   *
6303 + *  6 Mar 2002 Robert Olsson <robban@robtex.com>
6304 + * 17 Apr 2003 Chris  Wilson <chris@netservers.co.uk>
6305 + *     - mark_source_chains speedup for complex chains
6306 + *
6307   * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
6308   *     - increase module usage count as soon as we have rules inside
6309   *       a table
6310 @@ -498,6 +502,9 @@
6311  {
6312         unsigned int hook;
6313  
6314 +       /* keep track of where we have been: */
6315 +       unsigned char *been = vmalloc(newinfo->size);
6316 +
6317         /* No recursion; use packet counter to save back ptrs (reset
6318            to 0 as we leave), and comefrom to save source hook bitmask */
6319         for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
6320 @@ -510,6 +517,7 @@
6321  
6322                 /* Set initial back pointer. */
6323                 e->counters.pcnt = pos;
6324 +               memset(been, 0, newinfo->size);
6325  
6326                 for (;;) {
6327                         struct ipt_standard_target *t
6328 @@ -518,6 +526,7 @@
6329                         if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
6330                                 printk("iptables: loop hook %u pos %u %08X.\n",
6331                                        hook, pos, e->comefrom);
6332 +                               vfree(been);
6333                                 return 0;
6334                         }
6335                         e->comefrom
6336 @@ -565,10 +574,14 @@
6337                         } else {
6338                                 int newpos = t->verdict;
6339  
6340 -                               if (strcmp(t->target.u.user.name,
6341 +                               if ( (pos < 0 || pos >= newinfo->size
6342 +                                     || !been[pos]) 
6343 +                                   && strcmp(t->target.u.user.name,
6344                                            IPT_STANDARD_TARGET) == 0
6345                                     && newpos >= 0) {
6346                                         /* This a jump; chase it. */
6347 +                                       if (pos >= 0 && pos < newinfo->size)
6348 +                                               been[pos]++;
6349                                         duprintf("Jump rule %u -> %u\n",
6350                                                  pos, newpos);
6351                                 } else {
6352 @@ -584,6 +597,7 @@
6353                 next:
6354                 duprintf("Finished chain %u\n", hook);
6355         }
6356 +       vfree(been);
6357         return 1;
6358  }
6359  
6360 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_CONNMARK.c
6361 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c       1970-01-01 01:00:00.000000000 +0100
6362 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_CONNMARK.c   2004-04-16 09:15:41.000000000 +0200
6363 @@ -0,0 +1,118 @@
6364 +/* This kernel module is used to modify the connection mark values, or
6365 + * to optionally restore the skb nfmark from the connection mark
6366 + *
6367 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
6368 + * by Henrik Nordstrom <hno@marasystems.com>
6369 + *
6370 + * This program is free software; you can redistribute it and/or modify
6371 + * it under the terms of the GNU General Public License as published by
6372 + * the Free Software Foundation; either version 2 of the License, or
6373 + * (at your option) any later version.
6374 + *
6375 + * This program is distributed in the hope that it will be useful,
6376 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6377 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6378 + * GNU General Public License for more details.
6379 + *
6380 + * You should have received a copy of the GNU General Public License
6381 + * along with this program; if not, write to the Free Software
6382 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
6383 + */
6384 +#include <linux/module.h>
6385 +#include <linux/skbuff.h>
6386 +#include <linux/ip.h>
6387 +#include <net/checksum.h>
6388 +
6389 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
6390 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
6391 +MODULE_LICENSE("GPL");
6392 +
6393 +#include <linux/netfilter_ipv4/ip_tables.h>
6394 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
6395 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6396 +
6397 +static unsigned int
6398 +target(struct sk_buff **pskb,
6399 +       const struct net_device *in,
6400 +       const struct net_device *out,
6401 +       unsigned int hooknum,
6402 +       const void *targinfo,
6403 +       void *userinfo)
6404 +{
6405 +       const struct ipt_connmark_target_info *markinfo = targinfo;
6406 +       unsigned long diff;
6407 +       unsigned long nfmark;
6408 +       unsigned long newmark;
6409 +
6410 +       enum ip_conntrack_info ctinfo;
6411 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
6412 +       if (ct) {
6413 +           switch(markinfo->mode) {
6414 +           case IPT_CONNMARK_SET:
6415 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
6416 +               if (newmark != ct->mark)
6417 +                   ct->mark = newmark;
6418 +               break;
6419 +           case IPT_CONNMARK_SAVE:
6420 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
6421 +               if (ct->mark != newmark)
6422 +                   ct->mark = newmark;
6423 +               break;
6424 +           case IPT_CONNMARK_RESTORE:
6425 +               nfmark = (*pskb)->nfmark;
6426 +               diff = (ct->mark ^ nfmark & markinfo->mask);
6427 +               if (diff != 0) {
6428 +                   (*pskb)->nfmark = nfmark ^ diff;
6429 +                   (*pskb)->nfcache |= NFC_ALTERED;
6430 +               }
6431 +               break;
6432 +           }
6433 +       }
6434 +
6435 +       return IPT_CONTINUE;
6436 +}
6437 +
6438 +static int
6439 +checkentry(const char *tablename,
6440 +          const struct ipt_entry *e,
6441 +          void *targinfo,
6442 +          unsigned int targinfosize,
6443 +          unsigned int hook_mask)
6444 +{
6445 +       struct ipt_connmark_target_info *matchinfo = targinfo;
6446 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
6447 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
6448 +                      targinfosize,
6449 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
6450 +               return 0;
6451 +       }
6452 +
6453 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
6454 +           if (strcmp(tablename, "mangle") != 0) {
6455 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6456 +                   return 0;
6457 +           }
6458 +       }
6459 +
6460 +       return 1;
6461 +}
6462 +
6463 +static struct ipt_target ipt_connmark_reg = {
6464 +       .name = "CONNMARK",
6465 +       .target = &target,
6466 +       .checkentry = &checkentry,
6467 +       .me = THIS_MODULE
6468 +};
6469 +
6470 +static int __init init(void)
6471 +{
6472 +       return ipt_register_target(&ipt_connmark_reg);
6473 +}
6474 +
6475 +static void __exit fini(void)
6476 +{
6477 +       ipt_unregister_target(&ipt_connmark_reg);
6478 +}
6479 +
6480 +module_init(init);
6481 +module_exit(fini);
6482 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_IPMARK.c
6483 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
6484 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_IPMARK.c     2004-04-16 09:15:43.000000000 +0200
6485 @@ -0,0 +1,81 @@
6486 +/* This is a module which is used for setting the NFMARK field of an skb. */
6487 +#include <linux/module.h>
6488 +#include <linux/skbuff.h>
6489 +#include <linux/ip.h>
6490 +#include <net/checksum.h>
6491 +
6492 +#include <linux/netfilter_ipv4/ip_tables.h>
6493 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
6494 +
6495 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
6496 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
6497 +MODULE_LICENSE("GPL");
6498 +
6499 +static unsigned int
6500 +target(struct sk_buff **pskb,
6501 +       const struct net_device *in,
6502 +       const struct net_device *out,
6503 +       unsigned int hooknum,
6504 +       const void *targinfo,
6505 +       void *userinfo)
6506 +{
6507 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
6508 +       struct iphdr *iph = (*pskb)->nh.iph;
6509 +       unsigned long mark;
6510 +
6511 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
6512 +               mark = (unsigned long) ntohl(iph->saddr);
6513 +       else
6514 +               mark = (unsigned long) ntohl(iph->daddr);
6515 +
6516 +       mark &= ipmarkinfo->andmask;
6517 +       mark |= ipmarkinfo->ormask;
6518 +       
6519 +       if ((*pskb)->nfmark != mark) {
6520 +               (*pskb)->nfmark = mark;
6521 +               (*pskb)->nfcache |= NFC_ALTERED;
6522 +       }
6523 +       return IPT_CONTINUE;
6524 +}
6525 +
6526 +static int
6527 +checkentry(const char *tablename,
6528 +          const struct ipt_entry *e,
6529 +           void *targinfo,
6530 +           unsigned int targinfosize,
6531 +           unsigned int hook_mask)
6532 +{
6533 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
6534 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
6535 +                      targinfosize,
6536 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
6537 +               return 0;
6538 +       }
6539 +
6540 +       if (strcmp(tablename, "mangle") != 0) {
6541 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6542 +               return 0;
6543 +       }
6544 +
6545 +       return 1;
6546 +}
6547 +
6548 +static struct ipt_target ipt_ipmark_reg = { 
6549 +       .name = "IPMARK",
6550 +       .target = target,
6551 +       .checkentry = checkentry,
6552 +       .me = THIS_MODULE
6553 +};
6554 +
6555 +static int __init init(void)
6556 +{
6557 +       return ipt_register_target(&ipt_ipmark_reg);
6558 +}
6559 +
6560 +static void __exit fini(void)
6561 +{
6562 +       ipt_unregister_target(&ipt_ipmark_reg);
6563 +}
6564 +
6565 +module_init(init);
6566 +module_exit(fini);
6567 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_ROUTE.c
6568 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_ROUTE.c  1970-01-01 01:00:00.000000000 +0100
6569 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_ROUTE.c      2004-04-16 09:15:44.000000000 +0200
6570 @@ -0,0 +1,369 @@
6571 +/*
6572 + * This implements the ROUTE target, which enables you to setup unusual
6573 + * routes not supported by the standard kernel routing table.
6574 + *
6575 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
6576 + *
6577 + * v 1.8 2003/07/25
6578 + *
6579 + * This software is distributed under GNU GPL v2, 1991
6580 + */
6581 +
6582 +#include <linux/module.h>
6583 +#include <linux/skbuff.h>
6584 +#include <linux/ip.h>
6585 +#include <linux/netfilter_ipv4/ip_tables.h>
6586 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
6587 +#include <linux/netdevice.h>
6588 +#include <linux/route.h>
6589 +#include <net/ip.h>
6590 +#include <net/route.h>
6591 +#include <net/icmp.h>
6592 +
6593 +#if 0
6594 +#define DEBUGP printk
6595 +#else
6596 +#define DEBUGP(format, args...)
6597 +#endif
6598 +
6599 +MODULE_LICENSE("GPL");
6600 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
6601 +
6602 +/* Try to route the packet according to the routing keys specified in
6603 + * route_info. Keys are :
6604 + *  - ifindex : 
6605 + *      0 if no oif preferred, 
6606 + *      otherwise set to the index of the desired oif
6607 + *  - route_info->gw :
6608 + *      0 if no gateway specified,
6609 + *      otherwise set to the next host to which the pkt must be routed
6610 + * If success, skb->dev is the output device to which the packet must 
6611 + * be sent and skb->dst is not NULL
6612 + *
6613 + * RETURN: -1 if an error occured
6614 + *          1 if the packet was succesfully routed to the 
6615 + *            destination desired
6616 + *          0 if the kernel routing table could not route the packet
6617 + *            according to the keys specified
6618 + */
6619 +static int route(struct sk_buff *skb,
6620 +                unsigned int ifindex,
6621 +                const struct ipt_route_target_info *route_info)
6622 +{
6623 +       int err;
6624 +       struct rtable *rt;
6625 +       struct iphdr *iph = skb->nh.iph;
6626 +       struct rt_key key = { 
6627 +               dst:iph->daddr,
6628 +               src:0,
6629 +               oif:ifindex, 
6630 +               tos:RT_TOS(iph->tos) 
6631 +       };
6632 +       
6633 +       /* The destination address may be overloaded by the target */
6634 +       if (route_info->gw)
6635 +               key.dst = route_info->gw;
6636 +       
6637 +       /* Trying to route the packet using the standard routing table. */
6638 +       if ((err = ip_route_output_key(&rt, &key))) {
6639 +               if (net_ratelimit()) 
6640 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
6641 +               return -1;
6642 +       }
6643 +       
6644 +       /* Drop old route. */
6645 +       dst_release(skb->dst);
6646 +       skb->dst = NULL;
6647 +
6648 +       /* Success if no oif specified or if the oif correspond to the 
6649 +        * one desired */
6650 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
6651 +               skb->dst = &rt->u.dst;
6652 +               skb->dev = skb->dst->dev;
6653 +               return 1;
6654 +       }
6655 +       
6656 +       /* The interface selected by the routing table is not the one
6657 +        * specified by the user. This may happen because the dst address
6658 +        * is one of our own addresses.
6659 +        */
6660 +       if (net_ratelimit()) 
6661 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
6662 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
6663 +       
6664 +       return 0;
6665 +}
6666 +
6667 +
6668 +/* Stolen from ip_finish_output2
6669 + * PRE : skb->dev is set to the device we are leaving by
6670 + *       skb->dst is not NULL
6671 + * POST: the packet is sent with the link layer header pushed
6672 + *       the packet is destroyed
6673 + */
6674 +static void ip_direct_send(struct sk_buff *skb)
6675 +{
6676 +       struct dst_entry *dst = skb->dst;
6677 +       struct hh_cache *hh = dst->hh;
6678 +
6679 +       if (hh) {
6680 +               read_lock_bh(&hh->hh_lock);
6681 +               memcpy(skb->data - 16, hh->hh_data, 16);
6682 +               read_unlock_bh(&hh->hh_lock);
6683 +               skb_push(skb, hh->hh_len);
6684 +               hh->hh_output(skb);
6685 +       } else if (dst->neighbour)
6686 +               dst->neighbour->output(skb);
6687 +       else {
6688 +               if (net_ratelimit())
6689 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
6690 +               kfree_skb(skb);
6691 +       }
6692 +}
6693 +
6694 +
6695 +/* PRE : skb->dev is set to the device we are leaving by
6696 + * POST: - the packet is directly sent to the skb->dev device, without 
6697 + *         pushing the link layer header.
6698 + *       - the packet is destroyed
6699 + */
6700 +static inline int dev_direct_send(struct sk_buff *skb)
6701 +{
6702 +       return dev_queue_xmit(skb);
6703 +}
6704 +
6705 +
6706 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
6707 +                             struct sk_buff *skb) 
6708 +{
6709 +       unsigned int ifindex = 0;
6710 +       struct net_device *dev_out = NULL;
6711 +
6712 +       /* The user set the interface name to use.
6713 +        * Getting the current interface index.
6714 +        */
6715 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
6716 +               ifindex = dev_out->ifindex;
6717 +       } else {
6718 +               /* Unknown interface name : packet dropped */
6719 +               if (net_ratelimit()) 
6720 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
6721 +               return NF_DROP;
6722 +       }
6723 +
6724 +       /* Trying the standard way of routing packets */
6725 +       switch (route(skb, ifindex, route_info)) {
6726 +       case 1:
6727 +               dev_put(dev_out);
6728 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
6729 +                       return IPT_CONTINUE;
6730 +
6731 +               ip_direct_send(skb);
6732 +               return NF_STOLEN;
6733 +
6734 +       case 0:
6735 +               /* Failed to send to oif. Trying the hard way */
6736 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
6737 +                       return NF_DROP;
6738 +
6739 +               if (net_ratelimit()) 
6740 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
6741 +                              ifindex);
6742 +
6743 +               /* We have to force the use of an interface.
6744 +                * This interface must be a tunnel interface since
6745 +                * otherwise we can't guess the hw address for
6746 +                * the packet. For a tunnel interface, no hw address
6747 +                * is needed.
6748 +                */
6749 +               if ((dev_out->type != ARPHRD_TUNNEL)
6750 +                   && (dev_out->type != ARPHRD_IPGRE)) {
6751 +                       if (net_ratelimit()) 
6752 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
6753 +                       dev_put(dev_out);
6754 +                       return NF_DROP;
6755 +               }
6756 +       
6757 +               /* Send the packet. This will also free skb
6758 +                * Do not go through the POST_ROUTING hook because 
6759 +                * skb->dst is not set and because it will probably
6760 +                * get confused by the destination IP address.
6761 +                */
6762 +               skb->dev = dev_out;
6763 +               dev_direct_send(skb);
6764 +               dev_put(dev_out);
6765 +               return NF_STOLEN;
6766 +               
6767 +       default:
6768 +               /* Unexpected error */
6769 +               dev_put(dev_out);
6770 +               return NF_DROP;
6771 +       }
6772 +}
6773 +
6774 +
6775 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
6776 +                             struct sk_buff *skb) 
6777 +{
6778 +       struct net_device *dev_out = NULL;
6779 +       unsigned int ifindex = 0;
6780 +
6781 +       /* Getting the current interface index. */
6782 +       if ((dev_out = dev_get_by_name(route_info->iif)))
6783 +               ifindex = dev_out->ifindex;
6784 +       else {
6785 +               /* Unknown interface name : packet dropped */
6786 +               if (net_ratelimit()) 
6787 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
6788 +               return NF_DROP;
6789 +       }
6790 +
6791 +       skb->dev = dev_out;
6792 +       dst_release(skb->dst);
6793 +       skb->dst = NULL;
6794 +               
6795 +       netif_rx(skb);
6796 +
6797 +       return NF_STOLEN;
6798 +}
6799 +
6800 +
6801 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
6802 +                            struct sk_buff *skb) 
6803 +{
6804 +       if (route(skb, 0, route_info)!=1)
6805 +               return NF_DROP;
6806 +
6807 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
6808 +               return IPT_CONTINUE;
6809 +
6810 +       ip_direct_send(skb);
6811 +       return NF_STOLEN;
6812 +}
6813 +
6814 +
6815 +static unsigned int ipt_route_target(struct sk_buff **pskb,
6816 +                                    const struct net_device *in,
6817 +                                    const struct net_device *out,
6818 +                                    unsigned int hooknum,
6819 +                                    const void *targinfo,
6820 +                                    void *userinfo)
6821 +{
6822 +       const struct ipt_route_target_info *route_info = targinfo;
6823 +       struct sk_buff *skb = *pskb;
6824 +
6825 +       /* If we are at PREROUTING or INPUT hook
6826 +        * the TTL isn't decreased by the IP stack
6827 +        */
6828 +       if (hooknum == NF_IP_PRE_ROUTING ||
6829 +           hooknum == NF_IP_LOCAL_IN) {
6830 +
6831 +               struct iphdr *iph = skb->nh.iph;
6832 +
6833 +               if (iph->ttl <= 1) {
6834 +                       struct rtable *rt;
6835 +
6836 +                       if (ip_route_output(&rt, iph->saddr, iph->daddr,
6837 +                                           RT_TOS(iph->tos) | RTO_CONN,
6838 +                                           0)) {
6839 +                               return NF_DROP;
6840 +                       }
6841 +
6842 +                       if (skb->dev == rt->u.dst.dev) {
6843 +                               /* Drop old route. */
6844 +                               dst_release(skb->dst);
6845 +                               skb->dst = &rt->u.dst;
6846 +
6847 +                               /* this will traverse normal stack, and 
6848 +                                * thus call conntrack on the icmp packet */
6849 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
6850 +                                         ICMP_EXC_TTL, 0);
6851 +                       }
6852 +
6853 +                       return NF_DROP;
6854 +               }
6855 +
6856 +               ip_decrease_ttl(iph);
6857 +       }
6858 +
6859 +       /* Tell conntrack to forget this packet since it may get confused 
6860 +        * when a packet is leaving with dst address == our address.
6861 +        * Good idea ? Dunno. Need advice.
6862 +        */
6863 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
6864 +               nf_conntrack_put(skb->nfct);
6865 +               skb->nfct = NULL;
6866 +               skb->nfcache = 0;
6867 +#ifdef CONFIG_NETFILTER_DEBUG
6868 +               skb->nf_debug = 0;
6869 +#endif
6870 +       }
6871 +
6872 +       if (route_info->oif[0]) 
6873 +               return route_oif(route_info, *pskb);
6874 +       
6875 +       if (route_info->iif[0]) 
6876 +               return route_iif(route_info, *pskb);
6877 +
6878 +       if (route_info->gw) 
6879 +               return route_gw(route_info, *pskb);
6880 +
6881 +       if (net_ratelimit()) 
6882 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
6883 +
6884 +       return IPT_CONTINUE;
6885 +}
6886 +
6887 +
6888 +static int ipt_route_checkentry(const char *tablename,
6889 +                               const struct ipt_entry *e,
6890 +                               void *targinfo,
6891 +                               unsigned int targinfosize,
6892 +                               unsigned int hook_mask)
6893 +{
6894 +       if (strcmp(tablename, "mangle") != 0) {
6895 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
6896 +                      tablename);
6897 +               return 0;
6898 +       }
6899 +
6900 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
6901 +                           | (1 << NF_IP_LOCAL_IN)
6902 +                           | (1 << NF_IP_FORWARD)
6903 +                           | (1 << NF_IP_LOCAL_OUT)
6904 +                           | (1 << NF_IP_POST_ROUTING))) {
6905 +               printk("ipt_ROUTE: bad hook\n");
6906 +               return 0;
6907 +       }
6908 +
6909 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
6910 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
6911 +                      targinfosize,
6912 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
6913 +               return 0;
6914 +       }
6915 +
6916 +       return 1;
6917 +}
6918 +
6919 +
6920 +static struct ipt_target ipt_route_reg = { 
6921 +       .name = "ROUTE",
6922 +       .target = ipt_route_target,
6923 +       .checkentry = ipt_route_checkentry,
6924 +       .me = THIS_MODULE,
6925 +};
6926 +
6927 +static int __init init(void)
6928 +{
6929 +       return ipt_register_target(&ipt_route_reg);
6930 +}
6931 +
6932 +
6933 +static void __exit fini(void)
6934 +{
6935 +       ipt_unregister_target(&ipt_route_reg);
6936 +}
6937 +
6938 +module_init(init);
6939 +module_exit(fini);
6940 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TARPIT.c
6941 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
6942 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TARPIT.c     2004-04-16 09:19:08.000000000 +0200
6943 @@ -0,0 +1,290 @@
6944 +/* 
6945 + * Kernel module to capture and hold incoming TCP connections using 
6946 + * no local per-connection resources.
6947 + * 
6948 + * Based on ipt_REJECT.c and offering functionality similar to 
6949 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
6950 + * 
6951 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
6952 + * 
6953 + * This program is free software; you can redistribute it and/or modify
6954 + * it under the terms of the GNU General Public License as published by
6955 + * the Free Software Foundation; either version 2 of the License, or
6956 + * (at your option) any later version.
6957 + *
6958 + * This program is distributed in the hope that it will be useful,
6959 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6960 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6961 + * GNU General Public License for more details.
6962 + *
6963 + * You should have received a copy of the GNU General Public License
6964 + * along with this program; if not, write to the Free Software
6965 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
6966 + * 
6967 + * Goal:
6968 + * - Allow incoming TCP connections to be established.
6969 + * - Passing data should result in the connection being switched to the 
6970 + *   persist state (0 byte window), in which the remote side stops sending 
6971 + *   data and asks to continue every 60 seconds.
6972 + * - Attempts to shut down the connection should be ignored completely, so 
6973 + *   the remote side ends up having to time it out.
6974 + *
6975 + * This means:
6976 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
6977 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
6978 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
6979 + */
6980 +
6981 +#include <linux/config.h>
6982 +#include <linux/module.h>
6983 +#include <linux/skbuff.h>
6984 +#include <linux/ip.h>
6985 +#include <net/ip.h>
6986 +#include <net/tcp.h>
6987 +#include <net/icmp.h>
6988 +struct in_device;
6989 +#include <net/route.h>
6990 +#include <linux/random.h>
6991 +#include <linux/netfilter_ipv4/ip_tables.h>
6992 +
6993 +#if 0
6994 +#define DEBUGP printk
6995 +#else
6996 +#define DEBUGP(format, args...)
6997 +#endif
6998 +
6999 +
7000 +/* Stolen from ip_finish_output2 */
7001 +static int ip_direct_send(struct sk_buff *skb)
7002 +{
7003 +       struct dst_entry *dst = skb->dst;
7004 +       struct hh_cache *hh = dst->hh;
7005 +
7006 +       if (hh) {    
7007 +               read_lock_bh(&hh->hh_lock);
7008 +               memcpy(skb->data - 16, hh->hh_data, 16);
7009 +                read_unlock_bh(&hh->hh_lock);
7010 +                skb_push(skb, hh->hh_len);
7011 +                return hh->hh_output(skb);
7012 +        } else if (dst->neighbour)
7013 +                return dst->neighbour->output(skb);
7014 +
7015 +       if (net_ratelimit())
7016 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
7017 +        kfree_skb(skb);
7018 +        return -EINVAL;
7019 +}
7020 +
7021 +
7022 +/* Send reply */
7023 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
7024 +{
7025 +       struct sk_buff *nskb;
7026 +       struct rtable *nrt;
7027 +       struct tcphdr *otcph, *ntcph;
7028 +       unsigned int otcplen;
7029 +       u_int16_t tmp;
7030 +       struct flowi fl = {};
7031 +
7032 +       /* A truncated TCP header isn't going to be useful */
7033 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
7034 +               return;
7035 +
7036 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
7037 +                                  + oskb->nh.iph->ihl);
7038 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
7039 +
7040 +       /* No replies for RST or FIN */
7041 +       if (otcph->rst || otcph->fin)
7042 +               return;
7043 +
7044 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
7045 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
7046 +               return;
7047 +
7048 +       /* Check checksum. */
7049 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
7050 +                        oskb->nh.iph->daddr,
7051 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
7052 +               return;
7053 +
7054 +       /* Copy skb (even if skb is about to be dropped, we can't just
7055 +           clone it because there may be other things, such as tcpdump,
7056 +           interested in it) */
7057 +       nskb = skb_copy(oskb, GFP_ATOMIC);
7058 +       if (!nskb)
7059 +               return;
7060 +
7061 +       /* This packet will not be the same as the other: clear nf fields */
7062 +       nf_conntrack_put(nskb->nfct);
7063 +       nskb->nfct = NULL;
7064 +       nskb->nfcache = 0;
7065 +#ifdef CONFIG_NETFILTER_DEBUG
7066 +       nskb->nf_debug = 0;
7067 +#endif
7068 +
7069 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
7070 +
7071 +       /* Truncate to length (no data) */
7072 +       ntcph->doff = sizeof(struct tcphdr)/4;
7073 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
7074 +       nskb->nh.iph->tot_len = htons(nskb->len);
7075 +
7076 +       /* Swap source and dest */
7077 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
7078 +       tmp = ntcph->source;
7079 +       ntcph->source = ntcph->dest;
7080 +       ntcph->dest = tmp;
7081 +
7082 +       /* Use supplied sequence number or make a new one */
7083 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
7084 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
7085 +                                                       nskb->nh.iph->daddr, 
7086 +                                                       ntcph->source, 
7087 +                                                       ntcph->dest));
7088 +
7089 +       /* Our SYN-ACKs must have a >0 window */
7090 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
7091 +
7092 +       ntcph->urg_ptr = 0;
7093 +
7094 +       /* Reset flags */
7095 +       ((u_int8_t *)ntcph)[13] = 0;
7096 +
7097 +       if (otcph->syn && otcph->ack) {
7098 +               ntcph->rst = 1;
7099 +               ntcph->ack_seq = 0;
7100 +       } else {
7101 +               ntcph->syn = otcph->syn;
7102 +               ntcph->ack = 1;
7103 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
7104 +       }
7105 +
7106 +       /* Adjust TCP checksum */
7107 +       ntcph->check = 0;
7108 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
7109 +                                  nskb->nh.iph->saddr,
7110 +                                  nskb->nh.iph->daddr,
7111 +                                  csum_partial((char *)ntcph,
7112 +                                               sizeof(struct tcphdr), 0));
7113 +
7114 +       /* Adjust IP TTL */
7115 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
7116 +
7117 +       /* Set DF, id = 0 */
7118 +       nskb->nh.iph->frag_off = htons(IP_DF);
7119 +       nskb->nh.iph->id = 0;
7120 +
7121 +       /* Adjust IP checksum */
7122 +       nskb->nh.iph->check = 0;
7123 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
7124 +                                          nskb->nh.iph->ihl);
7125 +
7126 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
7127 +       fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
7128 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
7129 +       fl.oif = 0;
7130 +       if (ip_route_output_key(&nrt, &fl) != 0)
7131 +               goto free_nskb;
7132 +
7133 +       dst_release(nskb->dst);
7134 +       nskb->dst = &nrt->u.dst;
7135 +
7136 +       /* "Never happens" */
7137 +       if (nskb->len > dst_pmtu(nskb->dst))
7138 +               goto free_nskb;
7139 +
7140 +       ip_direct_send (nskb);
7141 +
7142 +       return;
7143 +
7144 + free_nskb:
7145 +       kfree_skb(nskb);
7146 +}
7147 +
7148 +
7149 +static unsigned int tarpit(struct sk_buff **pskb,
7150 +                          unsigned int hooknum,
7151 +                          const struct net_device *in,
7152 +                          const struct net_device *out,
7153 +                          const void *targinfo,
7154 +                          void *userinfo)
7155 +{
7156 +       struct sk_buff *skb = *pskb;
7157 +       struct rtable *rt = (struct rtable*)skb->dst;
7158 +
7159 +       /* Do we have an input route cache entry? */
7160 +       if (!rt)
7161 +               return NF_DROP;
7162 +
7163 +        /* No replies to physical multicast/broadcast */
7164 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
7165 +               return NF_DROP;
7166 +
7167 +        /* Now check at the protocol level */
7168 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
7169 +                return NF_DROP;
7170 +
7171 +       /* Our naive response construction doesn't deal with IP
7172 +           options, and probably shouldn't try. */
7173 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
7174 +               return NF_DROP;
7175 +
7176 +        /* We aren't interested in fragments */
7177 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
7178 +                return NF_DROP;
7179 +
7180 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
7181 +
7182 +       return NF_DROP;
7183 +}
7184 +
7185 +
7186 +static int check(const char *tablename,
7187 +                const struct ipt_entry *e,
7188 +                void *targinfo,
7189 +                unsigned int targinfosize,
7190 +                unsigned int hook_mask)
7191 +{
7192 +       /* Only allow these for input/forward packet filtering. */
7193 +       if (strcmp(tablename, "filter") != 0) {
7194 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
7195 +               return 0;
7196 +       }
7197 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
7198 +                           | (1 << NF_IP_FORWARD))) != 0) {
7199 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
7200 +               return 0;
7201 +       }
7202 +
7203 +       /* Must specify that it's a TCP packet */
7204 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
7205 +               DEBUGP("TARPIT: not valid for non-tcp\n");
7206 +               return 0;
7207 +       }
7208 +
7209 +       return 1;
7210 +}
7211 +
7212 +static struct ipt_target ipt_tarpit_reg = {
7213 +       .name           = "TARPIT",
7214 +       .target         = tarpit,
7215 +       .checkentry     = check,
7216 +       .me             = THIS_MODULE
7217 +};
7218 +
7219 +static int __init init(void)
7220 +{
7221 +       if (ipt_register_target(&ipt_tarpit_reg))
7222 +               return -EINVAL;
7223 +       return 0;
7224 +}
7225 +
7226 +static void __exit fini(void)
7227 +{
7228 +       ipt_unregister_target(&ipt_tarpit_reg);
7229 +}
7230 +
7231 +module_init(init);
7232 +module_exit(fini);
7233 +MODULE_LICENSE("GPL");
7234 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TCPLAG.c
7235 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TCPLAG.c 1970-01-01 01:00:00.000000000 +0100
7236 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TCPLAG.c     2004-04-16 09:15:54.000000000 +0200
7237 @@ -0,0 +1,697 @@
7238 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
7239 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
7240 + *
7241 + * This program is free software; you can redistribute it and/or modify
7242 + * it under the terms of the GNU General Public License as published by
7243 + * the Free Software Foundation; either version 2 of the License, or
7244 + * (at your option) any later version.
7245 + *
7246 + * This program is distributed in the hope that it will be useful,
7247 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7248 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7249 + * GNU General Public License for more details.
7250 + *
7251 + * You should have received a copy of the GNU General Public License
7252 + * along with this program; if not, write to the Free Software
7253 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
7254 + */
7255 +
7256 +/*
7257 + * This collects packets and attempts to make them into pairs
7258 + * based on its own knowledge of how typical network conversations
7259 + * operate. Once it has a pair, it logs the time between them.
7260 + */
7261 +#include <linux/module.h>
7262 +#include <linux/skbuff.h>
7263 +#include <linux/ip.h>
7264 +#include <linux/spinlock.h>
7265 +#include <net/icmp.h>
7266 +#include <net/udp.h>
7267 +#include <net/tcp.h>
7268 +#include <linux/netfilter_ipv4/ip_tables.h>
7269 +
7270 +#include <net/route.h>
7271 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
7272 +
7273 +#if 0
7274 +#define DEBUGP printk
7275 +#else
7276 +#define DEBUGP(format, args...)
7277 +#endif
7278 +
7279 +/*
7280 + * We need one spinlock for the hash table.
7281 + */
7282 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
7283 +
7284 +typedef struct timeval timeval_T;
7285 +
7286 +/*
7287 + * Linked lists of events in the connection,
7288 + * these store the SEQ numbers and the newest is always
7289 + * at the start of the linked list, then they get older
7290 + * down to the end of the linked list (this is not perfect
7291 + * if packets get out of order but we don't worry about fine
7292 + * details like that).
7293 + *
7294 + * Matching any event wipes out that event and also all other
7295 + * events down the chain (i.e. all older events).
7296 + * This keeps the linked list as short as possible.
7297 + */
7298 +typedef struct tcplag_event_S
7299 +{
7300 +       struct tcplag_event_S *next;
7301 +       u16 source_port;
7302 +       u16 dest_port;
7303 +       u32 expected_ACK;
7304 +       struct timeval stamp;
7305 +} tcplag_event_T;
7306 +
7307 +/*
7308 + * This stores the connection statistics
7309 + * We define connections more loosely than TCP/IP does,
7310 + * because we only consider the two hosts, not the ports
7311 + * Also, we list the host-pairs in low,high order which
7312 + * means that we don't care who originated the connection.
7313 + */
7314 +typedef struct tcplag_hash_S
7315 +{
7316 +       u32 low_ip;
7317 +       u32 high_ip;
7318 +       struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
7319 +       struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
7320 +       tcplag_event_T *h_ACK_list;     /* Try to match ACK packets coming from h in this list */
7321 +       tcplag_event_T *l_ACK_list;     /* Try to match ACK packets coming from l in this list */
7322 +       time_t stamp;                   /* When this bucket got added to the table */
7323 +       u16 count_l_SEQ_h_ACK;          /* Increment for each event */
7324 +       u16 count_h_SEQ_l_ACK;          /* Increment for each event */
7325 +} tcplag_hash_T;
7326 +
7327 +static tcplag_hash_T **hashtab = 0;
7328 +static u32 hashsize = 0;
7329 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
7330 +static u32 reaper_ix = 0;
7331 +
7332 +static void divide_down( timeval_T *T, int c )
7333 +{
7334 +       int remainder;
7335 +
7336 +       T->tv_usec /= c;
7337 +       remainder = T->tv_sec % c; /* Only works properly with positive numbers */
7338 +       remainder *= 1000000;
7339 +       T->tv_usec == remainder;
7340 +       T->tv_sec /= c;
7341 +}
7342 +
7343 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
7344 +{
7345 +       register long x;
7346 +
7347 +       x = tv1->tv_sec - tv2->tv_sec;
7348 +       if( x ) return( x );
7349 +       x = tv1->tv_usec - tv2->tv_usec;
7350 +       return( x );
7351 +}
7352 +
7353 +void sprint_timeval( char *buf, timeval_T *tv )
7354 +{
7355 +       if( tv->tv_sec )
7356 +               sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
7357 +       else
7358 +               sprintf( buf, "%lu", tv->tv_usec );
7359 +}
7360 +
7361 +/*
7362 + * This generates the log messages through printk()
7363 + *
7364 + * There is really no particular interest in the port numbers at this stage,
7365 + * they are only useful for matching up the request with the reply.
7366 + * The IP numbers are useful because some sites may be slower than others
7367 + * or may travel different routes, etc (OK, in theory changing the port number
7368 + * could also change the route but I don't like that sort of theory).
7369 + *
7370 + * The tags are:
7371 + *
7372 + * LIP=          The IP number of the side with the lowest lag
7373 + * RIP=          The IP number of the side with the highest lag
7374 + * LLAG=         The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
7375 + * RLAG=         The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
7376 + */
7377 +static void output( tcplag_hash_T *H, int level, const char *prefix )
7378 +{
7379 +       struct timeval ltm, rtm;
7380 +       u32 local_ip, remote_ip;
7381 +       char r_buf[ 20 ], l_buf[ 20 ];
7382 +/*
7383 + * We can't make sense of a connection that only passes data one way,
7384 + * In principle, at least the SYN and FIN should go both ways so we
7385 + * should get a few hits for every connection.
7386 + */
7387 +       if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
7388 +/*
7389 + * Calculate average times by dividing down
7390 + */
7391 +       divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
7392 +       divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
7393 +/*
7394 + * Sort these two by the lag so the the local is always the short lag
7395 + */
7396 +       if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
7397 +       {
7398 +               local_ip    = H->low_ip;
7399 +               remote_ip   = H->high_ip;
7400 +               rtm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
7401 +               rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
7402 +               ltm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
7403 +               ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
7404 +       }
7405 +       else
7406 +       {
7407 +               local_ip    = H->high_ip;
7408 +               remote_ip   = H->low_ip;
7409 +               ltm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
7410 +               ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
7411 +               rtm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
7412 +               rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
7413 +       }
7414 +/*
7415 + * Don't use a spinlock on the output,
7416 + * it is not guaranteed safe because some OTHER printk could
7417 + * split our log message so we want only one single printk.
7418 + *
7419 + * We use sprintf() to partially pre-digest the output
7420 + *
7421 + * Actually, neither this not the main netfilter LOG target is
7422 + * really safe from printk() overlap, basically syslog cannot
7423 + * be regarded as a guaranteed data output channel. It is good
7424 + * enough for most purposes.
7425 + */
7426 +       sprint_timeval( l_buf, &ltm );
7427 +       sprint_timeval( r_buf, &rtm );
7428 +       printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
7429 +                       level & 7, prefix,
7430 +                       NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
7431 +                       l_buf, r_buf );
7432 +}
7433 +
7434 +/*
7435 + * The reaper rolls through the hash table looking for old.
7436 + * Log entries are only generated at the reaping time
7437 + * (which means all log entries are out-of-date)
7438 + */
7439 +static void reaper( time_t now, int level, const char *prefix )
7440 +{
7441 +       int i;
7442 +
7443 +       now -= max_seconds;
7444 +       if( !hashsize ) return;
7445 +       if( !hashtab ) return;
7446 +       for( i = 0; i < 10; i++ )
7447 +       {
7448 +               if( ++reaper_ix >= hashsize ) reaper_ix = 0; 
7449 +
7450 +//             DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
7451 +
7452 +               if( hashtab[ reaper_ix ])
7453 +               {
7454 +                       tcplag_hash_T *found = 0;
7455 +
7456 +                       spin_lock_bh( &hash_lock );
7457 +                       if( hashtab[ reaper_ix ])
7458 +                       {
7459 +                               if( now > hashtab[ reaper_ix ]->stamp )
7460 +                               {
7461 +                                       DEBUGP( KERN_WARNING "reaper found expired entry\n" );
7462 +                                       found = hashtab[ reaper_ix ];
7463 +                                       hashtab[ reaper_ix ] = 0;
7464 +                               }
7465 +                       }
7466 +                       spin_unlock_bh( &hash_lock );
7467 +
7468 +                       if( found )
7469 +                       {
7470 +                               output( found, level, prefix );
7471 +                               kfree( found );
7472 +                       }
7473 +               }
7474 +       }
7475 +}
7476 +
7477 +/*
7478 + * Convert the connection characteristics into a number
7479 + * (not including the timestamp) FIXME: this is a sucky hash function
7480 + */
7481 +static u32 make_hash( tcplag_hash_T *connection )
7482 +{
7483 +       register u32 r;
7484 +
7485 +       r = connection->low_ip;
7486 +       r += connection->high_ip;
7487 +       return( r );
7488 +}
7489 +
7490 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
7491 +{
7492 +       int x;
7493 +
7494 +       x = con1->low_ip - con2->low_ip; if( x ) return( x );
7495 +       x = con1->high_ip - con2->high_ip;
7496 +       return( x );
7497 +}
7498 +
7499 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
7500 +{
7501 +       int x;
7502 +
7503 +       DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
7504 +       x = ev1->expected_ACK - ev2->expected_ACK;
7505 +       if( x ) return( x );
7506 +       DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
7507 +       x = ev1->source_port - ev2->source_port;
7508 +       if( x ) return( x );
7509 +       DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
7510 +       x = ev1->dest_port - ev2->dest_port;
7511 +       return( x );
7512 +}
7513 +
7514 +/*
7515 + * Go to the hash table and either find an existing connection that
7516 + * matches correctly or inject a new connection into the table.
7517 + * Once the connection is OK, chain the event onto the linked list.
7518 + */
7519 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
7520 +{
7521 +       u32 h, i;
7522 +
7523 +       if( !event ) return; /* Just to be safe */
7524 +       if( !hashsize ) return;
7525 +       if( !hashtab ) return;
7526 +
7527 +       h = make_hash( connection );
7528 +       h %= hashsize;
7529 +
7530 +       DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
7531 +
7532 +       spin_lock_bh( &hash_lock );
7533 +       for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
7534 +       {
7535 +               tcplag_hash_T *co_new = 0;
7536 +/*
7537 + * Consider existing entry
7538 + */
7539 +               if( hashtab[ h ])
7540 +               {
7541 +                       if( compare_connections( hashtab[ h ], connection )) continue;
7542 +                       co_new = hashtab[ h ];
7543 +                       DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
7544 +                       goto add_link;
7545 +               }
7546 +/*
7547 + * Use empty slot for new entry
7548 + */
7549 +               if( !hashtab[ h ])
7550 +               {
7551 +                       co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
7552 +                       memset( co_new, 0, sizeof( tcplag_hash_T ));
7553 +                       co_new->low_ip = connection->low_ip;
7554 +                       co_new->high_ip = connection->high_ip;
7555 +                       co_new->stamp = event->stamp.tv_sec;
7556 +                       hashtab[ h ] = co_new;
7557 +                       DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
7558 + add_link:
7559 +                       {
7560 +                               tcplag_event_T *ev_new;
7561 +
7562 +                               ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
7563 +                               memcpy( ev_new, event, sizeof( tcplag_event_T ));
7564 +                               if( direction )
7565 +                               {
7566 +                                       ev_new->next = co_new->h_ACK_list;
7567 +                                       co_new->h_ACK_list = ev_new;
7568 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
7569 +                               }
7570 +                               else
7571 +                               {
7572 +                                       ev_new->next = co_new->l_ACK_list;
7573 +                                       co_new->l_ACK_list = ev_new;
7574 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
7575 +                               }
7576 +                       }
7577 +                       goto done;
7578 +               }
7579 +       }
7580 + done:
7581 +       spin_unlock_bh( &hash_lock );
7582 +}
7583 +
7584 +/*
7585 + * Search the hash table for a matching connection,
7586 + * if we can't find one of those then we are stuffed.
7587 + *
7588 + * Once a connection has been found, scan along the list for
7589 + * a matching SEQ number and if that is found then calculate
7590 + * the lag, update the counters and cut the chain at the
7591 + * point where the matching SEQ is found.
7592 + */
7593 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
7594 +{
7595 +       u32 h, i;
7596 +
7597 +       if( !event ) return( 0 );
7598 +       if( !hashsize ) return( 0 );
7599 +       if( !hashtab ) return( 0 );
7600 +       h = make_hash( connection );
7601 +       h %= hashsize;
7602 +
7603 +       DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
7604 +
7605 +       for( i = 0; i < hashsize; i++ )
7606 +       {
7607 +               tcplag_hash_T *found = 0;
7608 +
7609 +               if( !hashtab[ h ]) return( 0 );
7610 +
7611 +               spin_lock_bh( &hash_lock );
7612 +               if( hashtab[ h ])
7613 +               {
7614 +                       if( !compare_connections( hashtab[ h ], connection ))
7615 +                       {
7616 +                               tcplag_event_T *ev, **evroot;
7617 +                               timeval_T *tv;
7618 +                               u16 *cn;
7619 +
7620 +                               found = hashtab[ h ];
7621 +                               if( direction )
7622 +                               {
7623 +                                       evroot = &found->h_ACK_list;
7624 +                                       tv = &found->lag_l_SEQ_h_ACK;
7625 +                                       cn = &found->count_l_SEQ_h_ACK;
7626 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
7627 +                               }
7628 +                               else
7629 +                               {
7630 +                                       evroot = &found->l_ACK_list;
7631 +                                       tv = &found->lag_h_SEQ_l_ACK;
7632 +                                       cn = &found->count_h_SEQ_l_ACK;
7633 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
7634 +                               }
7635 +                               for( ev = *evroot; ev; ev = ev->next )
7636 +                               {
7637 +                                       if( !compare_events( ev, event ))
7638 +                                       {
7639 +/*
7640 + * Calculate the lag (in two parts) and add that to the collection
7641 + */
7642 +                                               event->stamp.tv_sec -= ev->stamp.tv_sec;
7643 +                                               event->stamp.tv_usec -= ev->stamp.tv_usec;
7644 +                                               if( event->stamp.tv_usec < 0 )
7645 +                                               {
7646 +                                                       event->stamp.tv_usec += 1000000;
7647 +                                                       event->stamp.tv_sec++;
7648 +                                               }
7649 +                                               if( event->stamp.tv_sec < 0 )
7650 +                                               {
7651 +                                                       DEBUGP( KERN_WARNING "Negative lag detected\n" );
7652 +                                               }
7653 +                                               else
7654 +                                               {
7655 +                                                       tv->tv_sec += event->stamp.tv_sec;
7656 +                                                       tv->tv_usec += event->stamp.tv_usec;
7657 +                                                       ++*cn;
7658 +                                                       DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
7659 +                                                                       " (accumulator is up to %lu.%06lu, %u events)\n",
7660 +                                                                       event->stamp.tv_sec,
7661 +                                                                       event->stamp.tv_usec,
7662 +                                                                       tv->tv_sec, tv->tv_usec, *cn );
7663 +                                               }
7664 +/*
7665 + * Truncate the linked list.
7666 + *
7667 + * Visit each event in the list and return the memory to the pool.
7668 + *
7669 + * If a host is making multiple connections to the same remote host
7670 + * then this truncation will result in some requests not being
7671 + * monitored. Statistically we will still get some reasonable number
7672 + * of measurements and multiple simultaneous connections between host
7673 + * pairs don't happen all that often.
7674 + */
7675 +                                               *evroot = 0;
7676 +                                               while( ev )
7677 +                                               {
7678 +                                                       tcplag_event_T *ev_next = ev->next;
7679 +                                                       DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
7680 +                                                       kfree( ev );
7681 +                                                       ev = ev_next;
7682 +                                               }
7683 +/*
7684 + * TODO: overflow limit for *cn, force premature output() if necessary
7685 + * (and drop this connection from the hash table)
7686 + */
7687 +                                               break;
7688 +                                       }
7689 +                               }
7690 +                               goto done;
7691 +                       }
7692 +               }
7693 + done:
7694 +               spin_unlock_bh( &hash_lock );
7695 +
7696 +               if( found ) return( 1 );
7697 +               if( ++h >= hashsize ) h = 0;
7698 +       }       
7699 +       return( 0 );
7700 +}
7701 +
7702 +/*
7703 + * Here is our target data:
7704 + *
7705 + * pskb      --  The packet itself (see linux/skbuff.h for breakdown)
7706 + *
7707 + * hooknum   --
7708 + *
7709 + * in        --  The device that this packet came in on
7710 + *               (depending on the chain this may or may not exist)
7711 + *
7712 + * out       --  The device that this packet is just about to go
7713 + *               out onto (again existance depends on the chain)
7714 + *
7715 + * targinfo  --  Our private data (handed through from iptables command util)
7716 + *
7717 + * userinfo  --  Some more data
7718 + *
7719 + */
7720 +
7721 +static unsigned int target( struct sk_buff **pskb,
7722 +                                                       unsigned int hooknum,
7723 +                                                       const struct net_device *in,
7724 +                                                       const struct net_device *out,
7725 +                                                       const void *targinfo,
7726 +                                                       void *userinfo )
7727 +{
7728 +       struct iphdr *iph = ( *pskb )->nh.iph;
7729 +       const struct ipt_tcplag *el = targinfo;
7730 +       tcplag_hash_T connection;
7731 +       tcplag_event_T event;
7732 +       int direction;
7733 +/*
7734 + * We know we are dealing with IP here
7735 + * Fill in all the obvious fields
7736 + */
7737 +       if( iph->saddr > iph->daddr )
7738 +       {
7739 +               direction = 0;
7740 +               connection.high_ip = iph->saddr;
7741 +               connection.low_ip = iph->daddr;
7742 +       }
7743 +       else
7744 +       {
7745 +               direction = 1;
7746 +               connection.low_ip = iph->saddr;
7747 +               connection.high_ip = iph->daddr;
7748 +       }
7749 +       do_gettimeofday( &event.stamp );
7750 +/*
7751 + * Do a bit of cleaning
7752 + */
7753 +       reaper( event.stamp.tv_sec, el->level, el->prefix );
7754 +
7755 +       DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
7756 +                       event.stamp.tv_sec,
7757 +                       event.stamp.tv_usec,
7758 +                       in ? in->name : "none", out ? out->name : "none" );
7759 +/*
7760 + * Now start looking at the details
7761 + *
7762 + * First step is to identify this packet to see if it is 
7763 + * the sort of packet that we are interested in.
7764 + * Don't hold any locks while we are doing this because often
7765 + * we will just let the packet go without any further consideration.
7766 + */
7767 +       switch( iph->protocol )
7768 +       {
7769 +               case IPPROTO_TCP:
7770 +               {
7771 +                       struct tcphdr *tcp;
7772 +
7773 +                       if( ntohs( iph->frag_off ) & IP_OFFSET )
7774 +                       {
7775 +                               DEBUGP( KERN_WARNING "ignoring fragment\n" );
7776 +                               break;
7777 +                       }
7778 +                       tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
7779 +                       event.source_port = ntohs( tcp->source );
7780 +                       event.dest_port = ntohs( tcp->dest );
7781 +/*
7782 + * Every packet should have a valid SEQ number so use this to
7783 + * generate an ACK number. This works along the formula:
7784 + * -- Start with the SEQ number
7785 + * -- For SYN or FIN add 1 to that number
7786 + * -- For data packet, add the data length to that number
7787 + */
7788 +
7789 +/*
7790 + * Data length requires a bit of fiddling around
7791 + */
7792 +                       {
7793 +                               unsigned int data_len;
7794 +                               if( tcp->syn || tcp->fin )
7795 +                               {
7796 +                                       data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
7797 +                               }
7798 +                               else
7799 +                               {
7800 +                                       data_len = ntohs( iph->tot_len );
7801 +                                       data_len -= 4 * iph->ihl;  /* Subtract away IP header & options */
7802 +                                       data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
7803 +                               }
7804 +                               
7805 +                               DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
7806 +
7807 +                               if( data_len ) /* Only track events that demand an ACK */
7808 +                               {
7809 +                                       event.expected_ACK = ntohl( tcp->seq ) + data_len;
7810 +                                       hash_insert( &connection, &event, direction );
7811 +                               }
7812 +                               else
7813 +                               {
7814 +                                       DEBUGP( "Don't bother to insert this, ACK not required\n" );
7815 +                               }
7816 +                       }
7817 +
7818 +                       if( tcp->ack )
7819 +                       {
7820 +/*
7821 + * Now we consider the matching of an existing event.
7822 + * Reverse the port numbers and change the ACK number to the actual ACK number
7823 + * Note that the direction is reversed because the reply will be going
7824 + * the opposite way to the request.
7825 + */
7826 +                               event.expected_ACK = ntohl( tcp->ack_seq );
7827 +                               event.dest_port = ntohs( tcp->source );
7828 +                               event.source_port = ntohs( tcp->dest );
7829 +                               request_complete( &connection, &event, !direction );
7830 +                       }
7831 +                       else
7832 +                       {
7833 +                               DEBUGP( "Don't bother to check this, ACK not valid\n" );
7834 +                       }
7835 +               }
7836 +       }
7837 +       return( IPT_CONTINUE );
7838 +}
7839 +
7840 +/*
7841 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
7842 + * return( 1 ) if the entry is suitable
7843 + *
7844 + * tablename     --  
7845 + *
7846 + * e             --  
7847 + *
7848 + * targinfo      --  Our private data block (handed to us from iptables plug-in)
7849 + *
7850 + * targinfosize  --  The size of our private data block
7851 + *
7852 + * hook_mask     --  
7853 + *
7854 + *
7855 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
7856 + * all possible flag combos make sense. All we check for is correct data size.
7857 + */
7858 +static int checkentry( const char *tablename,
7859 +                                          const struct ipt_entry *e,
7860 +                                          void *targinfo,
7861 +                                          unsigned int targinfosize,
7862 +                                          unsigned int hook_mask )
7863 +{
7864 +       const struct ipt_tcplag *el = targinfo;
7865 +
7866 +       if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
7867 +       {
7868 +               DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
7869 +                               IPT_ALIGN( sizeof( struct ipt_tcplag )));
7870 +               return( 0 );
7871 +       }
7872 +       if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
7873 +       return( 1 );
7874 +}
7875 +
7876 +static struct ipt_target reg =
7877 +{
7878 +       { 0, 0 },
7879 +       "TCPLAG",
7880 +       &target,
7881 +       &checkentry,
7882 +       0,
7883 +    THIS_MODULE
7884 +};
7885 +
7886 +static int __init init( void )
7887 +{
7888 +       if( ipt_register_target( &reg )) return( -EINVAL );
7889 +       hashsize = 123; /* should be configurable */
7890 +       hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
7891 +       memset( hashtab, 0, sizeof( void * ) * hashsize );
7892 +       return( 0 );
7893 +}
7894 +
7895 +/*
7896 + * This should not need locks (in theory)
7897 + * because it can only get punted after it is no longer
7898 + * chained into any of the netfilter lists.
7899 + */
7900 +static void __exit fini( void )
7901 +{
7902 +       int i;
7903 +
7904 +       ipt_unregister_target( &reg );
7905 +/*
7906 + * Put back kernel memory
7907 + */
7908 +       for( i = 0; i < hashsize; i++ )
7909 +       {
7910 +               tcplag_hash_T *p;
7911 +
7912 +               if(( p = hashtab[ i ]))
7913 +               {
7914 +                       tcplag_event_T *ev, *evn;
7915 +
7916 +                       hashtab[ i ] = 0;
7917 +                       for( ev = p->h_ACK_list; ev; ev = evn )
7918 +                       {
7919 +                               evn = ev->next;
7920 +                               kfree( ev );
7921 +                       }
7922 +                       for( ev = p->l_ACK_list; ev; ev = evn )
7923 +                       {
7924 +                               evn = ev->next;
7925 +                               kfree( ev );
7926 +                       }
7927 +                       kfree( p );
7928 +               }
7929 +       }
7930 +       kfree( hashtab );
7931 +}
7932 +
7933 +module_init(init);
7934 +module_exit(fini);
7935 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_XOR.c
7936 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_XOR.c    1970-01-01 01:00:00.000000000 +0100
7937 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_XOR.c        2004-04-16 09:16:25.000000000 +0200
7938 @@ -0,0 +1,117 @@
7939 +/* XOR target for IP tables
7940 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
7941 + * Based on ipt_TTL.c
7942 + *
7943 + * Version 1.0
7944 + *
7945 + * This software is distributed under the terms of GNU GPL
7946 + */
7947 +
7948 +#include <linux/module.h>
7949 +#include <linux/skbuff.h>
7950 +#include <linux/ip.h>
7951 +#include <linux/tcp.h>
7952 +#include <linux/udp.h>
7953 +
7954 +#include <linux/netfilter_ipv4/ip_tables.h>
7955 +#include <linux/netfilter_ipv4/ipt_XOR.h>
7956 +
7957 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
7958 +MODULE_DESCRIPTION("IP tables XOR module");
7959 +MODULE_LICENSE("GPL");
7960 +
7961 +static unsigned int 
7962 +ipt_xor_target(struct sk_buff **pskb, 
7963 +               const struct net_device *in, const struct net_device *out, 
7964 +               unsigned int hooknum, const void *targinfo, void *userinfo)
7965 +{
7966 +       struct ipt_XOR_info *info = (void *) targinfo;
7967 +       struct iphdr *iph;
7968 +       struct tcphdr *tcph;
7969 +       struct udphdr *udph;
7970 +       int i, j, k;
7971 +
7972 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
7973 +               return NF_DROP;
7974 +
7975 +       iph = (*pskb)->nh.iph;
7976 +  
7977 +       if (iph->protocol == IPPROTO_TCP) {
7978 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
7979 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
7980 +                       for (k=0; k<=info->block_size; k++) {
7981 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
7982 +                                               info->key[j];
7983 +                               i++;
7984 +                       }
7985 +                       j++;
7986 +                       if (info->key[j] == 0x00)
7987 +                               j = 0;
7988 +               }
7989 +       } else if (iph->protocol == IPPROTO_UDP) {
7990 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
7991 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
7992 +                       for (k=0; k<=info->block_size; k++) {
7993 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
7994 +                                               info->key[j];
7995 +                               i++;
7996 +                       }
7997 +                       j++;
7998 +                       if (info->key[j] == 0x00)
7999 +                               j = 0;
8000 +               }
8001 +       }
8002 +  
8003 +       return IPT_CONTINUE;
8004 +}
8005 +
8006 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
8007 +               void *targinfo, unsigned int targinfosize, 
8008 +               unsigned int hook_mask)
8009 +{
8010 +       struct ipt_XOR_info *info = targinfo;
8011 +
8012 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
8013 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
8014 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
8015 +               return 0;
8016 +       }       
8017 +
8018 +       if (strcmp(tablename, "mangle")) {
8019 +               printk(KERN_WARNING "XOR: can only be called from"
8020 +                               "\"mangle\" table, not \"%s\"\n", tablename);
8021 +               return 0; 
8022 +       }
8023 +
8024 +       if (!strcmp(info->key, "")) {
8025 +               printk(KERN_WARNING "XOR: You must specify a key");
8026 +               return 0;
8027 +       }
8028 +
8029 +       if (info->block_size == 0) {
8030 +               printk(KERN_WARNING "XOR: You must specify a block-size");
8031 +               return 0;
8032 +       }
8033 +
8034 +       return 1;
8035 +}
8036 +
8037 +static struct ipt_target ipt_XOR = { 
8038 +       .name = "XOR",
8039 +       .target = ipt_xor_target, 
8040 +       .checkentry = ipt_xor_checkentry,
8041 +       .me = THIS_MODULE,
8042 +};
8043 +
8044 +static int __init init(void)
8045 +{
8046 +       return ipt_register_target(&ipt_XOR);
8047 +}
8048 +
8049 +static void __exit fini(void)
8050 +{
8051 +       ipt_unregister_target(&ipt_XOR);
8052 +}
8053 +
8054 +module_init(init);
8055 +module_exit(fini);
8056 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_addrtype.c
8057 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_addrtype.c       1970-01-01 01:00:00.000000000 +0100
8058 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_addrtype.c   2004-04-16 09:16:27.000000000 +0200
8059 @@ -0,0 +1,68 @@
8060 +/*
8061 + *  iptables module to match inet_addr_type() of an ip.
8062 + */
8063 +
8064 +#include <linux/module.h>
8065 +#include <linux/skbuff.h>
8066 +#include <linux/netdevice.h>
8067 +#include <net/route.h>
8068 +
8069 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
8070 +#include <linux/netfilter_ipv4/ip_tables.h>
8071 +
8072 +MODULE_LICENSE("GPL");
8073 +
8074 +static inline int match_type(u_int32_t addr, u_int16_t mask)
8075 +{
8076 +       return !!(mask & (1 << inet_addr_type(addr)));
8077 +}
8078 +
8079 +static int match(const struct sk_buff *skb, const struct net_device *in,
8080 +                const struct net_device *out, const void *matchinfo,
8081 +                int offset, int *hotdrop)
8082 +{
8083 +       const struct ipt_addrtype_info *info = matchinfo;
8084 +       const struct iphdr *iph = skb->nh.iph;
8085 +       int ret = 1;
8086 +
8087 +       if (info->source)
8088 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
8089 +       if (info->dest)
8090 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
8091 +       
8092 +       return ret;
8093 +}
8094 +
8095 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
8096 +                     void *matchinfo, unsigned int matchsize,
8097 +                     unsigned int hook_mask)
8098 +{
8099 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
8100 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
8101 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
8102 +               return 0;
8103 +       }
8104 +
8105 +       return 1;
8106 +}
8107 +
8108 +static struct ipt_match addrtype_match = { 
8109 +       .name = "addrtype",
8110 +       .match = match,
8111 +       .checkentry = checkentry,
8112 +       .me = THIS_MODULE
8113 +};
8114 +
8115 +static int __init init(void)
8116 +{
8117 +       return ipt_register_match(&addrtype_match);
8118 +}
8119 +
8120 +static void __exit fini(void)
8121 +{
8122 +       ipt_unregister_match(&addrtype_match);
8123 +
8124 +}
8125 +
8126 +module_init(init);
8127 +module_exit(fini);
8128 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_connmark.c
8129 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_connmark.c       1970-01-01 01:00:00.000000000 +0100
8130 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_connmark.c   2004-04-16 09:15:41.000000000 +0200
8131 @@ -0,0 +1,81 @@
8132 +/* This kernel module matches connection mark values set by the
8133 + * CONNMARK target
8134 + *
8135 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8136 + * by Henrik Nordstrom <hno@marasystems.com>
8137 + *
8138 + * This program is free software; you can redistribute it and/or modify
8139 + * it under the terms of the GNU General Public License as published by
8140 + * the Free Software Foundation; either version 2 of the License, or
8141 + * (at your option) any later version.
8142 + *
8143 + * This program is distributed in the hope that it will be useful,
8144 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8145 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8146 + * GNU General Public License for more details.
8147 + *
8148 + * You should have received a copy of the GNU General Public License
8149 + * along with this program; if not, write to the Free Software
8150 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
8151 + */
8152 +
8153 +#include <linux/module.h>
8154 +#include <linux/skbuff.h>
8155 +
8156 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8157 +MODULE_DESCRIPTION("IP tables connmark match module");
8158 +MODULE_LICENSE("GPL");
8159 +
8160 +#include <linux/netfilter_ipv4/ip_tables.h>
8161 +#include <linux/netfilter_ipv4/ipt_connmark.h>
8162 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8163 +
8164 +static int
8165 +match(const struct sk_buff *skb,
8166 +      const struct net_device *in,
8167 +      const struct net_device *out,
8168 +      const void *matchinfo,
8169 +      int offset,
8170 +      int *hotdrop)
8171 +{
8172 +       const struct ipt_connmark_info *info = matchinfo;
8173 +       enum ip_conntrack_info ctinfo;
8174 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
8175 +       if (!ct)
8176 +               return 0;
8177 +
8178 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
8179 +}
8180 +
8181 +static int
8182 +checkentry(const char *tablename,
8183 +          const struct ipt_ip *ip,
8184 +          void *matchinfo,
8185 +          unsigned int matchsize,
8186 +          unsigned int hook_mask)
8187 +{
8188 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
8189 +               return 0;
8190 +
8191 +       return 1;
8192 +}
8193 +
8194 +static struct ipt_match connmark_match = {
8195 +       .name = "connmark",
8196 +       .match = &match,
8197 +       .checkentry = &checkentry,
8198 +       .me = THIS_MODULE
8199 +};
8200 +
8201 +static int __init init(void)
8202 +{
8203 +       return ipt_register_match(&connmark_match);
8204 +}
8205 +
8206 +static void __exit fini(void)
8207 +{
8208 +       ipt_unregister_match(&connmark_match);
8209 +}
8210 +
8211 +module_init(init);
8212 +module_exit(fini);
8213 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_osf.c
8214 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_osf.c    2004-04-16 08:59:08.000000000 +0200
8215 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_osf.c        2004-04-16 09:20:53.000000000 +0200
8216 @@ -44,6 +44,7 @@
8217  #include <linux/ctype.h>
8218  #include <linux/list.h>
8219  #include <linux/if.h>
8220 +#include <linux/tcp.h>
8221  
8222  #include <net/sock.h>
8223  #include <net/ip.h>
8224 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_owner.c
8225 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_owner.c  2004-04-15 03:35:57.000000000 +0200
8226 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_owner.c      2004-04-16 09:18:14.000000000 +0200
8227 @@ -6,12 +6,19 @@
8228   * This program is free software; you can redistribute it and/or modify
8229   * it under the terms of the GNU General Public License version 2 as
8230   * published by the Free Software Foundation.
8231 + *
8232 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
8233   */
8234  
8235  #include <linux/module.h>
8236  #include <linux/skbuff.h>
8237  #include <linux/file.h>
8238 +#include <linux/ip.h>
8239 +#include <linux/tcp.h>
8240 +#include <linux/udp.h>
8241  #include <net/sock.h>
8242 +#include <net/tcp.h>
8243 +#include <net/udp.h>
8244  
8245  #include <linux/netfilter_ipv4/ipt_owner.h>
8246  #include <linux/netfilter_ipv4/ip_tables.h>
8247 @@ -21,7 +28,7 @@
8248  MODULE_DESCRIPTION("iptables owner match");
8249  
8250  static int
8251 -match_comm(const struct sk_buff *skb, const char *comm)
8252 +match_comm(const struct sock *sk, const char *comm)
8253  {
8254         struct task_struct *g, *p;
8255         struct files_struct *files;
8256 @@ -38,7 +45,7 @@
8257                         spin_lock(&files->file_lock);
8258                         for (i=0; i < files->max_fds; i++) {
8259                                 if (fcheck_files(files, i) ==
8260 -                                   skb->sk->sk_socket->file) {
8261 +                                   sk->sk_socket->file) {
8262                                         spin_unlock(&files->file_lock);
8263                                         task_unlock(p);
8264                                         read_unlock(&tasklist_lock);
8265 @@ -54,7 +61,7 @@
8266  }
8267  
8268  static int
8269 -match_pid(const struct sk_buff *skb, pid_t pid)
8270 +match_pid(const struct sock *sk, pid_t pid)
8271  {
8272         struct task_struct *p;
8273         struct files_struct *files;
8274 @@ -70,7 +77,7 @@
8275                 spin_lock(&files->file_lock);
8276                 for (i=0; i < files->max_fds; i++) {
8277                         if (fcheck_files(files, i) ==
8278 -                           skb->sk->sk_socket->file) {
8279 +                           sk->sk_socket->file) {
8280                                 spin_unlock(&files->file_lock);
8281                                 task_unlock(p);
8282                                 read_unlock(&tasklist_lock);
8283 @@ -86,10 +93,10 @@
8284  }
8285  
8286  static int
8287 -match_sid(const struct sk_buff *skb, pid_t sid)
8288 +match_sid(const struct sock *sk, pid_t sid)
8289  {
8290         struct task_struct *g, *p;
8291 -       struct file *file = skb->sk->sk_socket->file;
8292 +       struct file *file = sk->sk_socket->file;
8293         int i, found=0;
8294  
8295         read_lock(&tasklist_lock);
8296 @@ -129,41 +136,71 @@
8297        int *hotdrop)
8298  {
8299         const struct ipt_owner_info *info = matchinfo;
8300 +       struct iphdr *iph = skb->nh.iph;
8301 +       struct sock *sk = NULL;
8302 +       int ret = 0;
8303 +
8304 +       if (out) {
8305 +               sk = skb->sk;
8306 +       } else {
8307 +               if (iph->protocol == IPPROTO_TCP) {
8308 +                       struct tcphdr *tcph =
8309 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
8310 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
8311 +                                          iph->daddr, tcph->dest,
8312 +                                          skb->dev->ifindex);
8313 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
8314 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
8315 +                               return ret;
8316 +                       }
8317 +               } else if (iph->protocol == IPPROTO_UDP) {
8318 +                       struct udphdr *udph =
8319 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
8320 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
8321 +                                          udph->dest, skb->dev->ifindex);
8322 +               }
8323 +       }
8324  
8325 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
8326 -               return 0;
8327 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
8328 +               goto out;
8329  
8330         if(info->match & IPT_OWNER_UID) {
8331 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
8332 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
8333                     !!(info->invert & IPT_OWNER_UID))
8334 -                       return 0;
8335 +                       goto out;
8336         }
8337  
8338         if(info->match & IPT_OWNER_GID) {
8339 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
8340 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
8341                     !!(info->invert & IPT_OWNER_GID))
8342 -                       return 0;
8343 +                       goto out;
8344         }
8345  
8346         if(info->match & IPT_OWNER_PID) {
8347 -               if (!match_pid(skb, info->pid) ^
8348 +               if (!match_pid(sk, info->pid) ^
8349                     !!(info->invert & IPT_OWNER_PID))
8350 -                       return 0;
8351 +                       goto out;
8352         }
8353  
8354         if(info->match & IPT_OWNER_SID) {
8355 -               if (!match_sid(skb, info->sid) ^
8356 +               if (!match_sid(sk, info->sid) ^
8357                     !!(info->invert & IPT_OWNER_SID))
8358 -                       return 0;
8359 +                       goto out;
8360         }
8361  
8362         if(info->match & IPT_OWNER_COMM) {
8363 -               if (!match_comm(skb, info->comm) ^
8364 +               if (!match_comm(sk, info->comm) ^
8365                     !!(info->invert & IPT_OWNER_COMM))
8366 -                       return 0;
8367 +                       goto out;
8368         }
8369  
8370 -       return 1;
8371 +       ret = 1;
8372 +
8373 +out:
8374 +       if (in && sk)
8375 +               sock_put(sk);
8376 +
8377 +       return ret;
8378  }
8379  
8380  static int
8381 @@ -173,11 +210,19 @@
8382             unsigned int matchsize,
8383             unsigned int hook_mask)
8384  {
8385 -        if (hook_mask
8386 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
8387 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
8388 -                return 0;
8389 -        }
8390 +       if (hook_mask
8391 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
8392 +           (1 << NF_IP_LOCAL_IN))) {
8393 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
8394 +                      "or POST_ROUTING.\n");
8395 +               return 0;
8396 +       }
8397 +
8398 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
8399 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
8400 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
8401 +               return 0;
8402 +       }
8403  
8404         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
8405                 printk("Matchsize %u != %Zu\n", matchsize,
8406 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_policy.c
8407 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
8408 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_policy.c     2004-04-16 09:18:18.000000000 +0200
8409 @@ -0,0 +1,176 @@
8410 +/* IP tables module for matching IPsec policy
8411 + *
8412 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
8413 + *
8414 + * This program is free software; you can redistribute it and/or modify
8415 + * it under the terms of the GNU General Public License version 2 as
8416 + * published by the Free Software Foundation.
8417 + */
8418 +
8419 +#include <linux/kernel.h>
8420 +#include <linux/config.h>
8421 +#include <linux/module.h>
8422 +#include <linux/skbuff.h>
8423 +#include <linux/init.h>
8424 +#include <net/xfrm.h>
8425 +
8426 +#include <linux/netfilter_ipv4.h>
8427 +#include <linux/netfilter_ipv4/ipt_policy.h>
8428 +#include <linux/netfilter_ipv4/ip_tables.h>
8429 +
8430 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
8431 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
8432 +MODULE_LICENSE("GPL");
8433 +
8434 +
8435 +static inline int
8436 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
8437 +{
8438 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
8439 +
8440 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
8441 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
8442 +           MISMATCH(proto, x->id.proto) ||
8443 +           MISMATCH(mode, x->props.mode) ||
8444 +           MISMATCH(spi, x->id.spi) ||
8445 +           MISMATCH(reqid, x->props.reqid))
8446 +               return 0;
8447 +       return 1;
8448 +}
8449 +
8450 +static int
8451 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
8452 +{
8453 +       const struct ipt_policy_elem *e;
8454 +       struct sec_path *sp = skb->sp;
8455 +       int strict = info->flags & POLICY_MATCH_STRICT;
8456 +       int i, pos;
8457 +
8458 +       if (sp == NULL)
8459 +               return -1;
8460 +       if (strict && info->len != sp->len)
8461 +               return 0;
8462 +
8463 +       for (i = sp->len - 1; i >= 0; i--) {
8464 +               pos = strict ? i - sp->len + 1 : 0;
8465 +               if (pos >= info->len)
8466 +                       return 0;
8467 +               e = &info->pol[pos];
8468 +
8469 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
8470 +                       if (!strict)
8471 +                               return 1;
8472 +               } else if (strict)
8473 +                       return 0;
8474 +       }
8475 +
8476 +       return strict ? 1 : 0;
8477 +}
8478 +
8479 +static int
8480 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
8481 +{
8482 +       const struct ipt_policy_elem *e;
8483 +       struct dst_entry *dst = skb->dst;
8484 +       int strict = info->flags & POLICY_MATCH_STRICT;
8485 +       int i, pos;
8486 +
8487 +       if (dst->xfrm == NULL)
8488 +               return -1;
8489 +
8490 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
8491 +               pos = strict ? i : 0;
8492 +               if (pos >= info->len)
8493 +                       return 0;
8494 +               e = &info->pol[pos];
8495 +
8496 +               if (match_xfrm_state(dst->xfrm, e)) {
8497 +                       if (!strict)
8498 +                               return 1;
8499 +               } else if (strict)
8500 +                       return 0;
8501 +       }
8502 +
8503 +       return strict ? 1 : 0;
8504 +}
8505 +
8506 +static int match(const struct sk_buff *skb,
8507 +                 const struct net_device *in,
8508 +                 const struct net_device *out,
8509 +                 const void *matchinfo, int offset, int *hotdrop)
8510 +{
8511 +       const struct ipt_policy_info *info = matchinfo;
8512 +       int ret;
8513 +
8514 +       if (info->flags & POLICY_MATCH_IN)
8515 +               ret = match_policy_in(skb, info);
8516 +       else
8517 +               ret = match_policy_out(skb, info);
8518 +
8519 +       if (ret < 0) {
8520 +               if (info->flags & POLICY_MATCH_NONE)
8521 +                       ret = 1;
8522 +               else
8523 +                       ret = 0;
8524 +       } else if (info->flags & POLICY_MATCH_NONE)
8525 +               ret = 0;
8526 +
8527 +       return ret;
8528 +}
8529 +
8530 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
8531 +                      void *matchinfo, unsigned int matchsize,
8532 +                      unsigned int hook_mask)
8533 +{
8534 +       struct ipt_policy_info *info = matchinfo;
8535 +
8536 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
8537 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
8538 +                      matchsize, IPT_ALIGN(sizeof(*info)));
8539 +               return 0;
8540 +       }
8541 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
8542 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
8543 +                               "outgoing policy selected\n");
8544 +               return 0;
8545 +       }
8546 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
8547 +           && info->flags & POLICY_MATCH_OUT) {
8548 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
8549 +                               "PRE_ROUTING and INPUT\n");
8550 +               return 0;
8551 +       }
8552 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
8553 +           && info->flags & POLICY_MATCH_IN) {
8554 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
8555 +                               "POST_ROUTING and OUTPUT\n");
8556 +               return 0;
8557 +       }
8558 +       if (info->len > POLICY_MAX_ELEM) {
8559 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
8560 +               return 0;
8561 +       }
8562 +
8563 +       return 1;
8564 +}
8565 +
8566 +static struct ipt_match policy_match =
8567 +{
8568 +       .name           = "policy",
8569 +       .match          = match,
8570 +       .checkentry     = checkentry,
8571 +       .me             = THIS_MODULE,
8572 +};
8573 +
8574 +static int __init init(void)
8575 +{
8576 +       return ipt_register_match(&policy_match);
8577 +}
8578 +
8579 +static void __exit fini(void)
8580 +{
8581 +       ipt_unregister_match(&policy_match);
8582 +}
8583 +
8584 +module_init(init);
8585 +module_exit(fini);
8586 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_rpc.c
8587 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_rpc.c    1970-01-01 01:00:00.000000000 +0100
8588 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_rpc.c        2004-04-16 09:18:44.000000000 +0200
8589 @@ -0,0 +1,428 @@
8590 +/* RPC extension for IP connection matching, Version 2.2
8591 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
8592 + *     - original rpc tracking module
8593 + *     - "recent" connection handling for kernel 2.3+ netfilter
8594 + *
8595 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
8596 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
8597 + *
8598 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
8599 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
8600 + *     - extended matching to support filtering on procedures
8601 + *
8602 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
8603 + *
8604 + *     This program is free software; you can redistribute it and/or
8605 + *     modify it under the terms of the GNU General Public License
8606 + *     as published by the Free Software Foundation; either version
8607 + *     2 of the License, or (at your option) any later version.
8608 + **
8609 + *     Module load syntax:
8610 + *     insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
8611 + *
8612 + *     Please give the ports of all RPC servers you wish to connect to.
8613 + *     If you don't specify ports, the default will be port 111.
8614 + **
8615 + *     Note to all:
8616 + *
8617 + *     RPCs should not be exposed to the internet - ask the Pentagon;
8618 + *
8619 + *       "The unidentified crackers pleaded guilty in July to charges
8620 + *        of juvenile delinquency stemming from a string of Pentagon
8621 + *        network intrusions in February.
8622 + *
8623 + *        The youths, going by the names TooShort and Makaveli, used
8624 + *        a common server security hole to break in, according to
8625 + *        Dane Jasper, owner of the California Internet service
8626 + *        provider, Sonic. They used the hole, known as the 'statd'
8627 + *        exploit, to attempt more than 800 break-ins, Jasper said."
8628 + *
8629 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
8630 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
8631 + **
8632 + */
8633 +
8634 +#include <linux/module.h>
8635 +#include <linux/skbuff.h>
8636 +#include <linux/list.h>
8637 +#include <linux/udp.h>
8638 +#include <linux/tcp.h>
8639 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8640 +#include <linux/netfilter_ipv4/ip_tables.h>
8641 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
8642 +#include <linux/netfilter_ipv4/lockhelp.h>
8643 +#include <linux/netfilter_ipv4/ipt_rpc.h>
8644 +
8645 +#define MAX_PORTS 8
8646 +static int ports[MAX_PORTS];
8647 +static int ports_n_c = 0;
8648 +
8649 +#ifdef MODULE_PARM
8650 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8651 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
8652 +#endif
8653 +
8654 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
8655 +MODULE_DESCRIPTION("RPC connection matching module");
8656 +MODULE_LICENSE("GPL");
8657 +
8658 +#if 0
8659 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
8660 +                                       format, ## args)
8661 +#else
8662 +#define DEBUGP(format, args...)
8663 +#endif
8664 +
8665 +EXPORT_NO_SYMBOLS;
8666 +
8667 +/* vars from ip_conntrack_rpc_tcp */
8668 +extern struct list_head request_p_list_tcp;
8669 +extern struct module *ip_conntrack_rpc_tcp;
8670 +
8671 +/* vars from ip_conntrack_rpc_udp */
8672 +extern struct list_head request_p_list_udp;
8673 +extern struct module *ip_conntrack_rpc_udp;
8674 +
8675 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
8676 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
8677 +
8678 +#define ASSERT_READ_LOCK(x)                                    \
8679 +do {                                                           \
8680 +       if (x == &request_p_list_udp)                           \
8681 +               MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);        \
8682 +       else if (x == &request_p_list_tcp)                      \
8683 +               MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);        \
8684 +} while (0)
8685 +
8686 +#define ASSERT_WRITE_LOCK(x)                                   \
8687 +do {                                                           \
8688 +       if (x == &request_p_list_udp)                           \
8689 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);       \
8690 +       else if (x == &request_p_list_tcp)                      \
8691 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);       \
8692 +} while (0)
8693 +
8694 +#include <linux/netfilter_ipv4/listhelp.h>
8695 +
8696 +const int IPT_RPC_CHAR_LEN = 11;
8697 +
8698 +
8699 +static int k_atoi(char *string)
8700 +{
8701 +       unsigned int result = 0;
8702 +       int maxoctet = IPT_RPC_CHAR_LEN;
8703 +
8704 +       for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
8705 +               if (*string < 0)
8706 +                       return(0);
8707 +               if (*string == 0)
8708 +                       break;
8709 +               if (*string < 48 || *string > 57) {
8710 +                       return(0);
8711 +               }
8712 +               result = result * 10 + ( *string - 48 );
8713 +       }
8714 +       return(result);
8715 +}
8716 +
8717 +
8718 +static int match_rpcs(char *c_procs, int i_procs, int proc)
8719 +{
8720 +       int   proc_ctr;
8721 +       char *proc_ptr;
8722 +       unsigned int proc_num;
8723 +
8724 +       DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
8725 +
8726 +       if (i_procs == -1)
8727 +               return 1;
8728 +
8729 +       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
8730 +
8731 +               proc_ptr = c_procs;
8732 +               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
8733 +               proc_num = k_atoi(proc_ptr);
8734 +
8735 +               if (proc_num == proc)
8736 +                       return 1;
8737 +       }
8738 +
8739 +       return 0;
8740 +}
8741 +
8742 +
8743 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
8744 +                       int *hotdrop, int dir, struct ip_conntrack *ct,
8745 +                       int offset, struct list_head request_p_list)
8746 +{
8747 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
8748 +       struct request_p *req_p;
8749 +       u_int32_t xid;
8750 +
8751 +
8752 +       /* Get XID */
8753 +       xid = *data;
8754 +
8755 +       /* This does sanity checking on RPC payloads,
8756 +        * and permits only the RPC "get port" (3)
8757 +        * in authorised procedures in client
8758 +        * communications with the portmapper.
8759 +        */
8760 +
8761 +       data += 5;
8762 +
8763 +       /* Get RPC requestor */
8764 +       if (IXDR_GET_INT32(data) != 3) {
8765 +               DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
8766 +               if(rpcinfo->strict == 1)
8767 +                       *hotdrop = 1;
8768 +               return 0;
8769 +       }
8770 +       DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
8771 +
8772 +       data++;
8773 +
8774 +       /* Jump Credentials and Verfifier */
8775 +       data = data + IXDR_GET_INT32(data) + 2;
8776 +       data = data + IXDR_GET_INT32(data) + 2;
8777 +
8778 +       /* Get RPC procedure */
8779 +       if (match_rpcs((char *)&rpcinfo->c_procs,
8780 +           rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
8781 +               DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
8782 +                       (unsigned int)IXDR_GET_INT32(data));
8783 +
8784 +               /* If the RPC conntrack half entry already exists .. */
8785 +
8786 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
8787 +                       case IPPROTO_UDP:
8788 +                               WRITE_LOCK(&ipct_rpc_udp_lock);
8789 +                       case IPPROTO_TCP:
8790 +                               WRITE_LOCK(&ipct_rpc_tcp_lock);
8791 +               }
8792 +               req_p = LIST_FIND(&request_p_list, request_p_cmp,
8793 +                                 struct request_p *, xid,
8794 +                                 ct->tuplehash[dir].tuple.src.ip,
8795 +                                 ct->tuplehash[dir].tuple.src.u.all);
8796 +
8797 +               if (req_p) {
8798 +                       DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
8799 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
8800 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
8801 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
8802 +
8803 +                       /* .. remove it */
8804 +                       if (del_timer(&req_p->timeout))
8805 +                               req_p->timeout.expires = 0;
8806 +
8807 +                               LIST_DELETE(&request_p_list, req_p);
8808 +                       DEBUGP("RPC req_p removed. [done]\n");
8809 +
8810 +               } else {
8811 +                       DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
8812 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
8813 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
8814 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
8815 +
8816 +               }
8817 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
8818 +                       case IPPROTO_UDP:
8819 +                               WRITE_UNLOCK(&ipct_rpc_udp_lock);
8820 +                       case IPPROTO_TCP:
8821 +                               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8822 +               }
8823 +
8824 +               if(rpcinfo->strict == 1)
8825 +                       *hotdrop = 1;
8826 +               return 0;
8827 +       }
8828 +
8829 +       DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
8830 +               (unsigned int)IXDR_GET_INT32(data));
8831 +       return (1 && (!offset));
8832 +}
8833 +
8834 +
8835 +static int match(const struct sk_buff *skb, const struct net_device *in,
8836 +                const struct net_device *out, const void *matchinfo,
8837 +                int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
8838 +{
8839 +       struct ip_conntrack *ct;
8840 +       enum ip_conntrack_info ctinfo;
8841 +       const u_int32_t *data;
8842 +       enum ip_conntrack_dir dir;
8843 +       const struct tcphdr *tcp;
8844 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
8845 +       int port, portsok;
8846 +       int tval;
8847 +
8848 +
8849 +       DEBUGP("new packet to evaluate ..\n");
8850 +
8851 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
8852 +       if (!ct) {
8853 +               DEBUGP("no ct available [skip]\n");
8854 +               return 0;
8855 +       }
8856 +
8857 +       DEBUGP("ct detected. [cont]\n");
8858 +       dir = CTINFO2DIR(ctinfo);
8859 +
8860 +       /* we only want the client to server packets for matching */
8861 +       if (dir != IP_CT_DIR_ORIGINAL)
8862 +               return 0;
8863 +
8864 +       /* This does sanity checking on UDP or TCP packets,
8865 +        * like their respective modules.
8866 +        */
8867 +
8868 +       switch (ct->tuplehash[0].tuple.dst.protonum) {
8869 +
8870 +               case IPPROTO_UDP:
8871 +                       DEBUGP("PROTO_UDP [cont]\n");
8872 +                       if (offset == 0 && datalen < sizeof(struct udphdr)) {
8873 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
8874 +                               return 0;
8875 +                       }
8876 +
8877 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
8878 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
8879 +                                       portsok++;
8880 +                                       break;
8881 +                               }
8882 +                       }
8883 +                       if (portsok == 0) {
8884 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
8885 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
8886 +                               return 0;
8887 +                       }
8888 +
8889 +                       if ((datalen - sizeof(struct udphdr)) != 56) {
8890 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
8891 +                               if (rpcinfo->strict == 1)
8892 +                                       *hotdrop = 1;
8893 +                               return 0;
8894 +                       }
8895 +                       DEBUGP("packet length is correct. [cont]\n");
8896 +
8897 +                       /* Get to the data */
8898 +                       data = (const u_int32_t *)hdr + 2;
8899 +
8900 +                       /* Check the RPC data */
8901 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
8902 +                                               dir, ct, offset,
8903 +                                               request_p_list_udp);
8904 +
8905 +                       return tval;
8906 +                       
8907 +               
8908 +               case IPPROTO_TCP:
8909 +                       DEBUGP("PROTO_TCP [cont]\n");
8910 +                       if (offset == 0 && datalen < sizeof(struct tcphdr)) {
8911 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
8912 +                               return 0;
8913 +                       }
8914 +       
8915 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
8916 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
8917 +                                       portsok++;
8918 +                                       break;
8919 +                               }
8920 +                       }
8921 +                       if (portsok == 0) {
8922 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
8923 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
8924 +                               return 0;
8925 +                       }
8926 +
8927 +                       tcp = hdr;
8928 +                       if (datalen == (tcp->doff * 4)) {
8929 +                               DEBUGP("packet does not contain any data. [match]\n");
8930 +                               return (1 && (!offset));
8931 +                       }
8932 +
8933 +                       /* Tests if packet len is ok */
8934 +                       if ((datalen - (tcp->doff * 4)) != 60) {
8935 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
8936 +                               if(rpcinfo->strict == 1)
8937 +                                       *hotdrop = 1;
8938 +                               return 0;
8939 +                       }
8940 +                       DEBUGP("packet length is correct. [cont]\n");
8941 +
8942 +                       /* Get to the data */
8943 +                       data = (const u_int32_t *)tcp + tcp->doff + 1;  
8944 +
8945 +                       /* Check the RPC data */
8946 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
8947 +                                               dir, ct, offset,
8948 +                                               request_p_list_tcp);
8949 +
8950 +                       return tval;
8951 +
8952 +       }
8953 +
8954 +       DEBUGP("transport protocol=%u, is not supported [skip]\n",
8955 +               ct->tuplehash[0].tuple.dst.protonum);
8956 +       return 0;
8957 +}
8958 +
8959 +
8960 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
8961 +                  unsigned int matchsize, unsigned int hook_mask)
8962 +{
8963 +       if (hook_mask
8964 +           & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
8965 +               | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
8966 +               printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
8967 +               return 0;
8968 +       }
8969 +
8970 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
8971 +               return 0;
8972 +
8973 +       return 1;
8974 +}
8975 +
8976 +
8977 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
8978 +                                       &match, &checkentry, NULL,
8979 +                                       THIS_MODULE };
8980 +
8981 +
8982 +static int __init init(void)
8983 +{
8984 +       int port;
8985 +
8986 +       DEBUGP("incrementing usage counts\n");
8987 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
8988 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
8989 +
8990 +       /* If no port given, default to standard RPC port */
8991 +       if (ports[0] == 0)
8992 +               ports[0] = RPC_PORT;
8993 +
8994 +       DEBUGP("registering match [%s] for;\n", rpc_match.name);
8995 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
8996 +               DEBUGP("  port %i (UDP|TCP);\n", ports[port]);
8997 +               ports_n_c++;
8998 +       }
8999 +       
9000 +       return ipt_register_match(&rpc_match);
9001 +}
9002 +
9003 +
9004 +static void fini(void)
9005 +{
9006 +       DEBUGP("unregistering match\n");
9007 +       ipt_unregister_match(&rpc_match);
9008 +
9009 +       DEBUGP("decrementing usage counts\n");
9010 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
9011 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
9012 +}
9013 +
9014 +
9015 +module_init(init);
9016 +module_exit(fini);
9017 +
9018 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_string.c
9019 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
9020 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_string.c     2004-04-16 09:19:37.000000000 +0200
9021 @@ -0,0 +1,218 @@
9022 +/* Kernel module to match a string into a packet.
9023 + *
9024 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
9025 + * 
9026 + * ChangeLog
9027 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
9028 + *             Fixed SMP re-entrancy problem using per-cpu data areas
9029 + *             for the skip/shift tables.
9030 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
9031 + *             Fixed kernel panic, due to overrunning boyer moore string
9032 + *             tables. Also slightly tweaked heuristic for deciding what
9033 + *             search algo to use.
9034 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
9035 + *             Implemented Boyer Moore Sublinear search algorithm
9036 + *             alongside the existing linear search based on memcmp().
9037 + *             Also a quick check to decide which method to use on a per
9038 + *             packet basis.
9039 + */
9040 +
9041 +#include <linux/smp.h>
9042 +#include <linux/module.h>
9043 +#include <linux/skbuff.h>
9044 +#include <linux/file.h>
9045 +#include <net/sock.h>
9046 +
9047 +#include <linux/netfilter_ipv4/ip_tables.h>
9048 +#include <linux/netfilter_ipv4/ipt_string.h>
9049 +
9050 +MODULE_LICENSE("GPL");
9051 +
9052 +struct string_per_cpu {
9053 +       int *skip;
9054 +       int *shift;
9055 +       int *len;
9056 +};
9057 +
9058 +struct string_per_cpu *bm_string_data=NULL;
9059 +
9060 +/* Boyer Moore Sublinear string search - VERY FAST */
9061 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
9062 +{
9063 +       int M1, right_end, sk, sh;  
9064 +       int ended, j, i;
9065 +
9066 +       int *skip, *shift, *len;
9067 +       
9068 +       /* use data suitable for this CPU */
9069 +       shift=bm_string_data[smp_processor_id()].shift;
9070 +       skip=bm_string_data[smp_processor_id()].skip;
9071 +       len=bm_string_data[smp_processor_id()].len;
9072 +       
9073 +       /* Setup skip/shift tables */
9074 +       M1 = right_end = needle_len-1;
9075 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
9076 +       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
9077 +
9078 +       for (i = 1; i < needle_len; i++) {   
9079 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
9080 +               len[i] = j;  
9081 +       }  
9082 +
9083 +       shift[0] = 1;  
9084 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
9085 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
9086 +       ended = 0;  
9087 +       
9088 +       for (i = 0; i < needle_len; i++) {  
9089 +               if (len[i] == M1 - i) ended = i;  
9090 +               if (ended) shift[i] = ended;  
9091 +       }  
9092 +
9093 +       /* Do the search*/  
9094 +       while (right_end < haystack_len)
9095 +       {
9096 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
9097 +               if (i == needle_len) {
9098 +                       return haystack+(right_end - M1);
9099 +               }
9100 +               
9101 +               sk = skip[haystack[right_end - i]];  
9102 +               sh = shift[i];
9103 +               right_end = max(right_end - i + sk, right_end + sh);  
9104 +       }
9105 +
9106 +       return NULL;
9107 +}  
9108 +
9109 +/* Linear string search based on memcmp() */
9110 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
9111 +{
9112 +       char *k = haystack + (haystack_len-needle_len);
9113 +       char *t = haystack;
9114 +       
9115 +       while ( t <= k ) {
9116 +               if (memcmp(t, needle, needle_len) == 0)
9117 +                       return t;
9118 +               t++;
9119 +       }
9120 +
9121 +       return NULL;
9122 +}
9123 +
9124 +
9125 +static int
9126 +match(const struct sk_buff *skb,
9127 +      const struct net_device *in,
9128 +      const struct net_device *out,
9129 +      const void *matchinfo,
9130 +      int offset,
9131 +      const void *hdr,
9132 +      u_int16_t datalen,
9133 +      int *hotdrop)
9134 +{
9135 +       const struct ipt_string_info *info = matchinfo;
9136 +       struct iphdr *ip = skb->nh.iph;
9137 +       int hlen, nlen;
9138 +       char *needle, *haystack;
9139 +       proc_ipt_search search=search_linear;
9140 +
9141 +       if ( !ip ) return 0;
9142 +
9143 +       /* get lenghts, and validate them */
9144 +       nlen=info->len;
9145 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
9146 +       if ( nlen > hlen ) return 0;
9147 +
9148 +       needle=(char *)&info->string;
9149 +       haystack=(char *)ip+(ip->ihl*4);
9150 +
9151 +       /* The sublinear search comes in to its own
9152 +        * on the larger packets */
9153 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
9154 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
9155 +               if ( hlen < BM_MAX_HLEN ) {
9156 +                       search=search_sublinear;
9157 +               }else{
9158 +                       if (net_ratelimit())
9159 +                               printk(KERN_INFO "ipt_string: Packet too big "
9160 +                                       "to attempt sublinear string search "
9161 +                                       "(%d bytes)\n", hlen );
9162 +               }
9163 +       }
9164 +       
9165 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
9166 +}
9167 +
9168 +static int
9169 +checkentry(const char *tablename,
9170 +           const struct ipt_ip *ip,
9171 +           void *matchinfo,
9172 +           unsigned int matchsize,
9173 +           unsigned int hook_mask)
9174 +{
9175 +
9176 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
9177 +               return 0;
9178 +
9179 +       return 1;
9180 +}
9181 +
9182 +void string_freeup_data(void)
9183 +{
9184 +       int c;
9185 +       
9186 +       if ( bm_string_data ) {
9187 +               for(c=0; c<smp_num_cpus; c++) {
9188 +                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
9189 +                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
9190 +                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
9191 +               }
9192 +               kfree(bm_string_data);
9193 +       }
9194 +}
9195 +
9196 +static struct ipt_match string_match
9197 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
9198 +
9199 +static int __init init(void)
9200 +{
9201 +       int c;
9202 +       size_t tlen;
9203 +       size_t alen;
9204 +
9205 +       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
9206 +       alen=sizeof(int)*BM_MAX_HLEN;
9207 +       
9208 +       /* allocate array of structures */
9209 +       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
9210 +               return 0;
9211 +       }
9212 +       
9213 +       memset(bm_string_data, 0, tlen);
9214 +       
9215 +       /* allocate our skip/shift tables */
9216 +       for(c=0; c<smp_num_cpus; c++) {
9217 +               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
9218 +                       goto alloc_fail;
9219 +               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
9220 +                       goto alloc_fail;
9221 +               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
9222 +                       goto alloc_fail;
9223 +       }
9224 +       
9225 +       return ipt_register_match(&string_match);
9226 +
9227 +alloc_fail:
9228 +       string_freeup_data();
9229 +       return 0;
9230 +}
9231 +
9232 +static void __exit fini(void)
9233 +{
9234 +       ipt_unregister_match(&string_match);
9235 +       string_freeup_data();
9236 +}
9237 +
9238 +module_init(init);
9239 +module_exit(fini);
9240 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_unclean.c
9241 --- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_unclean.c        1970-01-01 01:00:00.000000000 +0100
9242 +++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_unclean.c    2004-04-16 09:19:34.000000000 +0200
9243 @@ -0,0 +1,604 @@
9244 +/* Kernel module to match suspect packets. */
9245 +#include <linux/module.h>
9246 +#include <linux/skbuff.h>
9247 +#include <linux/ip.h>
9248 +#include <linux/udp.h>
9249 +#include <linux/tcp.h>
9250 +#include <linux/icmp.h>
9251 +#include <net/checksum.h>
9252 +
9253 +#include <linux/netfilter_ipv4/ip_tables.h>
9254 +
9255 +#define limpk(format, args...)                                          \
9256 +do {                                                                    \
9257 +       if (net_ratelimit())                                             \
9258 +               printk("ipt_unclean: %s" format,                         \
9259 +                      embedded ? "(embedded packet) " : "" , ## args);  \
9260 +} while(0)
9261 +
9262 +enum icmp_error_status
9263 +{
9264 +       ICMP_MAY_BE_ERROR,
9265 +       ICMP_IS_ERROR,
9266 +       ICMP_NOT_ERROR
9267 +};
9268 +
9269 +struct icmp_info
9270 +{
9271 +       size_t min_len, max_len;
9272 +       enum icmp_error_status err;
9273 +       u_int8_t min_code, max_code;
9274 +};
9275 +
9276 +static int
9277 +check_ip(struct iphdr *iph, size_t length, int embedded);
9278 +
9279 +/* ICMP-specific checks. */
9280 +static int
9281 +check_icmp(const struct icmphdr *icmph,
9282 +          u_int16_t datalen,
9283 +          unsigned int offset,
9284 +          int more_frags,
9285 +          int embedded)
9286 +{
9287 +       static struct icmp_info info[]
9288 +               = { [ICMP_ECHOREPLY]
9289 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
9290 +                   [ICMP_DEST_UNREACH]
9291 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
9292 +                   [ICMP_SOURCE_QUENCH]
9293 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
9294 +                   [ICMP_REDIRECT]
9295 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
9296 +                   [ICMP_ECHO]
9297 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0  },
9298 +                   /* Router advertisement. */
9299 +                   [9]
9300 +                   = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
9301 +                   /* Router solicitation. */
9302 +                   [10]
9303 +                   = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
9304 +                   [ICMP_TIME_EXCEEDED]
9305 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1  },
9306 +                   [ICMP_PARAMETERPROB]
9307 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
9308 +                   [ICMP_TIMESTAMP]
9309 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
9310 +                   [ICMP_TIMESTAMPREPLY]
9311 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
9312 +                   [ICMP_INFO_REQUEST]
9313 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
9314 +                   [ICMP_INFO_REPLY]
9315 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
9316 +                   [ICMP_ADDRESS]
9317 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
9318 +                   [ICMP_ADDRESSREPLY]
9319 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
9320 +
9321 +       /* Can't do anything if it's a fragment. */
9322 +       if (offset)
9323 +               return 1;
9324 +
9325 +       /* Must cover type and code. */
9326 +       if (datalen < 2) {
9327 +               limpk("ICMP len=%u too short\n", datalen);
9328 +               return 0;
9329 +       }
9330 +
9331 +       /* If not embedded. */
9332 +       if (!embedded) {
9333 +               /* Bad checksum?  Don't print, just ignore. */
9334 +               if (!more_frags
9335 +                   && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
9336 +                       return 0;
9337 +
9338 +               /* CHECK: Truncated ICMP (even if first fragment). */
9339 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9340 +                   && info[icmph->type].min_len != 0
9341 +                   && datalen < info[icmph->type].min_len) {
9342 +                       limpk("ICMP type %u len %u too short\n",
9343 +                             icmph->type, datalen);
9344 +                       return 0;
9345 +               }
9346 +
9347 +               /* CHECK: Check within known error ICMPs. */
9348 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9349 +                   && info[icmph->type].err == ICMP_IS_ERROR) {
9350 +                       /* CHECK: Embedded packet must be at least
9351 +                          length of iph + 8 bytes. */
9352 +                       struct iphdr *inner = (void *)icmph + 8;
9353 +
9354 +                       /* datalen > 8 since all ICMP_IS_ERROR types
9355 +                           have min length > 8 */
9356 +                       if (datalen - 8 < sizeof(struct iphdr)) {
9357 +                               limpk("ICMP error internal way too short\n");
9358 +                               return 0;
9359 +                       }
9360 +                       if (datalen - 8 < inner->ihl*4 + 8) {
9361 +                               limpk("ICMP error internal too short\n");
9362 +                               return 0;
9363 +                       }
9364 +                       if (!check_ip(inner, datalen - 8, 1))
9365 +                               return 0;
9366 +               }
9367 +       } else {
9368 +               /* CHECK: Can't embed ICMP unless known non-error. */
9369 +               if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
9370 +                   || info[icmph->type].err != ICMP_NOT_ERROR) {
9371 +                       limpk("ICMP type %u not embeddable\n",
9372 +                             icmph->type);
9373 +                       return 0;
9374 +               }
9375 +       }
9376 +
9377 +       /* CHECK: Invalid ICMP codes. */
9378 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9379 +           && (icmph->code < info[icmph->type].min_code
9380 +               || icmph->code > info[icmph->type].max_code)) {
9381 +               limpk("ICMP type=%u code=%u\n",
9382 +                     icmph->type, icmph->code);
9383 +               return 0;
9384 +       }
9385 +
9386 +       /* CHECK: Above maximum length. */
9387 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
9388 +           && info[icmph->type].max_len != 0
9389 +           && datalen > info[icmph->type].max_len) {
9390 +               limpk("ICMP type=%u too long: %u bytes\n",
9391 +                     icmph->type, datalen);
9392 +               return 0;
9393 +       }
9394 +
9395 +       switch (icmph->type) {
9396 +       case ICMP_PARAMETERPROB: {
9397 +               /* CHECK: Problem param must be within error packet's
9398 +                * IP header. */
9399 +               struct iphdr *iph = (void *)icmph + 8;
9400 +               u_int32_t arg = ntohl(icmph->un.gateway);
9401 +
9402 +               if (icmph->code == 0) {
9403 +                       /* Code 0 means that upper 8 bits is pointer
9404 +                           to problem. */
9405 +                       if ((arg >> 24) >= iph->ihl*4) {
9406 +                               limpk("ICMP PARAMETERPROB ptr = %u\n",
9407 +                                     ntohl(icmph->un.gateway) >> 24);
9408 +                               return 0;
9409 +                       }
9410 +                       arg &= 0x00FFFFFF;
9411 +               }
9412 +
9413 +               /* CHECK: Rest must be zero. */
9414 +               if (arg) {
9415 +                       limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
9416 +                             arg);
9417 +                       return 0;
9418 +               }
9419 +               break;
9420 +       }
9421 +
9422 +       case ICMP_TIME_EXCEEDED:
9423 +       case ICMP_SOURCE_QUENCH:
9424 +               /* CHECK: Unused must be zero. */
9425 +               if (icmph->un.gateway != 0) {
9426 +                       limpk("ICMP type=%u unused = %u\n",
9427 +                             icmph->type, ntohl(icmph->un.gateway));
9428 +                       return 0;
9429 +               }
9430 +               break;
9431 +       }
9432 +
9433 +       return 1;
9434 +}
9435 +
9436 +/* UDP-specific checks. */
9437 +static int
9438 +check_udp(const struct iphdr *iph,
9439 +         const struct udphdr *udph,
9440 +         u_int16_t datalen,
9441 +         unsigned int offset,
9442 +         int more_frags,
9443 +         int embedded)
9444 +{
9445 +       /* Can't do anything if it's a fragment. */
9446 +       if (offset)
9447 +               return 1;
9448 +
9449 +       /* CHECK: Must cover UDP header. */
9450 +       if (datalen < sizeof(struct udphdr)) {
9451 +               limpk("UDP len=%u too short\n", datalen);
9452 +               return 0;
9453 +       }
9454 +
9455 +       /* Bad checksum?  Don't print, just say it's unclean. */
9456 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
9457 +       if (!more_frags && !embedded && udph->check
9458 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
9459 +                                csum_partial((char *)udph, datalen, 0)) != 0)
9460 +               return 0;
9461 +
9462 +       /* CHECK: Destination port can't be zero. */
9463 +       if (!udph->dest) {
9464 +               limpk("UDP zero destination port\n");
9465 +               return 0;
9466 +       }
9467 +
9468 +       if (!more_frags) {
9469 +               if (!embedded) {
9470 +                       /* CHECK: UDP length must match. */
9471 +                       if (ntohs(udph->len) != datalen) {
9472 +                               limpk("UDP len too short %u vs %u\n",
9473 +                                     ntohs(udph->len), datalen);
9474 +                               return 0;
9475 +                       }
9476 +               } else {
9477 +                       /* CHECK: UDP length be >= this truncated pkt. */
9478 +                       if (ntohs(udph->len) < datalen) {
9479 +                               limpk("UDP len too long %u vs %u\n",
9480 +                                     ntohs(udph->len), datalen);
9481 +                               return 0;
9482 +                       }
9483 +               }
9484 +       } else {
9485 +               /* CHECK: UDP length must be > this frag's length. */
9486 +               if (ntohs(udph->len) <= datalen) {
9487 +                       limpk("UDP fragment len too short %u vs %u\n",
9488 +                             ntohs(udph->len), datalen);
9489 +                       return 0;
9490 +               }
9491 +       }
9492 +
9493 +       return 1;
9494 +}
9495 +
9496 +#define        TH_FIN  0x01
9497 +#define        TH_SYN  0x02
9498 +#define        TH_RST  0x04
9499 +#define        TH_PUSH 0x08
9500 +#define        TH_ACK  0x10
9501 +#define        TH_URG  0x20
9502 +#define        TH_ECE  0x40
9503 +#define        TH_CWR  0x80
9504 +
9505 +/* table of valid flag combinations - ECE and CWR are always valid */
9506 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
9507 +{
9508 +       [TH_SYN]                        = 1,
9509 +       [TH_SYN|TH_ACK]                 = 1,
9510 +       [TH_RST]                        = 1,
9511 +       [TH_RST|TH_ACK]                 = 1,
9512 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
9513 +       [TH_FIN|TH_ACK]                 = 1,
9514 +       [TH_ACK]                        = 1,
9515 +       [TH_ACK|TH_PUSH]                = 1,
9516 +       [TH_ACK|TH_URG]                 = 1,
9517 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
9518 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
9519 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
9520 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
9521 +};
9522 +
9523 +/* TCP-specific checks. */
9524 +static int
9525 +check_tcp(const struct iphdr *iph,
9526 +         const struct tcphdr *tcph,
9527 +         u_int16_t datalen,
9528 +         unsigned int offset,
9529 +         int more_frags,
9530 +         int embedded)
9531 +{
9532 +       u_int8_t *opt = (u_int8_t *)tcph;
9533 +       u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
9534 +       u_int8_t tcpflags;
9535 +       int end_of_options = 0;
9536 +       size_t i;
9537 +
9538 +       /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
9539 +       /* In fact, this is caught below (offset < 516). */
9540 +
9541 +       /* Can't do anything if it's a fragment. */
9542 +       if (offset)
9543 +               return 1;
9544 +
9545 +       /* CHECK: Smaller than minimal TCP hdr. */
9546 +       if (datalen < sizeof(struct tcphdr)) {
9547 +               if (!embedded) {
9548 +                       limpk("Packet length %u < TCP header.\n", datalen);
9549 +                       return 0;
9550 +               }
9551 +               /* Must have ports available (datalen >= 8), from
9552 +                   check_icmp which set embedded = 1 */
9553 +               /* CHECK: TCP ports inside ICMP error */
9554 +               if (!tcph->source || !tcph->dest) {
9555 +                       limpk("Zero TCP ports %u/%u.\n",
9556 +                             htons(tcph->source), htons(tcph->dest));
9557 +                       return 0;
9558 +               }
9559 +               return 1;
9560 +       }
9561 +
9562 +       /* CHECK: Smaller than actual TCP hdr. */
9563 +       if (datalen < tcph->doff * 4) {
9564 +               if (!embedded) {
9565 +                       limpk("Packet length %u < actual TCP header.\n",
9566 +                             datalen);
9567 +                       return 0;
9568 +               } else
9569 +                       return 1;
9570 +       }
9571 +
9572 +       /* Bad checksum?  Don't print, just say it's unclean. */
9573 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
9574 +       if (!more_frags && !embedded
9575 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
9576 +                                csum_partial((char *)tcph, datalen, 0)) != 0)
9577 +               return 0;
9578 +
9579 +       /* CHECK: TCP ports non-zero */
9580 +       if (!tcph->source || !tcph->dest) {
9581 +               limpk("Zero TCP ports %u/%u.\n",
9582 +                     htons(tcph->source), htons(tcph->dest));
9583 +               return 0;
9584 +       }
9585 +
9586 +       /* CHECK: TCP reserved bits zero. */
9587 +       if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
9588 +               limpk("TCP reserved bits not zero\n");
9589 +               return 0;
9590 +       }
9591 +
9592 +       /* CHECK: TCP flags. */
9593 +       tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
9594 +       if (!tcp_valid_flags[tcpflags]) {
9595 +               limpk("TCP flags bad: %u\n", tcpflags);
9596 +               return 0;
9597 +       }
9598 +
9599 +       for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
9600 +               switch (opt[i]) {
9601 +               case 0:
9602 +                       end_of_options = 1;
9603 +                       i++;
9604 +                       break;
9605 +               case 1:
9606 +                       i++;
9607 +                       break;
9608 +               default:
9609 +                       /* CHECK: options after EOO. */
9610 +                       if (end_of_options) {
9611 +                               limpk("TCP option %u after end\n",
9612 +                                     opt[i]);
9613 +                               return 0;
9614 +                       }
9615 +                       /* CHECK: options at tail. */
9616 +                       else if (i+1 >= tcph->doff * 4) {
9617 +                               limpk("TCP option %u at tail\n",
9618 +                                     opt[i]);
9619 +                               return 0;
9620 +                       }
9621 +                       /* CHECK: zero-length options. */
9622 +                       else if (opt[i+1] == 0) {
9623 +                               limpk("TCP option %u 0 len\n",
9624 +                                     opt[i]);
9625 +                               return 0;
9626 +                       }
9627 +                       /* CHECK: oversize options. */
9628 +                       else if (&opt[i] + opt[i+1] > endhdr) {
9629 +                               limpk("TCP option %u at %Zu too long\n",
9630 +                                     (unsigned int) opt[i], i);
9631 +                               return 0;
9632 +                       }
9633 +                       /* Move to next option */
9634 +                       i += opt[i+1];
9635 +               }
9636 +       }
9637 +
9638 +       return 1;
9639 +}
9640 +
9641 +/* Returns 1 if ok */
9642 +/* Standard IP checks. */
9643 +static int
9644 +check_ip(struct iphdr *iph, size_t length, int embedded)
9645 +{
9646 +       u_int8_t *opt = (u_int8_t *)iph;
9647 +       u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
9648 +       int end_of_options = 0;
9649 +       void *protoh;
9650 +       size_t datalen;
9651 +       unsigned int i;
9652 +       unsigned int offset;
9653 +
9654 +       /* Should only happen for local outgoing raw-socket packets. */
9655 +       /* CHECK: length >= ip header. */
9656 +       if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
9657 +               limpk("Packet length %Zu < IP header.\n", length);
9658 +               return 0;
9659 +       }
9660 +
9661 +       offset = ntohs(iph->frag_off) & IP_OFFSET;
9662 +       protoh = (void *)iph + iph->ihl * 4;
9663 +       datalen = length - iph->ihl * 4;
9664 +
9665 +       /* CHECK: Embedded fragment. */
9666 +       if (embedded && offset) {
9667 +               limpk("Embedded fragment.\n");
9668 +               return 0;
9669 +       }
9670 +
9671 +       for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
9672 +               switch (opt[i]) {
9673 +               case 0:
9674 +                       end_of_options = 1;
9675 +                       i++;
9676 +                       break;
9677 +               case 1:
9678 +                       i++;
9679 +                       break;
9680 +               default:
9681 +                       /* CHECK: options after EOO. */
9682 +                       if (end_of_options) {
9683 +                               limpk("IP option %u after end\n",
9684 +                                     opt[i]);
9685 +                               return 0;
9686 +                       }
9687 +                       /* CHECK: options at tail. */
9688 +                       else if (i+1 >= iph->ihl * 4) {
9689 +                               limpk("IP option %u at tail\n",
9690 +                                     opt[i]);
9691 +                               return 0;
9692 +                       }
9693 +                       /* CHECK: zero-length or one-length options. */
9694 +                       else if (opt[i+1] < 2) {
9695 +                               limpk("IP option %u %u len\n",
9696 +                                     opt[i], opt[i+1]);
9697 +                               return 0;
9698 +                       }
9699 +                       /* CHECK: oversize options. */
9700 +                       else if (&opt[i] + opt[i+1] > endhdr) {
9701 +                               limpk("IP option %u at %u too long\n",
9702 +                                     opt[i], i);
9703 +                               return 0;
9704 +                       }
9705 +                       /* Move to next option */
9706 +                       i += opt[i+1];
9707 +               }
9708 +       }
9709 +
9710 +       /* Fragment checks. */
9711 +
9712 +       /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
9713 +       if ((ntohs(iph->frag_off) & IP_MF)
9714 +           && (ntohs(iph->tot_len) % 8) != 0) {
9715 +               limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
9716 +               return 0;
9717 +       }
9718 +
9719 +       /* CHECK: Oversize fragment a-la Ping of Death. */
9720 +       if (offset * 8 + datalen > 65535) {
9721 +               limpk("Oversize fragment to %u.\n", offset * 8);
9722 +               return 0;
9723 +       }
9724 +
9725 +       /* CHECK: DF set and offset or MF set. */
9726 +       if ((ntohs(iph->frag_off) & IP_DF)
9727 +           && (offset || (ntohs(iph->frag_off) & IP_MF))) {
9728 +               limpk("DF set and offset=%u, MF=%u.\n",
9729 +                     offset, ntohs(iph->frag_off) & IP_MF);
9730 +               return 0;
9731 +       }
9732 +
9733 +       /* CHECK: Zero-sized fragments. */
9734 +       if ((offset || (ntohs(iph->frag_off) & IP_MF))
9735 +           && datalen == 0) {
9736 +               limpk("Zero size fragment offset=%u\n", offset);
9737 +               return 0;
9738 +       }
9739 +
9740 +       /* Note: we can have even middle fragments smaller than this:
9741 +          consider a large packet passing through a 600MTU then
9742 +          576MTU link: this gives a fragment of 24 data bytes.  But
9743 +          everyone packs fragments largest first, hence a fragment
9744 +          can't START before 576 - MAX_IP_HEADER_LEN. */
9745 +
9746 +       /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
9747 +          down to 128 (576 taken from RFC 791: All hosts must be
9748 +          prepared to accept datagrams of up to 576 octets).  Use 128
9749 +          here. */
9750 +#define MIN_LIKELY_MTU 128
9751 +       /* CHECK: Min size of first frag = 128. */
9752 +       if ((ntohs(iph->frag_off) & IP_MF)
9753 +           && offset == 0
9754 +           && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
9755 +               limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
9756 +                     MIN_LIKELY_MTU);
9757 +               return 0;
9758 +       }
9759 +
9760 +       /* CHECK: Min offset of frag = 128 - IP hdr len. */
9761 +       if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
9762 +               limpk("Fragment starts at %u < %u\n", offset * 8,
9763 +                     MIN_LIKELY_MTU - iph->ihl * 4);
9764 +               return 0;
9765 +       }
9766 +
9767 +       /* CHECK: Protocol specification non-zero. */
9768 +       if (iph->protocol == 0) {
9769 +               limpk("Zero protocol\n");
9770 +               return 0;
9771 +       }
9772 +
9773 +       /* CHECK: Do not use what is unused.
9774 +        * First bit of fragmentation flags should be unused.
9775 +        * May be used by OS fingerprinting tools.
9776 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
9777 +        */
9778 +       if (ntohs(iph->frag_off)>>15) {
9779 +               limpk("IP unused bit set\n");
9780 +               return 0;
9781 +       }
9782 +
9783 +       /* Per-protocol checks. */
9784 +       switch (iph->protocol) {
9785 +       case IPPROTO_ICMP:
9786 +               return check_icmp(protoh, datalen, offset,
9787 +                                 (ntohs(iph->frag_off) & IP_MF),
9788 +                                 embedded);
9789 +
9790 +       case IPPROTO_UDP:
9791 +               return check_udp(iph, protoh, datalen, offset,
9792 +                                (ntohs(iph->frag_off) & IP_MF),
9793 +                                embedded);
9794 +
9795 +       case IPPROTO_TCP:
9796 +               return check_tcp(iph, protoh, datalen, offset,
9797 +                                (ntohs(iph->frag_off) & IP_MF),
9798 +                                embedded);
9799 +       default:
9800 +               /* Ignorance is bliss. */
9801 +               return 1;
9802 +       }
9803 +}
9804 +
9805 +static int
9806 +match(const struct sk_buff *skb,
9807 +      const struct net_device *in,
9808 +      const struct net_device *out,
9809 +      const void *matchinfo,
9810 +      int offset,
9811 +      const void *hdr,
9812 +      u_int16_t datalen,
9813 +      int *hotdrop)
9814 +{
9815 +       return !check_ip(skb->nh.iph, skb->len, 0);
9816 +}
9817 +
9818 +/* Called when user tries to insert an entry of this type. */
9819 +static int
9820 +checkentry(const char *tablename,
9821 +          const struct ipt_ip *ip,
9822 +          void *matchinfo,
9823 +          unsigned int matchsize,
9824 +          unsigned int hook_mask)
9825 +{
9826 +       if (matchsize != IPT_ALIGN(0))
9827 +               return 0;
9828 +
9829 +       return 1;
9830 +}
9831 +
9832 +static struct ipt_match unclean_match
9833 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
9834 +
9835 +static int __init init(void)
9836 +{
9837 +       return ipt_register_match(&unclean_match);
9838 +}
9839 +
9840 +static void __exit fini(void)
9841 +{
9842 +       ipt_unregister_match(&unclean_match);
9843 +}
9844 +
9845 +module_init(init);
9846 +module_exit(fini);
9847 +MODULE_LICENSE("GPL");
9848 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/raw.c linux-2.6.6-rc1/net/ipv4/raw.c
9849 --- linux-2.6.6-rc1.org/net/ipv4/raw.c  2004-04-15 03:35:04.000000000 +0200
9850 +++ linux-2.6.6-rc1/net/ipv4/raw.c      2004-04-16 09:17:13.000000000 +0200
9851 @@ -249,6 +249,7 @@
9852                 kfree_skb(skb);
9853                 return NET_RX_DROP;
9854         }
9855 +       nf_reset(skb);
9856  
9857         skb_push(skb, skb->data - skb->nh.raw);
9858  
9859 @@ -307,7 +308,7 @@
9860         }
9861  
9862         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
9863 -                     dst_output);
9864 +                     ip_dst_output);
9865         if (err > 0)
9866                 err = inet->recverr ? net_xmit_errno(err) : 0;
9867         if (err)
9868 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc1/net/ipv4/tcp_ipv4.c
9869 --- linux-2.6.6-rc1.org/net/ipv4/tcp_ipv4.c     2004-04-15 03:34:35.000000000 +0200
9870 +++ linux-2.6.6-rc1/net/ipv4/tcp_ipv4.c 2004-04-16 09:18:14.000000000 +0200
9871 @@ -1785,6 +1785,7 @@
9872  
9873         if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
9874                 goto discard_and_relse;
9875 +       nf_reset(skb);
9876  
9877         if (sk_filter(sk, skb, 0))
9878                 goto discard_and_relse;
9879 @@ -2670,6 +2671,7 @@
9880  EXPORT_SYMBOL(tcp_v4_connect);
9881  EXPORT_SYMBOL(tcp_v4_do_rcv);
9882  EXPORT_SYMBOL(tcp_v4_lookup_listener);
9883 +EXPORT_SYMBOL(tcp_v4_lookup);
9884  EXPORT_SYMBOL(tcp_v4_rebuild_header);
9885  EXPORT_SYMBOL(tcp_v4_remember_stamp);
9886  EXPORT_SYMBOL(tcp_v4_send_check);
9887 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/udp.c linux-2.6.6-rc1/net/ipv4/udp.c
9888 --- linux-2.6.6-rc1.org/net/ipv4/udp.c  2004-04-15 03:34:02.000000000 +0200
9889 +++ linux-2.6.6-rc1/net/ipv4/udp.c      2004-04-16 09:18:14.000000000 +0200
9890 @@ -1030,6 +1030,7 @@
9891                 kfree_skb(skb);
9892                 return -1;
9893         }
9894 +       nf_reset(skb);
9895  
9896         if (up->encap_type) {
9897                 /*
9898 @@ -1195,6 +1196,7 @@
9899  
9900         if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
9901                 goto drop;
9902 +       nf_reset(skb);
9903  
9904         /* No socket. Drop packet silently, if checksum is wrong */
9905         if (udp_checksum_complete(skb))
9906 @@ -1543,6 +1545,7 @@
9907  EXPORT_SYMBOL(udp_port_rover);
9908  EXPORT_SYMBOL(udp_prot);
9909  EXPORT_SYMBOL(udp_sendmsg);
9910 +EXPORT_SYMBOL(udp_v4_lookup);
9911  
9912  #ifdef CONFIG_PROC_FS
9913  EXPORT_SYMBOL(udp_proc_register);
9914 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc1/net/ipv4/xfrm4_tunnel.c
9915 --- linux-2.6.6-rc1.org/net/ipv4/xfrm4_tunnel.c 2004-04-15 03:33:55.000000000 +0200
9916 +++ linux-2.6.6-rc1/net/ipv4/xfrm4_tunnel.c     2004-04-16 09:17:09.000000000 +0200
9917 @@ -76,6 +76,7 @@
9918                 err = -EHOSTUNREACH;
9919                 goto error_nolock;
9920         }
9921 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
9922         return NET_XMIT_BYPASS;
9923  
9924  error_nolock:
9925 @@ -170,6 +171,7 @@
9926         .handler        =       ipip_rcv,
9927         .err_handler    =       ipip_err,
9928         .no_policy      =       1,
9929 +       .xfrm_prot      =       1,
9930  };
9931  
9932  static int __init ipip_init(void)
9933 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc1/net/ipv6/netfilter/Kconfig
9934 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/Kconfig      2004-04-16 08:59:09.000000000 +0200
9935 +++ linux-2.6.6-rc1/net/ipv6/netfilter/Kconfig  2004-04-16 09:15:44.000000000 +0200
9936 @@ -255,5 +255,10 @@
9937           <file:Documentation/modules.txt>.  If unsure, say `N'.
9938           help
9939  
9940 +config IP6_NF_TARGET_ROUTE
9941 +       tristate '    ROUTE target support'
9942 +       depends on IP6_NF_MANGLE
9943 +         help
9944 +
9945  endmenu
9946  
9947 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc1/net/ipv6/netfilter/Makefile
9948 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/Makefile     2004-04-16 08:59:09.000000000 +0200
9949 +++ linux-2.6.6-rc1/net/ipv6/netfilter/Makefile 2004-04-16 09:15:44.000000000 +0200
9950 @@ -20,6 +20,7 @@
9951  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
9952  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
9953  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
9954 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
9955  obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
9956  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
9957  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
9958 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_ROUTE.c
9959 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
9960 +++ linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_ROUTE.c     2004-04-16 09:15:44.000000000 +0200
9961 @@ -0,0 +1,289 @@
9962 +/*
9963 + * This implements the ROUTE v6 target, which enables you to setup unusual
9964 + * routes not supported by the standard kernel routing table.
9965 + *
9966 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
9967 + *
9968 + * v 1.0 2003/08/05
9969 + *
9970 + * This software is distributed under GNU GPL v2, 1991
9971 + */
9972 +
9973 +#include <linux/module.h>
9974 +#include <linux/skbuff.h>
9975 +#include <linux/ipv6.h>
9976 +#include <linux/netfilter_ipv6/ip6_tables.h>
9977 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
9978 +#include <linux/netdevice.h>
9979 +#include <net/ipv6.h>
9980 +#include <net/ndisc.h>
9981 +#include <net/ip6_route.h>
9982 +#include <linux/icmpv6.h>
9983 +
9984 +#if 1
9985 +#define DEBUGP printk
9986 +#else
9987 +#define DEBUGP(format, args...)
9988 +#endif
9989 +
9990 +#define NIP6(addr) \
9991 +       ntohs((addr).s6_addr16[0]), \
9992 +       ntohs((addr).s6_addr16[1]), \
9993 +       ntohs((addr).s6_addr16[2]), \
9994 +       ntohs((addr).s6_addr16[3]), \
9995 +       ntohs((addr).s6_addr16[4]), \
9996 +       ntohs((addr).s6_addr16[5]), \
9997 +       ntohs((addr).s6_addr16[6]), \
9998 +       ntohs((addr).s6_addr16[7])
9999 +
10000 +/* Route the packet according to the routing keys specified in
10001 + * route_info. Keys are :
10002 + *  - ifindex : 
10003 + *      0 if no oif preferred, 
10004 + *      otherwise set to the index of the desired oif
10005 + *  - route_info->gw :
10006 + *      0 if no gateway specified,
10007 + *      otherwise set to the next host to which the pkt must be routed
10008 + * If success, skb->dev is the output device to which the packet must 
10009 + * be sent and skb->dst is not NULL
10010 + *
10011 + * RETURN:  1 if the packet was succesfully routed to the 
10012 + *            destination desired
10013 + *          0 if the kernel routing table could not route the packet
10014 + *            according to the keys specified
10015 + */
10016 +static int 
10017 +route6(struct sk_buff *skb,
10018 +       unsigned int ifindex,
10019 +       const struct ip6t_route_target_info *route_info)
10020 +{
10021 +       struct rt6_info *rt = NULL;
10022 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
10023 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
10024 +
10025 +       DEBUGP("ip6t_ROUTE: called with: ");
10026 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
10027 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
10028 +       DEBUGP("OUT=%s\n", route_info->oif);
10029 +       
10030 +       if (ipv6_addr_any(gw))
10031 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
10032 +       else
10033 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
10034 +
10035 +       if (!rt)
10036 +               goto no_route;
10037 +
10038 +       DEBUGP("ip6t_ROUTE: routing gives: ");
10039 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
10040 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
10041 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
10042 +
10043 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
10044 +               goto wrong_route;
10045 +       
10046 +       if (!rt->rt6i_nexthop) {
10047 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
10048 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
10049 +       }
10050 +
10051 +       /* Drop old route. */
10052 +       dst_release(skb->dst);
10053 +       skb->dst = &rt->u.dst;
10054 +       skb->dev = rt->rt6i_dev;
10055 +       return 1;
10056 +
10057 + wrong_route:
10058 +       dst_release(&rt->u.dst);
10059 + no_route:
10060 +       if (!net_ratelimit())
10061 +               return 0;
10062 +
10063 +       printk("ip6t_ROUTE: no explicit route found ");
10064 +       if (ifindex)
10065 +               printk("via interface %s ", route_info->oif);
10066 +       if (!ipv6_addr_any(gw))
10067 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
10068 +       printk("\n");
10069 +       return 0;
10070 +}
10071 +
10072 +
10073 +/* Stolen from ip6_output_finish
10074 + * PRE : skb->dev is set to the device we are leaving by
10075 + *       skb->dst is not NULL
10076 + * POST: the packet is sent with the link layer header pushed
10077 + *       the packet is destroyed
10078 + */
10079 +static void ip_direct_send(struct sk_buff *skb)
10080 +{
10081 +       struct dst_entry *dst = skb->dst;
10082 +       struct hh_cache *hh = dst->hh;
10083 +
10084 +       if (hh) {
10085 +               read_lock_bh(&hh->hh_lock);
10086 +               memcpy(skb->data - 16, hh->hh_data, 16);
10087 +               read_unlock_bh(&hh->hh_lock);
10088 +               skb_push(skb, hh->hh_len);
10089 +               hh->hh_output(skb);
10090 +       } else if (dst->neighbour)
10091 +               dst->neighbour->output(skb);
10092 +       else {
10093 +               if (net_ratelimit())
10094 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
10095 +               kfree_skb(skb);
10096 +       }
10097 +}
10098 +
10099 +
10100 +static unsigned int 
10101 +route6_oif(const struct ip6t_route_target_info *route_info,
10102 +          struct sk_buff *skb) 
10103 +{
10104 +       unsigned int ifindex = 0;
10105 +       struct net_device *dev_out = NULL;
10106 +
10107 +       /* The user set the interface name to use.
10108 +        * Getting the current interface index.
10109 +        */
10110 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
10111 +               ifindex = dev_out->ifindex;
10112 +       } else {
10113 +               /* Unknown interface name : packet dropped */
10114 +               if (net_ratelimit()) 
10115 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
10116 +
10117 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
10118 +                       return IP6T_CONTINUE;
10119 +               else
10120 +                       return NF_DROP;
10121 +       }
10122 +
10123 +       /* Trying the standard way of routing packets */
10124 +       if (route6(skb, ifindex, route_info)) {
10125 +               dev_put(dev_out);
10126 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
10127 +                       return IP6T_CONTINUE;
10128 +               
10129 +               ip_direct_send(skb);
10130 +               return NF_STOLEN;
10131 +       } else 
10132 +               return NF_DROP;
10133 +}
10134 +
10135 +
10136 +static unsigned int 
10137 +route6_gw(const struct ip6t_route_target_info *route_info,
10138 +         struct sk_buff *skb) 
10139 +{
10140 +       if (route6(skb, 0, route_info)) {
10141 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
10142 +                       return IP6T_CONTINUE;
10143 +
10144 +               ip_direct_send(skb);
10145 +               return NF_STOLEN;
10146 +       } else
10147 +               return NF_DROP;
10148 +}
10149 +
10150 +
10151 +static unsigned int 
10152 +ip6t_route_target(struct sk_buff **pskb,
10153 +                 unsigned int hooknum,
10154 +                 const struct net_device *in,
10155 +                 const struct net_device *out,
10156 +                 const void *targinfo,
10157 +                 void *userinfo)
10158 +{
10159 +       const struct ip6t_route_target_info *route_info = targinfo;
10160 +       struct sk_buff *skb = *pskb;
10161 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
10162 +
10163 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
10164 +               goto do_it;
10165 +
10166 +       /* If we are at PREROUTING or INPUT hook
10167 +        * the TTL isn't decreased by the IP stack
10168 +        */
10169 +       if (hooknum == NF_IP6_PRE_ROUTING ||
10170 +           hooknum == NF_IP6_LOCAL_IN) {
10171 +
10172 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
10173 +
10174 +               if (ipv6h->hop_limit <= 1) {
10175 +                       /* Force OUTPUT device used as source address */
10176 +                       skb->dev = skb->dst->dev;
10177 +
10178 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
10179 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
10180 +
10181 +                       return NF_DROP;
10182 +               }
10183 +
10184 +               ipv6h->hop_limit--;
10185 +       }
10186 +
10187 +
10188 + do_it:
10189 +       if (route_info->oif[0]) 
10190 +               return route6_oif(route_info, *pskb);
10191 +       
10192 +       if (!ipv6_addr_any(gw))
10193 +               return route6_gw(route_info, *pskb);
10194 +
10195 +       if (net_ratelimit()) 
10196 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
10197 +
10198 +       return IP6T_CONTINUE;
10199 +}
10200 +
10201 +
10202 +static int 
10203 +ip6t_route_checkentry(const char *tablename,
10204 +                     const struct ip6t_entry *e,
10205 +                     void *targinfo,
10206 +                     unsigned int targinfosize,
10207 +                     unsigned int hook_mask)
10208 +{
10209 +       if (strcmp(tablename, "mangle") != 0) {
10210 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
10211 +               return 0;
10212 +       }
10213 +
10214 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
10215 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
10216 +                      targinfosize,
10217 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
10218 +               return 0;
10219 +       }
10220 +
10221 +       return 1;
10222 +}
10223 +
10224 +
10225 +static struct ip6t_target ip6t_route_reg = {
10226 +       .name       = "ROUTE",
10227 +       .target     = ip6t_route_target,
10228 +       .checkentry = ip6t_route_checkentry,
10229 +       .me         = THIS_MODULE
10230 +};
10231 +
10232 +
10233 +static int __init init(void)
10234 +{
10235 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
10236 +       if (ip6t_register_target(&ip6t_route_reg))
10237 +               return -EINVAL;
10238 +
10239 +       return 0;
10240 +}
10241 +
10242 +
10243 +static void __exit fini(void)
10244 +{
10245 +       ip6t_unregister_target(&ip6t_route_reg);
10246 +}
10247 +
10248 +module_init(init);
10249 +module_exit(fini);
10250 +MODULE_LICENSE("GPL");
10251 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_owner.c
10252 --- linux-2.6.6-rc1.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-15 03:35:20.000000000 +0200
10253 +++ linux-2.6.6-rc1/net/ipv6/netfilter/ip6t_owner.c     2004-04-16 09:18:17.000000000 +0200
10254 @@ -21,6 +21,38 @@
10255  MODULE_LICENSE("GPL");
10256  
10257  static int
10258 +match_comm(const struct sk_buff *skb, const char *comm)
10259 +{
10260 +       struct task_struct *p;
10261 +       struct files_struct *files;
10262 +       int i;
10263 +
10264 +       read_lock(&tasklist_lock);
10265 +       for_each_task(p) {
10266 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
10267 +                       continue;
10268 +
10269 +               task_lock(p);
10270 +               files = p->files;
10271 +               if(files) {
10272 +                       read_lock(&files->file_lock);
10273 +                       for (i=0; i < files->max_fds; i++) {
10274 +                               if (fcheck_files(files, i) == skb->sk->socket->file) {
10275 +                                       read_unlock(&files->file_lock);
10276 +                                       task_unlock(p);
10277 +                                       read_unlock(&tasklist_lock);
10278 +                                       return 1;
10279 +                               }
10280 +                       }
10281 +                       read_unlock(&files->file_lock);
10282 +               }
10283 +               task_unlock(p);
10284 +       }
10285 +       read_unlock(&tasklist_lock);
10286 +       return 0;
10287 +}
10288 +
10289 +static int
10290  match_pid(const struct sk_buff *skb, pid_t pid)
10291  {
10292         struct task_struct *p;
10293 @@ -125,6 +157,12 @@
10294                         return 0;
10295         }
10296  
10297 +       if(info->match & IP6T_OWNER_COMM) {
10298 +               if (!match_comm(skb, info->comm) ^
10299 +                   !!(info->invert & IP6T_OWNER_COMM))
10300 +                       return 0;
10301 +       }
10302 +
10303         return 1;
10304  }
10305  
10306 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/xfrm/xfrm_input.c linux-2.6.6-rc1/net/xfrm/xfrm_input.c
10307 --- linux-2.6.6-rc1.org/net/xfrm/xfrm_input.c   2004-04-15 03:33:51.000000000 +0200
10308 +++ linux-2.6.6-rc1/net/xfrm/xfrm_input.c       2004-04-16 09:17:09.000000000 +0200
10309 @@ -29,6 +29,9 @@
10310         if (!sp)
10311                 return NULL;
10312  
10313 +#ifdef CONFIG_NETFILTER
10314 +       sp->decap_done = 0;
10315 +#endif
10316         sp->len = 0;
10317         if (src) {
10318                 int i;
10319 diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc1/net/xfrm/xfrm_policy.c
10320 --- linux-2.6.6-rc1.org/net/xfrm/xfrm_policy.c  2004-04-15 03:34:48.000000000 +0200
10321 +++ linux-2.6.6-rc1/net/xfrm/xfrm_policy.c      2004-04-16 09:17:13.000000000 +0200
10322 @@ -21,6 +21,7 @@
10323  #include <linux/workqueue.h>
10324  #include <linux/notifier.h>
10325  #include <linux/netdevice.h>
10326 +#include <linux/netfilter.h>
10327  #include <net/xfrm.h>
10328  #include <net/ip.h>
10329  
10330 @@ -908,6 +909,7 @@
10331  
10332         if (_decode_session(skb, &fl, family) < 0)
10333                 return 0;
10334 +       nf_nat_decode_session(skb, &fl, family);
10335  
10336         /* First, check used SA against their selectors. */
10337         if (skb->sp) {
This page took 0.886201 seconds and 3 git commands to generate.