]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.5-rc1-patch-o-matic-ng-extra-20040316.patch
- ported from linux-2.4.25-atmdd.patch
[packages/kernel.git] / 2.6.5-rc1-patch-o-matic-ng-extra-20040316.patch
1 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_helpers.h linux-2.6.5-rc1/include/linux/netfilter_helpers.h
2 --- linux-2.6.5-rc1.org/include/linux/netfilter_helpers.h       1970-01-01 00:00:00.000000000 +0000
3 +++ linux-2.6.5-rc1/include/linux/netfilter_helpers.h   2004-03-16 12:04:49.000000000 +0000
4 @@ -0,0 +1,133 @@
5 +/*
6 + * Helpers for netfiler modules.  This file provides implementations for basic
7 + * functions such as strncasecmp(), etc.
8 + *
9 + * gcc will warn for defined but unused functions, so we only include the
10 + * functions requested.  The following macros are used:
11 + *   NF_NEED_STRNCASECMP        nf_strncasecmp()
12 + *   NF_NEED_STRTOU16           nf_strtou16()
13 + *   NF_NEED_STRTOU32           nf_strtou32()
14 + */
15 +#ifndef _NETFILTER_HELPERS_H
16 +#define _NETFILTER_HELPERS_H
17 +
18 +/* Only include these functions for kernel code. */
19 +#ifdef __KERNEL__
20 +
21 +#include <linux/ctype.h>
22 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
23 +
24 +/*
25 + * The standard strncasecmp()
26 + */
27 +#ifdef NF_NEED_STRNCASECMP
28 +static int
29 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
30 +{
31 +    if (s1 == NULL || s2 == NULL)
32 +    {
33 +        if (s1 == NULL && s2 == NULL)
34 +        {
35 +            return 0;
36 +        }
37 +        return (s1 == NULL) ? -1 : 1;
38 +    }
39 +    while (len > 0 && tolower(*s1) == tolower(*s2))
40 +    {
41 +        len--;
42 +        s1++;
43 +        s2++;
44 +    }
45 +    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
46 +}
47 +#endif /* NF_NEED_STRNCASECMP */
48 +
49 +/*
50 + * Parse a string containing a 16-bit unsigned integer.
51 + * Returns the number of chars used, or zero if no number is found.
52 + */
53 +#ifdef NF_NEED_STRTOU16
54 +static int
55 +nf_strtou16(const char* pbuf, u_int16_t* pval)
56 +{
57 +    int n = 0;
58 +
59 +    *pval = 0;
60 +    while (isdigit(pbuf[n]))
61 +    {
62 +        *pval = (*pval * 10) + (pbuf[n] - '0');
63 +        n++;
64 +    }
65 +
66 +    return n;
67 +}
68 +#endif /* NF_NEED_STRTOU16 */
69 +
70 +/*
71 + * Parse a string containing a 32-bit unsigned integer.
72 + * Returns the number of chars used, or zero if no number is found.
73 + */
74 +#ifdef NF_NEED_STRTOU32
75 +static int
76 +nf_strtou32(const char* pbuf, u_int32_t* pval)
77 +{
78 +    int n = 0;
79 +
80 +    *pval = 0;
81 +    while (pbuf[n] >= '0' && pbuf[n] <= '9')
82 +    {
83 +        *pval = (*pval * 10) + (pbuf[n] - '0');
84 +        n++;
85 +    }
86 +
87 +    return n;
88 +}
89 +#endif /* NF_NEED_STRTOU32 */
90 +
91 +/*
92 + * Given a buffer and length, advance to the next line and mark the current
93 + * line.
94 + */
95 +#ifdef NF_NEED_NEXTLINE
96 +static int
97 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
98 +{
99 +    uint    off = *poff;
100 +    uint    physlen = 0;
101 +
102 +    if (off >= len)
103 +    {
104 +        return 0;
105 +    }
106 +
107 +    while (p[off] != '\n')
108 +    {
109 +        if (len-off <= 1)
110 +        {
111 +            return 0;
112 +        }
113 +
114 +        physlen++;
115 +        off++;
116 +    }
117 +
118 +    /* if we saw a crlf, physlen needs adjusted */
119 +    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
120 +    {
121 +        physlen--;
122 +    }
123 +
124 +    /* advance past the newline */
125 +    off++;
126 +
127 +    *plineoff = *poff;
128 +    *plinelen = physlen;
129 +    *poff = off;
130 +
131 +    return 1;
132 +}
133 +#endif /* NF_NEED_NEXTLINE */
134 +
135 +#endif /* __KERNEL__ */
136 +
137 +#endif /* _NETFILTER_HELPERS_H */
138 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ip_conntrack.h
139 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h     2004-03-16 12:00:23.000000000 +0000
140 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ip_conntrack.h 2004-03-16 12:04:49.000000000 +0000
141 @@ -64,6 +64,7 @@
142  };
143  
144  /* Add protocol helper include file here */
145 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
146  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
147  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
148  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
149 @@ -71,6 +72,8 @@
150  /* per expectation: application helper private data */
151  union ip_conntrack_expect_help {
152         /* insert conntrack helper private data (expect) here */
153 +       struct ip_ct_rtsp_expect exp_rtsp_info;
154 +       struct ip_ct_rtsp_master ct_rtsp_info;
155         struct ip_ct_amanda_expect exp_amanda_info;
156         struct ip_ct_ftp_expect exp_ftp_info;
157         struct ip_ct_irc_expect exp_irc_info;
158 @@ -206,6 +209,10 @@
159         } nat;
160  #endif /* CONFIG_IP_NF_NAT_NEEDED */
161  
162 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
163 +       unsigned long mark;
164 +#endif
165 +
166  };
167  
168  /* get master conntrack via master expectation */
169 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
170 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 00:00:00.000000000 +0000
171 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ip_conntrack_rpc.h     2004-03-16 12:04:46.000000000 +0000
172 @@ -0,0 +1,68 @@
173 +/* RPC extension for IP connection tracking, Version 2.2
174 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
175 + *     - original rpc tracking module
176 + *     - "recent" connection handling for kernel 2.3+ netfilter
177 + *
178 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
179 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
180 + *
181 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
182 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
183 + *     - extended matching to support filtering on procedures
184 + *
185 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
186 + *
187 + *     This program is free software; you can redistribute it and/or
188 + *     modify it under the terms of the GNU General Public License
189 + *     as published by the Free Software Foundation; either version
190 + *     2 of the License, or (at your option) any later version.
191 + **
192 + */
193 +
194 +#include <asm/param.h>
195 +#include <linux/sched.h>
196 +#include <linux/timer.h>
197 +#include <linux/stddef.h>
198 +#include <linux/list.h>
199 +
200 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
201 +
202 +#ifndef _IP_CONNTRACK_RPC_H
203 +#define _IP_CONNTRACK_RPC_H
204 +
205 +#define RPC_PORT       111
206 +
207 +
208 +/* Datum in RPC packets are encoded in XDR */
209 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
210 +
211 +/* Fast timeout, to deny DoS atacks */
212 +#define EXP (60 * HZ)
213 +
214 +/* Normal timeouts */
215 +#define EXPIRES (180 * HZ)
216 +
217 +/* For future conections RPC, using client's cache bindings
218 + * I'll use ip_conntrack_lock to lock these lists      */
219 +
220 +/* This identifies each request and stores protocol */
221 +struct request_p {
222 +       struct list_head list;
223 +
224 +       u_int32_t xid;   
225 +       u_int32_t ip;
226 +       u_int16_t port;
227 +       
228 +       /* Protocol */
229 +       u_int16_t proto;
230 +
231 +       struct timer_list timeout;
232 +};
233 +
234 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
235 +                               u_int32_t ip, u_int32_t port) {
236 +       return (p->xid == xid && p->ip == ip && p->port);
237 +
238 +}
239 +
240 +#endif /* _IP_CONNTRACK_RPC_H */
241 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
242 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h        1970-01-01 00:00:00.000000000 +0000
243 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h    2004-03-16 12:04:49.000000000 +0000
244 @@ -0,0 +1,68 @@
245 +/*
246 + * RTSP extension for IP connection tracking.
247 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
248 + * based on ip_conntrack_irc.h
249 + *
250 + *      This program is free software; you can redistribute it and/or
251 + *      modify it under the terms of the GNU General Public License
252 + *      as published by the Free Software Foundation; either version
253 + *      2 of the License, or (at your option) any later version.
254 + */
255 +#ifndef _IP_CONNTRACK_RTSP_H
256 +#define _IP_CONNTRACK_RTSP_H
257 +
258 +/* #define IP_NF_RTSP_DEBUG */
259 +#define IP_NF_RTSP_VERSION "0.01"
260 +
261 +/* port block types */
262 +typedef enum {
263 +    pb_single,  /* client_port=x */
264 +    pb_range,   /* client_port=x-y */
265 +    pb_discon   /* client_port=x/y (rtspbis) */
266 +} portblock_t;
267 +
268 +/* We record seq number and length of rtsp headers here, all in host order. */
269 +
270 +/*
271 + * This structure is per expected connection.  It is a member of struct
272 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
273 + * there and we are expected to only store the length of the data which
274 + * needs replaced.  If a packet contains multiple RTSP messages, we create
275 + * one expected connection per message.
276 + *
277 + * We use these variables to mark the entire header block.  This may seem
278 + * like overkill, but the nature of RTSP requires it.  A header may appear
279 + * multiple times in a message.  We must treat two Transport headers the
280 + * same as one Transport header with two entries.
281 + */
282 +struct ip_ct_rtsp_expect
283 +{
284 +    u_int32_t   len;        /* length of header block */
285 +    portblock_t pbtype;     /* Type of port block that was requested */
286 +    u_int16_t   loport;     /* Port that was requested, low or first */
287 +    u_int16_t   hiport;     /* Port that was requested, high or second */
288 +#if 0
289 +    uint        method;     /* RTSP method */
290 +    uint        cseq;       /* CSeq from request */
291 +#endif
292 +};
293 +
294 +/* This structure exists only once per master */
295 +struct ip_ct_rtsp_master
296 +{
297 +    /* Empty (?) */
298 +};
299 +
300 +
301 +#ifdef __KERNEL__
302 +
303 +#include <linux/netfilter_ipv4/lockhelp.h>
304 +
305 +#define RTSP_PORT   554
306 +
307 +/* Protects rtsp part of conntracks */
308 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
309 +
310 +#endif /* __KERNEL__ */
311 +
312 +#endif /* _IP_CONNTRACK_RTSP_H */
313 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h
314 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h     1970-01-01 00:00:00.000000000 +0000
315 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-03-16 12:04:09.000000000 +0000
316 @@ -0,0 +1,25 @@
317 +#ifndef _IPT_CONNMARK_H_target
318 +#define _IPT_CONNMARK_H_target
319 +
320 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
321 + * by Henrik Nordstrom <hno@marasystems.com>
322 + *
323 + * This program is free software; you can redistribute it and/or modify
324 + * it under the terms of the GNU General Public License as published by
325 + * the Free Software Foundation; either version 2 of the License, or
326 + * (at your option) any later version.
327 + */
328 +
329 +enum {
330 +       IPT_CONNMARK_SET = 0,
331 +       IPT_CONNMARK_SAVE,
332 +       IPT_CONNMARK_RESTORE
333 +};
334 +
335 +struct ipt_connmark_target_info {
336 +       unsigned long mark;
337 +       unsigned long mask;
338 +       u_int8_t mode;
339 +};
340 +
341 +#endif /*_IPT_CONNMARK_H_target*/
342 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h
343 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h       1970-01-01 00:00:00.000000000 +0000
344 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h   2004-03-16 12:04:10.000000000 +0000
345 @@ -0,0 +1,13 @@
346 +#ifndef _IPT_IPMARK_H_target
347 +#define _IPT_IPMARK_H_target
348 +
349 +struct ipt_ipmark_target_info {
350 +       unsigned long andmask;
351 +       unsigned long ormask;
352 +       unsigned int addr;
353 +};
354 +
355 +#define IPT_IPMARK_SRC    0
356 +#define IPT_IPMARK_DST    1
357 +
358 +#endif /*_IPT_IPMARK_H_target*/
359 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_XOR.h
360 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h  1970-01-01 00:00:00.000000000 +0000
361 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_XOR.h      2004-03-16 12:04:18.000000000 +0000
362 @@ -0,0 +1,9 @@
363 +#ifndef _IPT_XOR_H
364 +#define _IPT_XOR_H
365 +
366 +struct ipt_XOR_info {
367 +       char            key[30];
368 +       u_int8_t        block_size;
369 +};
370 +
371 +#endif /* _IPT_XOR_H */
372 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h
373 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h     1970-01-01 00:00:00.000000000 +0000
374 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-03-16 12:04:20.000000000 +0000
375 @@ -0,0 +1,11 @@
376 +#ifndef _IPT_ADDRTYPE_H
377 +#define _IPT_ADDRTYPE_H
378 +
379 +struct ipt_addrtype_info {
380 +       u_int16_t       source;         /* source-type mask */
381 +       u_int16_t       dest;           /* dest-type mask */
382 +       int             invert_source;
383 +       int             invert_dest;
384 +};
385 +
386 +#endif
387 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_connmark.h
388 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h     1970-01-01 00:00:00.000000000 +0000
389 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_connmark.h 2004-03-16 12:04:09.000000000 +0000
390 @@ -0,0 +1,18 @@
391 +#ifndef _IPT_CONNMARK_H
392 +#define _IPT_CONNMARK_H
393 +
394 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
395 + * by Henrik Nordstrom <hno@marasystems.com>
396 + *
397 + * This program is free software; you can redistribute it and/or modify
398 + * it under the terms of the GNU General Public License as published by
399 + * the Free Software Foundation; either version 2 of the License, or
400 + * (at your option) any later version.
401 + */
402 +
403 +struct ipt_connmark_info {
404 +       unsigned long mark, mask;
405 +       u_int8_t invert;
406 +};
407 +
408 +#endif /*_IPT_CONNMARK_H*/
409 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_policy.h
410 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h       1970-01-01 00:00:00.000000000 +0000
411 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_policy.h   2004-03-16 12:04:45.000000000 +0000
412 @@ -0,0 +1,52 @@
413 +#ifndef _IPT_POLICY_H
414 +#define _IPT_POLICY_H
415 +
416 +#define POLICY_MAX_ELEM        4
417 +
418 +enum ipt_policy_flags
419 +{
420 +       POLICY_MATCH_IN         = 0x1,
421 +       POLICY_MATCH_OUT        = 0x2,
422 +       POLICY_MATCH_NONE       = 0x4,
423 +       POLICY_MATCH_STRICT     = 0x8,
424 +};
425 +
426 +enum ipt_policy_modes
427 +{
428 +       POLICY_MODE_TRANSPORT,
429 +       POLICY_MODE_TUNNEL
430 +};
431 +
432 +struct ipt_policy_spec
433 +{
434 +       u_int8_t        saddr:1,
435 +                       daddr:1,
436 +                       proto:1,
437 +                       mode:1,
438 +                       spi:1,
439 +                       reqid:1;
440 +};
441 +
442 +struct ipt_policy_elem
443 +{
444 +       u_int32_t       saddr;
445 +       u_int32_t       smask;
446 +       u_int32_t       daddr;
447 +       u_int32_t       dmask;
448 +       u_int32_t       spi;
449 +       u_int32_t       reqid;
450 +       u_int8_t        proto;
451 +       u_int8_t        mode;
452 +
453 +       struct ipt_policy_spec  match;
454 +       struct ipt_policy_spec  invert;
455 +};
456 +
457 +struct ipt_policy_info
458 +{
459 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
460 +       u_int16_t flags;
461 +       u_int16_t len;
462 +};
463 +
464 +#endif /* _IPT_POLICY_H */
465 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_rpc.h
466 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_rpc.h  1970-01-01 00:00:00.000000000 +0000
467 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_rpc.h      2004-03-16 12:04:46.000000000 +0000
468 @@ -0,0 +1,35 @@
469 +/* RPC extension for IP netfilter matching, Version 2.2
470 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
471 + *     - original rpc tracking module
472 + *     - "recent" connection handling for kernel 2.3+ netfilter
473 + *
474 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
475 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
476 + *
477 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
478 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
479 + *     - extended matching to support filtering on procedures
480 + *
481 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
482 + *
483 + *     This program is free software; you can redistribute it and/or
484 + *     modify it under the terms of the GNU General Public License
485 + *     as published by the Free Software Foundation; either version
486 + *     2 of the License, or (at your option) any later version.
487 + **
488 + */
489 +
490 +#ifndef _IPT_RPC_H
491 +#define _IPT_RPC_H
492 +
493 +struct ipt_rpc_data;
494 +
495 +struct ipt_rpc_info {
496 +       int inverse;
497 +       int strict;
498 +       const char c_procs[1408];
499 +       int i_procs;
500 +       struct ipt_rpc_data *data;
501 +};
502 +
503 +#endif /* _IPT_RPC_H */
504 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_string.h
505 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv4/ipt_string.h       1970-01-01 00:00:00.000000000 +0000
506 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv4/ipt_string.h   2004-03-16 12:06:26.000000000 +0000
507 @@ -0,0 +1,21 @@
508 +#ifndef _IPT_STRING_H
509 +#define _IPT_STRING_H
510 +
511 +/* *** PERFORMANCE TWEAK ***
512 + * Packet size and search string threshold,
513 + * above which sublinear searches is used. */
514 +#define IPT_STRING_HAYSTACK_THRESH     100
515 +#define IPT_STRING_NEEDLE_THRESH       20
516 +
517 +#define BM_MAX_NLEN 256
518 +#define BM_MAX_HLEN 1024
519 +
520 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
521 +
522 +struct ipt_string_info {
523 +    char string[BM_MAX_NLEN];
524 +    u_int16_t invert;
525 +    u_int16_t len;
526 +};
527 +
528 +#endif /* _IPT_STRING_H */
529 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.5-rc1/include/linux/netfilter_ipv6/ip6t_owner.h
530 --- linux-2.6.5-rc1.org/include/linux/netfilter_ipv6/ip6t_owner.h       2004-03-16 05:46:45.000000000 +0000
531 +++ linux-2.6.5-rc1/include/linux/netfilter_ipv6/ip6t_owner.h   2004-03-16 12:04:42.000000000 +0000
532 @@ -6,12 +6,14 @@
533  #define IP6T_OWNER_GID 0x02
534  #define IP6T_OWNER_PID 0x04
535  #define IP6T_OWNER_SID 0x08
536 +#define IP6T_OWNER_COMM 0x10
537  
538  struct ip6t_owner_info {
539      uid_t uid;
540      gid_t gid;
541      pid_t pid;
542      pid_t sid;
543 +    char comm[16];
544      u_int8_t match, invert;    /* flags */
545  };
546  
547 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/linux/netfilter_mime.h linux-2.6.5-rc1/include/linux/netfilter_mime.h
548 --- linux-2.6.5-rc1.org/include/linux/netfilter_mime.h  1970-01-01 00:00:00.000000000 +0000
549 +++ linux-2.6.5-rc1/include/linux/netfilter_mime.h      2004-03-16 12:04:49.000000000 +0000
550 @@ -0,0 +1,89 @@
551 +/*
552 + * MIME functions for netfilter modules.  This file provides implementations
553 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
554 + * HTTP, RTSP, SIP, etc.
555 + *
556 + * gcc will warn for defined but unused functions, so we only include the
557 + * functions requested.  The following macros are used:
558 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
559 + */
560 +#ifndef _NETFILTER_MIME_H
561 +#define _NETFILTER_MIME_H
562 +
563 +/* Only include these functions for kernel code. */
564 +#ifdef __KERNEL__
565 +
566 +#include <linux/ctype.h>
567 +
568 +/*
569 + * Given a buffer and length, advance to the next line and mark the current
570 + * line.  If the current line is empty, *plinelen will be set to zero.  If
571 + * not, it will be set to the actual line length (including CRLF).
572 + *
573 + * 'line' in this context means logical line (includes LWS continuations).
574 + * Returns 1 on success, 0 on failure.
575 + */
576 +#ifdef NF_NEED_MIME_NEXTLINE
577 +static int
578 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
579 +{
580 +    uint    off = *poff;
581 +    uint    physlen = 0;
582 +    int     is_first_line = 1;
583 +
584 +    if (off >= len)
585 +    {
586 +        return 0;
587 +    }
588 +
589 +    do
590 +    {
591 +        while (p[off] != '\n')
592 +        {
593 +            if (len-off <= 1)
594 +            {
595 +                return 0;
596 +            }
597 +
598 +            physlen++;
599 +            off++;
600 +        }
601 +
602 +        /* if we saw a crlf, physlen needs adjusted */
603 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
604 +        {
605 +            physlen--;
606 +        }
607 +
608 +        /* advance past the newline */
609 +        off++;
610 +
611 +        /* check for an empty line */
612 +        if (physlen == 0)
613 +        {
614 +            break;
615 +        }
616 +
617 +        /* check for colon on the first physical line */
618 +        if (is_first_line)
619 +        {
620 +            is_first_line = 0;
621 +            if (memchr(p+(*poff), ':', physlen) == NULL)
622 +            {
623 +                return 0;
624 +            }
625 +        }
626 +    }
627 +    while (p[off] == ' ' || p[off] == '\t');
628 +
629 +    *plineoff = *poff;
630 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
631 +    *poff = off;
632 +
633 +    return 1;
634 +}
635 +#endif /* NF_NEED_MIME_NEXTLINE */
636 +
637 +#endif /* __KERNEL__ */
638 +
639 +#endif /* _NETFILTER_MIME_H */
640 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/net/tcp.h linux-2.6.5-rc1/include/net/tcp.h
641 --- linux-2.6.5-rc1.org/include/net/tcp.h       2004-03-16 05:45:33.000000000 +0000
642 +++ linux-2.6.5-rc1/include/net/tcp.h   2004-03-16 12:04:38.000000000 +0000
643 @@ -162,6 +162,7 @@
644  extern void tcp_bucket_unlock(struct sock *sk);
645  extern int tcp_port_rover;
646  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
647 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
648  
649  /* These are AF independent. */
650  static __inline__ int tcp_bhashfn(__u16 lport)
651 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/include/net/udp.h linux-2.6.5-rc1/include/net/udp.h
652 --- linux-2.6.5-rc1.org/include/net/udp.h       2004-03-16 05:47:17.000000000 +0000
653 +++ linux-2.6.5-rc1/include/net/udp.h   2004-03-16 12:04:38.000000000 +0000
654 @@ -74,6 +74,8 @@
655  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
656  extern int     udp_disconnect(struct sock *sk, int flags);
657  
658 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
659 +
660  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
661  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
662  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
663 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/Kconfig linux-2.6.5-rc1/net/ipv4/netfilter/Kconfig
664 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/Kconfig      2004-03-16 12:00:23.000000000 +0000
665 +++ linux-2.6.5-rc1/net/ipv4/netfilter/Kconfig  2004-03-16 12:06:26.000000000 +0000
666 @@ -672,5 +672,61 @@
667         depends on IP_NF_IPTABLES
668           help
669  
670 +config IP_NF_CONNTRACK_MARK
671 +       bool  'Connection mark tracking support'
672 +config IP_NF_TARGET_CONNMARK
673 +       tristate  'CONNMARK target support'
674 +       depends on IP_NF_MANGLE
675 +config IP_NF_MATCH_CONNMARK
676 +       tristate  ' Connection mark match support'
677 +       depends on IP_NF_IPTABLES
678 +         help
679 +
680 +config IP_NF_TARGET_IPMARK
681 +       tristate  'IPMARK target support'
682 +       depends on IP_NF_MANGLE
683 +         help
684 +
685 +config IP_NF_TARGET_XOR
686 +       tristate  'XOR target support'
687 +       depends on IP_NF_MANGLE
688 +         help
689 +
690 +config IP_NF_MATCH_ADDRTYPE
691 +       tristate  'address type match support'
692 +       depends on IP_NF_IPTABLES
693 +         help
694 +
695 +config IP_NF_MATCH_POLICY
696 +       tristate "IPsec policy match support"
697 +       depends on IP_NF_IPTABLES && XFRM
698 +       help
699 +         Policy matching allows you to match packets based on the
700 +         IPsec policy that was used during decapsulation/will
701 +         be used during encapsulation.
702 +
703 +         To compile it as a module, choose M here.  If unsure, say N.
704 +         help
705 +
706 +config IP_NF_MATCH_RPC
707 +       tristate  'RPC match support'
708 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
709 +         help
710 +
711 +config IP_NF_NAT_RTSP
712 +       tristate
713 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
714 +       default IP_NF_NAT if IP_NF_RTSP=y
715 +       default m if IP_NF_RTSP=m
716 +config IP_NF_RTSP
717 +       tristate  ' RTSP protocol support'
718 +       depends on IP_NF_CONNTRACK
719 +         help
720 +
721 +config IP_NF_MATCH_STRING
722 +       tristate  'String match support'
723 +       depends on IP_NF_IPTABLES
724 +         help
725 +
726  endmenu
727  
728 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/Makefile linux-2.6.5-rc1/net/ipv4/netfilter/Makefile
729 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/Makefile     2004-03-16 12:00:23.000000000 +0000
730 +++ linux-2.6.5-rc1/net/ipv4/netfilter/Makefile 2004-03-16 12:06:26.000000000 +0000
731 @@ -20,6 +20,14 @@
732  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
733  
734  # connection tracking helpers
735 +
736 +# rtsp protocol support
737 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
738 +ifdef CONFIG_IP_NF_NAT_RTSP
739 +       export-objs += ip_conntrack_rtsp.o
740 +endif
741 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
742 +
743  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
744  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
745  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
746 @@ -41,6 +49,9 @@
747  obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
748  
749  # matches
750 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
751 +export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
752 +
753  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
754  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
755  obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
756 @@ -48,6 +59,7 @@
757  obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
758  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
759  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
760 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
761  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
762  
763  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
764 @@ -78,12 +90,15 @@
765  
766  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
767  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
768 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
769  obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
770  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
771  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
772 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
773  obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
774  
775  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
776 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
777  
778  # targets
779  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
780 @@ -91,6 +106,7 @@
781  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
782  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
783  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
784 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
785  obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
786  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
787  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
788 @@ -99,6 +115,8 @@
789  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
790  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
791  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
792 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
793 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
794  obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
795  obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
796  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
797 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
798 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c       1970-01-01 00:00:00.000000000 +0000
799 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c   2004-03-16 12:04:46.000000000 +0000
800 @@ -0,0 +1,508 @@
801 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
802 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
803 + *     - original rpc tracking module
804 + *     - "recent" connection handling for kernel 2.3+ netfilter
805 + *
806 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
807 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
808 + *
809 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
810 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
811 + *     - extended matching to support filtering on procedures
812 + *
813 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
814 + *
815 + *     This program is free software; you can redistribute it and/or
816 + *     modify it under the terms of the GNU General Public License
817 + *     as published by the Free Software Foundation; either version
818 + *     2 of the License, or (at your option) any later version.
819 + **
820 + *     Module load syntax:
821 + *     insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
822 + *
823 + *     Please give the ports of all RPC servers you wish to connect to.
824 + *     If you don't specify ports, the default will be port 111.
825 + **
826 + *     Note to all:
827 + *
828 + *     RPCs should not be exposed to the internet - ask the Pentagon;
829 + *
830 + *       "The unidentified crackers pleaded guilty in July to charges
831 + *        of juvenile delinquency stemming from a string of Pentagon
832 + *        network intrusions in February.
833 + *
834 + *        The youths, going by the names TooShort and Makaveli, used
835 + *        a common server security hole to break in, according to
836 + *        Dane Jasper, owner of the California Internet service
837 + *        provider, Sonic. They used the hole, known as the 'statd'
838 + *        exploit, to attempt more than 800 break-ins, Jasper said."
839 + *
840 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
841 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
842 + **
843 + */
844 +
845 +#include <linux/module.h>
846 +#include <linux/netfilter.h>
847 +#include <linux/ip.h>
848 +#include <net/checksum.h>
849 +#include <net/tcp.h>
850 +
851 +#include <asm/param.h>
852 +#include <linux/sched.h>
853 +#include <linux/timer.h>
854 +#include <linux/stddef.h>
855 +#include <linux/list.h>
856 +
857 +#include <linux/netfilter_ipv4/lockhelp.h>
858 +#include <linux/netfilter_ipv4/ip_tables.h>
859 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
860 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
861 +
862 +#define MAX_PORTS 8
863 +static int ports[MAX_PORTS];
864 +static int ports_n_c = 0;
865 +
866 +#ifdef MODULE_PARM
867 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
868 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
869 +#endif
870 +
871 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
872 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
873 +MODULE_LICENSE("GPL");
874 +
875 +#if 0
876 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
877 +                                       format, ## args)
878 +#else
879 +#define DEBUGP(format, args...)
880 +#endif
881 +
882 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
883 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
884 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
885 +#include <linux/netfilter_ipv4/listhelp.h>
886 +
887 +/* For future conections RPC, using client's cache bindings
888 + * I'll use ip_conntrack_lock to lock these lists         */
889 +
890 +LIST_HEAD(request_p_list_tcp);
891 +
892 +
893 +static void delete_request_p(unsigned long request_p_ul) 
894 +{
895 +       struct request_p *p = (void *)request_p_ul;
896 +       
897 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
898 +       LIST_DELETE(&request_p_list_tcp, p);
899 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
900 +       kfree(p);
901 +       return;
902 +}
903 +
904 +
905 +static void req_cl(struct request_p * r)
906 +{
907 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
908 +       del_timer(&r->timeout);
909 +       LIST_DELETE(&request_p_list_tcp, r);
910 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
911 +       kfree(r);
912 +       return;
913 +}
914 +
915 +
916 +static void clean_request(struct list_head *list)
917 +{
918 +       struct list_head *first = list->prev;
919 +       struct list_head *temp = list->next;
920 +       struct list_head *aux;
921 +
922 +       if (list_empty(list))
923 +               return;
924 +
925 +       while (first != temp) {
926 +               aux = temp->next;
927 +               req_cl((struct request_p *)temp);
928 +               temp = aux;     
929 +       }
930 +       req_cl((struct request_p *)temp);
931 +       return;
932 +}
933 +
934 +
935 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
936 +                    u_int16_t port)
937 +{
938 +       struct request_p *req_p;
939 +       
940 +       /* Verifies if entry already exists */
941 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
942 +       req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
943 +               struct request_p *, xid, ip, port);
944 +
945 +       if (req_p) {
946 +               /* Refresh timeout */
947 +               if (del_timer(&req_p->timeout)) {
948 +                       req_p->timeout.expires = jiffies + EXP;
949 +                       add_timer(&req_p->timeout);     
950 +               } 
951 +               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
952 +               return; 
953 +
954 +       }
955 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
956 +       
957 +       /* Allocate new request_p */
958 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
959 +       if (!req_p) {
960 +               DEBUGP("can't allocate request_p\n");
961 +               return;                 
962 +       }
963 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
964 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
965 +                       NULL }}); 
966 +      
967 +       /* Initialize timer */
968 +       init_timer(&req_p->timeout);
969 +       req_p->timeout.function = delete_request_p;
970 +       add_timer(&req_p->timeout); 
971 +
972 +       /* Put in list */
973 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
974 +       list_prepend(&request_p_list_tcp, req_p);
975 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
976 +       return; 
977 +
978 +}
979 +
980 +
981 +static int check_rpc_packet(const u_int32_t *data,
982 +                       int dir, struct ip_conntrack *ct,
983 +                       struct list_head request_p_list)
984 +{
985 +       struct request_p *req_p;
986 +       u_int32_t xid;
987 +       struct ip_conntrack_expect expect, *exp = &expect;
988 +
989 +        /* Translstion's buffer for XDR */
990 +        u_int16_t port_buf;
991 +
992 +
993 +       /* Get XID */
994 +       xid = *data;
995 +
996 +       /* This does sanity checking on RPC payloads,
997 +        * and permits only the RPC "get port" (3)
998 +        * in authorised procedures in client
999 +        * communications with the portmapper.
1000 +        */
1001 +
1002 +       /* perform direction dependant RPC work */
1003 +       if (dir == IP_CT_DIR_ORIGINAL) {
1004 +
1005 +               data += 5;
1006 +
1007 +               /* Get RPC requestor */
1008 +               if (IXDR_GET_INT32(data) != 3) {
1009 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
1010 +                       return NF_ACCEPT;
1011 +               }
1012 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
1013 +
1014 +               data++;
1015 +
1016 +               /* Jump Credentials and Verfifier */
1017 +               data += IXDR_GET_INT32(data) + 2;
1018 +               data += IXDR_GET_INT32(data) + 2;
1019 +
1020 +               /* Get RPC procedure */
1021 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
1022 +                       (unsigned int)IXDR_GET_INT32(data));
1023 +
1024 +               /* Get RPC protocol and store against client parameters */
1025 +               data = data + 2;
1026 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
1027 +                               ct->tuplehash[dir].tuple.src.u.all);
1028 +
1029 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1030 +                       xid, IXDR_GET_INT32(data),
1031 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
1032 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
1033 +
1034 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
1035 +                       (unsigned int)IXDR_GET_INT32(data));
1036 +
1037 +       } else {
1038 +
1039 +               /* Check for returning packet's stored counterpart */
1040 +               req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
1041 +                                 struct request_p *, xid,
1042 +                                 ct->tuplehash[!dir].tuple.src.ip,
1043 +                                 ct->tuplehash[!dir].tuple.src.u.all);
1044 +
1045 +               /* Drop unexpected packets */
1046 +               if (!req_p) {
1047 +                       DEBUGP("packet is not expected. [skip]\n");
1048 +                       return NF_ACCEPT;
1049 +               }
1050 +
1051 +               /* Verifies if packet is really an RPC reply packet */
1052 +               data = data++;
1053 +               if (IXDR_GET_INT32(data) != 1) {
1054 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
1055 +                       return NF_ACCEPT;
1056 +               }
1057 +
1058 +               /* Is status accept? */
1059 +               data++;
1060 +               if (IXDR_GET_INT32(data)) {
1061 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
1062 +                       return NF_ACCEPT;
1063 +               }
1064 +
1065 +               /* Get Verifier length. Jump verifier */
1066 +               data++;
1067 +               data = data + IXDR_GET_INT32(data) + 2;
1068 +
1069 +               /* Is accpet status "success"? */
1070 +               if (IXDR_GET_INT32(data)) {
1071 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
1072 +                       return NF_ACCEPT;
1073 +               }
1074 +
1075 +               /* Get server port number */      
1076 +               data++;
1077 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
1078 +
1079 +               /* If a packet has made it this far then it deserves an
1080 +                * expectation ...  if port == 0, then this service is 
1081 +                * not going to be registered.
1082 +                */
1083 +               if (port_buf) {
1084 +                       DEBUGP("port found: %u\n", port_buf);
1085 +
1086 +                       memset(&expect, 0, sizeof(expect));
1087 +
1088 +                       /* Watch out, Radioactive-Man! */
1089 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1090 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
1091 +                       exp->mask.src.ip = 0xffffffff;
1092 +                       exp->mask.dst.ip = 0xffffffff;
1093 +
1094 +                       switch (req_p->proto) {
1095 +                               case IPPROTO_UDP:
1096 +                                       exp->tuple.src.u.udp.port = 0;
1097 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
1098 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
1099 +                                       exp->mask.src.u.udp.port = 0;
1100 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
1101 +                                       exp->mask.dst.protonum = 0xffff;
1102 +                                       break;
1103 +
1104 +                               case IPPROTO_TCP:
1105 +                                       exp->tuple.src.u.tcp.port = 0;
1106 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
1107 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
1108 +                                       exp->mask.src.u.tcp.port = 0;
1109 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
1110 +                                       exp->mask.dst.protonum = 0xffff;
1111 +                                       break;
1112 +                       }
1113 +                       exp->expectfn = NULL;
1114 +
1115 +                       ip_conntrack_expect_related(ct, &expect);
1116 +
1117 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
1118 +                               NIPQUAD(exp->tuple.src.ip),
1119 +                               NIPQUAD(exp->tuple.dst.ip),
1120 +                               port_buf, req_p->proto);
1121 +
1122 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
1123 +                               NIPQUAD(exp->mask.src.ip),
1124 +                               NIPQUAD(exp->mask.dst.ip),
1125 +                               exp->mask.dst.protonum);
1126 +
1127 +               }
1128 +
1129 +               req_cl(req_p);
1130 +
1131 +               DEBUGP("packet evaluated. [expect]\n");
1132 +               return NF_ACCEPT;
1133 +       }
1134 +
1135 +       return NF_ACCEPT;
1136 +
1137 +}
1138 +
1139 +
1140 +/* RPC TCP helper */
1141 +static int help(const struct iphdr *iph, size_t len,
1142 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
1143 +{
1144 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
1145 +       const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
1146 +       size_t tcplen = len - iph->ihl * 4;
1147 +
1148 +       int dir = CTINFO2DIR(ctinfo);
1149 +       int crp_ret;
1150 +
1151 +
1152 +       DEBUGP("new packet to evaluate ..\n");
1153 +
1154 +       /* This works for packets like handshake packets, ignore */
1155 +       if (len == ((tcph->doff + iph->ihl) * 4)) {
1156 +               DEBUGP("packet has no data (may still be handshaking). [skip]\n");
1157 +               return NF_ACCEPT;
1158 +       }
1159 +
1160 +       /* Until there's been traffic both ways, don't look in packets. */
1161 +       if (ctinfo != IP_CT_ESTABLISHED
1162 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1163 +               DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
1164 +               DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
1165 +               DEBUGP("packet is not yet part of a two way stream. [skip]\n");
1166 +               return NF_ACCEPT;
1167 +       }
1168 +
1169 +       /* Not whole TCP header? */
1170 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
1171 +               DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
1172 +               DEBUGP("packet does not contain a complete TCP header. [skip]\n");
1173 +               return NF_ACCEPT;
1174 +       }
1175 +
1176 +       /* FIXME: Source route IP option packets --RR */
1177 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1178 +                        csum_partial((char *) tcph, tcplen, 0))) {
1179 +               DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
1180 +                    tcph, tcplen, NIPQUAD(iph->saddr),
1181 +                    NIPQUAD(iph->daddr));
1182 +               DEBUGP("[note: failure to get past this error may indicate source routing]\n");
1183 +               DEBUGP("packet contains a bad checksum. [skip]\n");
1184 +               return NF_ACCEPT;
1185 +       }
1186 +
1187 +       /* perform direction dependant protocol work */
1188 +       if (dir == IP_CT_DIR_ORIGINAL) {
1189 +
1190 +               DEBUGP("packet is from the initiator. [cont]\n");
1191 +
1192 +               /* Tests if packet len is ok */
1193 +               if ((tcplen - (tcph->doff * 4)) != 60) {
1194 +                       DEBUGP("packet length is not correct. [skip]\n");
1195 +                       return NF_ACCEPT;
1196 +               }
1197 +
1198 +       } else {
1199 +
1200 +               DEBUGP("packet is from the receiver. [cont]\n");
1201 +
1202 +               /* Tests if packet len is ok */
1203 +               if ((tcplen - (tcph->doff * 4)) != 32) {
1204 +                       DEBUGP("packet length is not correct. [skip]\n");
1205 +                       return NF_ACCEPT;
1206 +               }
1207 +       }
1208 +
1209 +       /* Get to the data */
1210 +       data++;
1211 +
1212 +       /* Check the RPC data */
1213 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
1214 +
1215 +       return crp_ret;
1216 +
1217 +}
1218 +
1219 +
1220 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
1221 +
1222 +static void fini(void);
1223 +
1224 +
1225 +static int __init init(void)
1226 +{
1227 +       int port, ret;
1228 +       static char name[10];
1229 +
1230 +
1231 +       /* If no port given, default to standard RPC port */
1232 +       if (ports[0] == 0)
1233 +               ports[0] = RPC_PORT;
1234 +
1235 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1236 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
1237 +
1238 +                if (ports[port] == RPC_PORT)
1239 +                        sprintf(name, "rpc");
1240 +                else
1241 +                        sprintf(name, "rpc-%d", port);
1242 +
1243 +               rpc_helpers[port].name = name;
1244 +               rpc_helpers[port].me = THIS_MODULE;
1245 +               rpc_helpers[port].max_expected = 1;
1246 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
1247 +               rpc_helpers[port].timeout = 0;
1248 +
1249 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
1250 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
1251 +
1252 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
1253 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
1254 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
1255 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
1256 +
1257 +               rpc_helpers[port].help = help;
1258 +
1259 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
1260 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1261 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
1262 +                       ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
1263 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
1264 +                       ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
1265 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1266 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
1267 +                       ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
1268 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
1269 +                       ntohs(rpc_helpers[port].mask.src.u.tcp.port));
1270 +
1271 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
1272 +
1273 +               if (ret) {
1274 +                       printk("ERROR registering port %d\n",
1275 +                               ports[port]);
1276 +                       fini();
1277 +                       return -EBUSY;
1278 +               }
1279 +               ports_n_c++;
1280 +       }
1281 +       return 0;
1282 +}
1283 +
1284 +
1285 +/* This function is intentionally _NOT_ defined as __exit, because 
1286 + * it is needed by the init function */
1287 +static void fini(void)
1288 +{
1289 +       int port;
1290 +
1291 +       DEBUGP("cleaning request list\n");
1292 +       clean_request(&request_p_list_tcp);
1293 +
1294 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
1295 +               DEBUGP("unregistering port %d\n", ports[port]);
1296 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
1297 +       }
1298 +}
1299 +
1300 +
1301 +module_init(init);
1302 +module_exit(fini);
1303 +
1304 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
1305 +EXPORT_SYMBOL(request_p_list_tcp);
1306 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
1307 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
1308 +
1309 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
1310 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c       1970-01-01 00:00:00.000000000 +0000
1311 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_rpc_udp.c   2004-03-16 12:04:46.000000000 +0000
1312 @@ -0,0 +1,503 @@
1313 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
1314 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
1315 + *     - original rpc tracking module
1316 + *     - "recent" connection handling for kernel 2.3+ netfilter
1317 + *
1318 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1319 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1320 + *
1321 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1322 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
1323 + *     - extended matching to support filtering on procedures
1324 + *
1325 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
1326 + *
1327 + *     This program is free software; you can redistribute it and/or
1328 + *     modify it under the terms of the GNU General Public License
1329 + *     as published by the Free Software Foundation; either version
1330 + *     2 of the License, or (at your option) any later version.
1331 + **
1332 + *     Module load syntax:
1333 + *     insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
1334 + *
1335 + *     Please give the ports of all RPC servers you wish to connect to.
1336 + *     If you don't specify ports, the default will be port 111.
1337 + **
1338 + *     Note to all:
1339 + *
1340 + *     RPCs should not be exposed to the internet - ask the Pentagon;
1341 + *
1342 + *       "The unidentified crackers pleaded guilty in July to charges
1343 + *        of juvenile delinquency stemming from a string of Pentagon
1344 + *        network intrusions in February.
1345 + *
1346 + *        The youths, going by the names TooShort and Makaveli, used
1347 + *        a common server security hole to break in, according to
1348 + *        Dane Jasper, owner of the California Internet service
1349 + *        provider, Sonic. They used the hole, known as the 'statd'
1350 + *        exploit, to attempt more than 800 break-ins, Jasper said."
1351 + *
1352 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
1353 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
1354 + **
1355 + */
1356 +
1357 +#include <linux/module.h>
1358 +#include <linux/netfilter.h>
1359 +#include <linux/ip.h>
1360 +#include <net/checksum.h>
1361 +#include <net/udp.h>
1362 +
1363 +#include <asm/param.h>
1364 +#include <linux/sched.h>
1365 +#include <linux/timer.h>
1366 +#include <linux/stddef.h>
1367 +#include <linux/list.h>
1368 +
1369 +#include <linux/netfilter_ipv4/lockhelp.h>
1370 +#include <linux/netfilter_ipv4/ip_tables.h>
1371 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1372 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
1373 +
1374 +#define MAX_PORTS 8
1375 +static int ports[MAX_PORTS];
1376 +static int ports_n_c = 0;
1377 +
1378 +#ifdef MODULE_PARM
1379 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
1380 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
1381 +#endif
1382 +
1383 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
1384 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
1385 +MODULE_LICENSE("GPL");
1386 +
1387 +#if 0
1388 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
1389 +                                       format, ## args)
1390 +#else
1391 +#define DEBUGP(format, args...)
1392 +#endif
1393 +
1394 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
1395 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
1396 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
1397 +#include <linux/netfilter_ipv4/listhelp.h>
1398 +
1399 +/* For future conections RPC, using client's cache bindings
1400 + * I'll use ip_conntrack_lock to lock these lists           */
1401 +
1402 +LIST_HEAD(request_p_list_udp);
1403 +
1404 +
1405 +static void delete_request_p(unsigned long request_p_ul)
1406 +{
1407 +       struct request_p *p = (void *)request_p_ul;
1408 +       
1409 +       WRITE_LOCK(&ipct_rpc_udp_lock);
1410 +       LIST_DELETE(&request_p_list_udp, p);
1411 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
1412 +       kfree(p);
1413 +       return;
1414 +}
1415 +
1416 +
1417 +static void req_cl(struct request_p * r)
1418 +{
1419 +       WRITE_LOCK(&ipct_rpc_udp_lock);
1420 +       del_timer(&r->timeout);
1421 +       LIST_DELETE(&request_p_list_udp, r);
1422 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
1423 +       kfree(r);
1424 +       return;
1425 +}
1426 +
1427 +
1428 +static void clean_request(struct list_head *list)
1429 +{
1430 +       struct list_head *first = list->prev;
1431 +       struct list_head *temp = list->next;
1432 +       struct list_head *aux;
1433 +
1434 +       if (list_empty(list))
1435 +               return;
1436 +
1437 +       while (first != temp) {
1438 +               aux = temp->next;
1439 +               req_cl((struct request_p *)temp);
1440 +               temp = aux;     
1441 +       }
1442 +       req_cl((struct request_p *)temp);
1443 +       return;
1444 +}
1445 +
1446 +
1447 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
1448 +                    u_int16_t port)
1449 +{
1450 +       struct request_p *req_p;
1451 +        
1452 +       /* Verifies if entry already exists */
1453 +       WRITE_LOCK(&ipct_rpc_udp_lock);
1454 +       req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
1455 +               struct request_p *, xid, ip, port);
1456 +
1457 +       if (req_p) {
1458 +               /* Refresh timeout */
1459 +               if (del_timer(&req_p->timeout)) {
1460 +                       req_p->timeout.expires = jiffies + EXP;
1461 +                       add_timer(&req_p->timeout);     
1462 +               } 
1463 +               WRITE_UNLOCK(&ipct_rpc_udp_lock);
1464 +               return; 
1465 +
1466 +       }
1467 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
1468 +       
1469 +       /* Allocate new request_p */
1470 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
1471 +       if (!req_p) {
1472 +               DEBUGP("can't allocate request_p\n");
1473 +               return;                 
1474 +       }
1475 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
1476 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
1477 +                       NULL }}); 
1478 +      
1479 +       /* Initialize timer */
1480 +       init_timer(&req_p->timeout);
1481 +       req_p->timeout.function = delete_request_p;
1482 +       add_timer(&req_p->timeout); 
1483 +
1484 +       /* Put in list */
1485 +       WRITE_LOCK(&ipct_rpc_udp_lock);
1486 +       list_prepend(&request_p_list_udp, req_p);
1487 +       WRITE_UNLOCK(&ipct_rpc_udp_lock); 
1488 +       return; 
1489 +
1490 +}
1491 +
1492 +
1493 +static int check_rpc_packet(const u_int32_t *data,
1494 +                       int dir, struct ip_conntrack *ct,
1495 +                       struct list_head request_p_list)
1496 +{
1497 +       struct request_p *req_p;
1498 +       u_int32_t xid;
1499 +       struct ip_conntrack_expect expect, *exp = &expect;
1500 +
1501 +       /* Translstion's buffer for XDR */
1502 +       u_int16_t port_buf;
1503 +
1504 +
1505 +       /* Get XID */
1506 +       xid = *data;
1507 +
1508 +       /* This does sanity checking on RPC payloads,
1509 +        * and permits only the RPC "get port" (3)
1510 +        * in authorised procedures in client
1511 +        * communications with the portmapper.
1512 +        */
1513 +
1514 +       /* perform direction dependant RPC work */
1515 +       if (dir == IP_CT_DIR_ORIGINAL) {
1516 +
1517 +               data += 5;
1518 +
1519 +               /* Get RPC requestor */
1520 +               if (IXDR_GET_INT32(data) != 3) {
1521 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
1522 +                       return NF_ACCEPT;
1523 +               }
1524 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
1525 +
1526 +               data++;
1527 +
1528 +               /* Jump Credentials and Verfifier */
1529 +               data = data + IXDR_GET_INT32(data) + 2;
1530 +               data = data + IXDR_GET_INT32(data) + 2;
1531 +
1532 +               /* Get RPC procedure */
1533 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
1534 +                       (unsigned int)IXDR_GET_INT32(data));
1535 +
1536 +               /* Get RPC protocol and store against client parameters */
1537 +               data = data + 2;
1538 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
1539 +                               ct->tuplehash[dir].tuple.src.u.all);
1540 +
1541 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1542 +                       xid, IXDR_GET_INT32(data),
1543 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
1544 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
1545 +
1546 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
1547 +                       (unsigned int)IXDR_GET_INT32(data));
1548 +
1549 +       } else {
1550 +
1551 +               /* Check for returning packet's stored counterpart */
1552 +               req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
1553 +                                 struct request_p *, xid,
1554 +                                 ct->tuplehash[!dir].tuple.src.ip,
1555 +                                 ct->tuplehash[!dir].tuple.src.u.all);
1556 +
1557 +               /* Drop unexpected packets */
1558 +               if (!req_p) {
1559 +                       DEBUGP("packet is not expected. [skip]\n");
1560 +                       return NF_ACCEPT;
1561 +               }
1562 +
1563 +               /* Verifies if packet is really an RPC reply packet */
1564 +               data = data++;
1565 +               if (IXDR_GET_INT32(data) != 1) {
1566 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
1567 +                       return NF_ACCEPT;
1568 +               }
1569 +
1570 +               /* Is status accept? */
1571 +               data++;
1572 +               if (IXDR_GET_INT32(data)) {
1573 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
1574 +                       return NF_ACCEPT;
1575 +               }
1576 +
1577 +               /* Get Verifier length. Jump verifier */
1578 +               data++;
1579 +               data = data + IXDR_GET_INT32(data) + 2;
1580 +
1581 +               /* Is accpet status "success"? */
1582 +               if (IXDR_GET_INT32(data)) {
1583 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
1584 +                       return NF_ACCEPT;
1585 +               }
1586 +
1587 +               /* Get server port number */      
1588 +               data++;
1589 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
1590 +
1591 +               /* If a packet has made it this far then it deserves an
1592 +                * expectation ...  if port == 0, then this service is 
1593 +                * not going to be registered.
1594 +                */
1595 +               if (port_buf) {
1596 +                       DEBUGP("port found: %u\n", port_buf);
1597 +
1598 +                       memset(&expect, 0, sizeof(expect));
1599 +
1600 +                       /* Watch out, Radioactive-Man! */
1601 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1602 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
1603 +                       exp->mask.src.ip = 0xffffffff;
1604 +                       exp->mask.dst.ip = 0xffffffff;
1605 +
1606 +                       switch (req_p->proto) {
1607 +                               case IPPROTO_UDP:
1608 +                                       exp->tuple.src.u.udp.port = 0;
1609 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
1610 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
1611 +                                       exp->mask.src.u.udp.port = 0;
1612 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
1613 +                                       exp->mask.dst.protonum = 0xffff;
1614 +                                       break;
1615 +
1616 +                               case IPPROTO_TCP:
1617 +                                       exp->tuple.src.u.tcp.port = 0;
1618 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
1619 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
1620 +                                       exp->mask.src.u.tcp.port = 0;
1621 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
1622 +                                       exp->mask.dst.protonum = 0xffff;
1623 +                                       break;
1624 +                       }
1625 +                       exp->expectfn = NULL;
1626 +
1627 +                       ip_conntrack_expect_related(ct, &expect);
1628 +
1629 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
1630 +                               NIPQUAD(exp->tuple.src.ip),
1631 +                               NIPQUAD(exp->tuple.dst.ip),
1632 +                               port_buf, req_p->proto);
1633 +
1634 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
1635 +                               NIPQUAD(exp->mask.src.ip),
1636 +                               NIPQUAD(exp->mask.dst.ip),
1637 +                               exp->mask.dst.protonum);
1638 +
1639 +               }
1640 +
1641 +               req_cl(req_p);
1642 +
1643 +               DEBUGP("packet evaluated. [expect]\n");
1644 +               return NF_ACCEPT;
1645 +       }
1646 +
1647 +       return NF_ACCEPT;
1648 +
1649 +}
1650 +
1651 +
1652 +/* RPC UDP helper */
1653 +static int help(const struct iphdr *iph, size_t len,
1654 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
1655 +{
1656 +       struct udphdr *udph = (void *) iph + iph->ihl * 4;
1657 +       const u_int32_t *data = (const u_int32_t *)udph + 2;
1658 +       size_t udplen = len - iph->ihl * 4;
1659 +       int dir = CTINFO2DIR(ctinfo);
1660 +       int crp_ret;
1661 +
1662 +       /* Checksum */
1663 +       const u_int16_t *chsm = (const u_int16_t *)udph + 3;
1664 +
1665 +
1666 +       DEBUGP("new packet to evaluate ..\n");
1667 +
1668 +       /* Not whole UDP header? */
1669 +       if (udplen < sizeof(struct udphdr)) {
1670 +               DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
1671 +               DEBUGP("packet does not contain a complete UDP header. [skip]\n");
1672 +               return NF_ACCEPT;
1673 +       }
1674 +
1675 +       /* FIXME: Source route IP option packets --RR */
1676 +       if (*chsm) {
1677 +               if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
1678 +                   csum_partial((char *)udph, udplen, 0))) {
1679 +                       DEBUGP("[note: failure to get past this error may indicate source routing]\n");
1680 +                       DEBUGP("packet contains a bad checksum. [skip]\n");
1681 +                       return NF_ACCEPT;
1682 +                  } 
1683 +       }
1684 +
1685 +       /* perform direction dependant protocol work */
1686 +       if (dir == IP_CT_DIR_ORIGINAL) {
1687 +
1688 +               DEBUGP("packet is from the initiator. [cont]\n");
1689 +
1690 +               /* Tests if packet len is ok */
1691 +               if ((udplen - sizeof(struct udphdr)) != 56) {
1692 +                       DEBUGP("packet length is not correct. [skip]\n");
1693 +                       return NF_ACCEPT;
1694 +               }
1695 +
1696 +       } else {
1697 +
1698 +               DEBUGP("packet is from the receiver. [cont]\n");
1699 +
1700 +               /* Until there's been traffic both ways, don't look in packets. */
1701 +               if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1702 +                       DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
1703 +                       DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
1704 +                       DEBUGP("packet is not yet part of a two way stream. [skip]\n");
1705 +                       return NF_ACCEPT;
1706 +               }
1707 +
1708 +               /* Tests if packet len is ok */
1709 +                       if ((udplen - sizeof(struct udphdr)) != 28) {
1710 +                       DEBUGP("packet length is not correct. [skip]\n");
1711 +                       return NF_ACCEPT;
1712 +               }
1713 +
1714 +       }
1715 +
1716 +       /* Get to the data */
1717 +       /* udp *data == *correct */
1718 +
1719 +       /* Check the RPC data */
1720 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
1721 +
1722 +       return crp_ret;
1723 +
1724 +}
1725 +
1726 +
1727 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
1728 +
1729 +static void fini(void);
1730 +
1731 +
1732 +static int __init init(void)
1733 +{
1734 +       int port, ret;
1735 +       static char name[10];
1736 +
1737 +
1738 +       /* If no port given, default to standard RPC port */
1739 +       if (ports[0] == 0)
1740 +               ports[0] = RPC_PORT;
1741 +
1742 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1743 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
1744 +
1745 +                if (ports[port] == RPC_PORT)
1746 +                        sprintf(name, "rpc");
1747 +                else
1748 +                        sprintf(name, "rpc-%d", port);
1749 +
1750 +               rpc_helpers[port].name = name;
1751 +               rpc_helpers[port].me = THIS_MODULE;
1752 +               rpc_helpers[port].max_expected = 1;
1753 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
1754 +               rpc_helpers[port].timeout = 0;
1755 +
1756 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
1757 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
1758 +
1759 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
1760 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
1761 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
1762 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
1763 +
1764 +               rpc_helpers[port].help = help;
1765 +
1766 +               DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
1767 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1768 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
1769 +                       ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
1770 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
1771 +                       ntohs(rpc_helpers[port].tuple.src.u.udp.port));
1772 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1773 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
1774 +                       ntohs(rpc_helpers[port].mask.dst.u.udp.port),
1775 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
1776 +                       ntohs(rpc_helpers[port].mask.src.u.udp.port));
1777 +
1778 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
1779 +
1780 +               if (ret) {
1781 +                       printk("ERROR registering port %d\n",
1782 +                               ports[port]);
1783 +                       fini();
1784 +                       return -EBUSY;
1785 +               }
1786 +               ports_n_c++;
1787 +       }
1788 +       return 0;
1789 +}
1790 +
1791 +
1792 +/* This function is intentionally _NOT_ defined as __exit, because 
1793 + * it is needed by the init function */
1794 +static void fini(void)
1795 +{
1796 +       int port;
1797 +
1798 +       DEBUGP("cleaning request list\n");
1799 +       clean_request(&request_p_list_udp);
1800 +
1801 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
1802 +               DEBUGP("unregistering port %d\n", ports[port]);
1803 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
1804 +       }
1805 +}
1806 +
1807 +
1808 +module_init(init);
1809 +module_exit(fini);
1810 +
1811 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
1812 +EXPORT_SYMBOL(request_p_list_udp);
1813 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
1814 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
1815 +
1816 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_rtsp.c
1817 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_rtsp.c  1970-01-01 00:00:00.000000000 +0000
1818 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_rtsp.c      2004-03-16 12:04:49.000000000 +0000
1819 @@ -0,0 +1,509 @@
1820 +/*
1821 + * RTSP extension for IP connection tracking
1822 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
1823 + * based on ip_conntrack_irc.c
1824 + *
1825 + *      This program is free software; you can redistribute it and/or
1826 + *      modify it under the terms of the GNU General Public License
1827 + *      as published by the Free Software Foundation; either version
1828 + *      2 of the License, or (at your option) any later version.
1829 + *
1830 + * Module load syntax:
1831 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
1832 + *                              max_outstanding=n setup_timeout=secs
1833 + *
1834 + * If no ports are specified, the default will be port 554.
1835 + *
1836 + * With max_outstanding you can define the maximum number of not yet
1837 + * answered SETUP requests per RTSP session (default 8).
1838 + * With setup_timeout you can specify how long the system waits for
1839 + * an expected data channel (default 300 seconds).
1840 + */
1841 +
1842 +#include <linux/config.h>
1843 +#include <linux/module.h>
1844 +#include <linux/netfilter.h>
1845 +#include <linux/ip.h>
1846 +#include <net/checksum.h>
1847 +#include <net/tcp.h>
1848 +
1849 +#include <linux/netfilter_ipv4/lockhelp.h>
1850 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1851 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
1852 +
1853 +#include <linux/ctype.h>
1854 +#define NF_NEED_STRNCASECMP
1855 +#define NF_NEED_STRTOU16
1856 +#define NF_NEED_STRTOU32
1857 +#define NF_NEED_NEXTLINE
1858 +#include <linux/netfilter_helpers.h>
1859 +#define NF_NEED_MIME_NEXTLINE
1860 +#include <linux/netfilter_mime.h>
1861 +
1862 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
1863 +
1864 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
1865 +#ifdef IP_NF_RTSP_DEBUG
1866 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args)
1867 +#else
1868 +#define DEBUGP(args...)
1869 +#endif
1870 +
1871 +#define MAX_PORTS 8
1872 +static int ports[MAX_PORTS];
1873 +static int num_ports = 0;
1874 +static int max_outstanding = 8;
1875 +static unsigned int setup_timeout = 300;
1876 +
1877 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
1878 +MODULE_DESCRIPTION("RTSP connection tracking module");
1879 +MODULE_LICENSE("GPL");
1880 +#ifdef MODULE_PARM
1881 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
1882 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
1883 +MODULE_PARM(max_outstanding, "i");
1884 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
1885 +MODULE_PARM(setup_timeout, "i");
1886 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
1887 +#endif
1888 +
1889 +DECLARE_LOCK(ip_rtsp_lock);
1890 +struct module* ip_conntrack_rtsp = THIS_MODULE;
1891 +
1892 +/*
1893 + * Max mappings we will allow for one RTSP connection (for RTP, the number
1894 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
1895 + * ports so keep this reasonably high.  If this is too low, you will see a
1896 + * lot of "no free client map entries" messages.
1897 + */
1898 +#define MAX_PORT_MAPS 16
1899 +
1900 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
1901 +
1902 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
1903 +
1904 +/*
1905 + * Parse an RTSP packet.
1906 + *
1907 + * Returns zero if parsing failed.
1908 + *
1909 + * Parameters:
1910 + *  IN      ptcp        tcp data pointer
1911 + *  IN      tcplen      tcp data len
1912 + *  IN/OUT  ptcpoff     points to current tcp offset
1913 + *  OUT     phdrsoff    set to offset of rtsp headers
1914 + *  OUT     phdrslen    set to length of rtsp headers
1915 + *  OUT     pcseqoff    set to offset of CSeq header
1916 + *  OUT     pcseqlen    set to length of CSeq header
1917 + */
1918 +static int
1919 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
1920 +                   uint* phdrsoff, uint* phdrslen,
1921 +                   uint* pcseqoff, uint* pcseqlen)
1922 +{
1923 +    uint    entitylen = 0;
1924 +    uint    lineoff;
1925 +    uint    linelen;
1926 +
1927 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
1928 +    {
1929 +        return 0;
1930 +    }
1931 +
1932 +    *phdrsoff = *ptcpoff;
1933 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
1934 +    {
1935 +        if (linelen == 0)
1936 +        {
1937 +            if (entitylen > 0)
1938 +            {
1939 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
1940 +            }
1941 +            break;
1942 +        }
1943 +        if (lineoff+linelen > tcplen)
1944 +        {
1945 +            INFOP("!! overrun !!\n");
1946 +            break;
1947 +        }
1948 +
1949 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
1950 +        {
1951 +            *pcseqoff = lineoff;
1952 +            *pcseqlen = linelen;
1953 +        }
1954 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
1955 +        {
1956 +            uint off = lineoff+15;
1957 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
1958 +            nf_strtou32(ptcp+off, &entitylen);
1959 +        }
1960 +    }
1961 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
1962 +
1963 +    return 1;
1964 +}
1965 +
1966 +/*
1967 + * Find lo/hi client ports (if any) in transport header
1968 + * In:
1969 + *   ptcp, tcplen = packet
1970 + *   tranoff, tranlen = buffer to search
1971 + *
1972 + * Out:
1973 + *   pport_lo, pport_hi = lo/hi ports (host endian)
1974 + *
1975 + * Returns nonzero if any client ports found
1976 + *
1977 + * Note: it is valid (and expected) for the client to request multiple
1978 + * transports, so we need to parse the entire line.
1979 + */
1980 +static int
1981 +rtsp_parse_transport(char* ptran, uint tranlen,
1982 +                     struct ip_ct_rtsp_expect* prtspexp)
1983 +{
1984 +    int     rc = 0;
1985 +    uint    off = 0;
1986 +
1987 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
1988 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
1989 +    {
1990 +        INFOP("sanity check failed\n");
1991 +        return 0;
1992 +    }
1993 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
1994 +    off += 10;
1995 +    SKIP_WSPACE(ptran, tranlen, off);
1996 +
1997 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
1998 +    while (off < tranlen)
1999 +    {
2000 +        const char* pparamend;
2001 +        uint        nextparamoff;
2002 +
2003 +        pparamend = memchr(ptran+off, ',', tranlen-off);
2004 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
2005 +        nextparamoff = pparamend-ptran;
2006 +
2007 +        while (off < nextparamoff)
2008 +        {
2009 +            const char* pfieldend;
2010 +            uint        nextfieldoff;
2011 +
2012 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
2013 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
2014 +
2015 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
2016 +            {
2017 +                u_int16_t   port;
2018 +                uint        numlen;
2019 +
2020 +                off += 12;
2021 +                numlen = nf_strtou16(ptran+off, &port);
2022 +                off += numlen;
2023 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
2024 +                {
2025 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
2026 +                }
2027 +                else
2028 +                {
2029 +                    prtspexp->loport = prtspexp->hiport = port;
2030 +                    if (ptran[off] == '-')
2031 +                    {
2032 +                        off++;
2033 +                        numlen = nf_strtou16(ptran+off, &port);
2034 +                        off += numlen;
2035 +                        prtspexp->pbtype = pb_range;
2036 +                        prtspexp->hiport = port;
2037 +
2038 +                        // If we have a range, assume rtp:
2039 +                        // loport must be even, hiport must be loport+1
2040 +                        if ((prtspexp->loport & 0x0001) != 0 ||
2041 +                            prtspexp->hiport != prtspexp->loport+1)
2042 +                        {
2043 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
2044 +                                   prtspexp->loport, prtspexp->hiport);
2045 +                            prtspexp->loport &= 0xfffe;
2046 +                            prtspexp->hiport = prtspexp->loport+1;
2047 +                        }
2048 +                    }
2049 +                    else if (ptran[off] == '/')
2050 +                    {
2051 +                        off++;
2052 +                        numlen = nf_strtou16(ptran+off, &port);
2053 +                        off += numlen;
2054 +                        prtspexp->pbtype = pb_discon;
2055 +                        prtspexp->hiport = port;
2056 +                    }
2057 +                    rc = 1;
2058 +                }
2059 +            }
2060 +
2061 +            /*
2062 +             * Note we don't look for the destination parameter here.
2063 +             * If we are using NAT, the NAT module will handle it.  If not,
2064 +             * and the client is sending packets elsewhere, the expectation
2065 +             * will quietly time out.
2066 +             */
2067 +
2068 +            off = nextfieldoff;
2069 +        }
2070 +
2071 +        off = nextparamoff;
2072 +    }
2073 +
2074 +    return rc;
2075 +}
2076 +
2077 +/*** conntrack functions ***/
2078 +
2079 +/* outbound packet: client->server */
2080 +static int
2081 +help_out(const struct iphdr* iph, size_t pktlen,
2082 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
2083 +{
2084 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
2085 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
2086 +    uint    tcplen = pktlen - iph->ihl * 4;
2087 +    char*   pdata = (char*)tcph + tcph->doff * 4;
2088 +    uint    datalen = tcplen - tcph->doff * 4;
2089 +    uint    dataoff = 0;
2090 +
2091 +    struct ip_conntrack_expect exp;
2092 +
2093 +    while (dataoff < datalen)
2094 +    {
2095 +        uint    cmdoff = dataoff;
2096 +        uint    hdrsoff = 0;
2097 +        uint    hdrslen = 0;
2098 +        uint    cseqoff = 0;
2099 +        uint    cseqlen = 0;
2100 +        uint    lineoff = 0;
2101 +        uint    linelen = 0;
2102 +        uint    off;
2103 +        int     rc;
2104 +
2105 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
2106 +                                &hdrsoff, &hdrslen,
2107 +                                &cseqoff, &cseqlen))
2108 +        {
2109 +            break;      /* not a valid message */
2110 +        }
2111 +
2112 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
2113 +        {
2114 +            continue;   /* not a SETUP message */
2115 +        }
2116 +        DEBUGP("found a setup message\n");
2117 +
2118 +        memset(&exp, 0, sizeof(exp));
2119 +
2120 +        off = 0;
2121 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
2122 +                                &lineoff, &linelen))
2123 +        {
2124 +            if (linelen == 0)
2125 +            {
2126 +                break;
2127 +            }
2128 +            if (off > hdrsoff+hdrslen)
2129 +            {
2130 +                INFOP("!! overrun !!");
2131 +                break;
2132 +            }
2133 +
2134 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
2135 +            {
2136 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
2137 +                                     &exp.help.exp_rtsp_info);
2138 +            }
2139 +        }
2140 +
2141 +        if (exp.help.exp_rtsp_info.loport == 0)
2142 +        {
2143 +            DEBUGP("no udp transports found\n");
2144 +            continue;   /* no udp transports found */
2145 +        }
2146 +
2147 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
2148 +              (int)exp.help.exp_rtsp_info.pbtype,
2149 +              exp.help.exp_rtsp_info.loport,
2150 +              exp.help.exp_rtsp_info.hiport);
2151 +
2152 +        LOCK_BH(&ip_rtsp_lock);
2153 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
2154 +        exp.help.exp_rtsp_info.len = hdrslen;
2155 +
2156 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
2157 +        exp.mask.src.ip  = 0xffffffff;
2158 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
2159 +        exp.mask.dst.ip  = 0xffffffff;
2160 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
2161 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
2162 +        exp.tuple.dst.protonum = IPPROTO_UDP;
2163 +        exp.mask.dst.protonum  = 0xffff;
2164 +
2165 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
2166 +                NIPQUAD(exp.tuple.src.ip),
2167 +                ntohs(exp.tuple.src.u.tcp.port),
2168 +                NIPQUAD(exp.tuple.dst.ip),
2169 +                ntohs(exp.tuple.dst.u.tcp.port));
2170 +
2171 +        /* pass the request off to the nat helper */
2172 +        rc = ip_conntrack_expect_related(ct, &exp);
2173 +        UNLOCK_BH(&ip_rtsp_lock);
2174 +        if (rc == 0)
2175 +        {
2176 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
2177 +        }
2178 +        else
2179 +        {
2180 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
2181 +        }
2182 +    }
2183 +
2184 +    return NF_ACCEPT;
2185 +}
2186 +
2187 +/* inbound packet: server->client */
2188 +static int
2189 +help_in(const struct iphdr* iph, size_t pktlen,
2190 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
2191 +{
2192 +    return NF_ACCEPT;
2193 +}
2194 +
2195 +static int
2196 +help(const struct iphdr* iph, size_t pktlen,
2197 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
2198 +{
2199 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
2200 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
2201 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
2202 +
2203 +    /* Until there's been traffic both ways, don't look in packets. */
2204 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
2205 +    {
2206 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
2207 +        return NF_ACCEPT;
2208 +    }
2209 +
2210 +    /* Not whole TCP header? */
2211 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
2212 +    {
2213 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
2214 +        return NF_ACCEPT;
2215 +    }
2216 +
2217 +    /* Checksum invalid?  Ignore. */
2218 +    /* FIXME: Source route IP option packets --RR */
2219 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2220 +                     csum_partial((char*)tcph, tcplen, 0)))
2221 +    {
2222 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2223 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
2224 +        return NF_ACCEPT;
2225 +    }
2226 +
2227 +    switch (CTINFO2DIR(ctinfo))
2228 +    {
2229 +    case IP_CT_DIR_ORIGINAL:
2230 +        help_out(iph, pktlen, ct, ctinfo);
2231 +        break;
2232 +    case IP_CT_DIR_REPLY:
2233 +        help_in(iph, pktlen, ct, ctinfo);
2234 +        break;
2235 +    default:
2236 +        /* oops */
2237 +    }
2238 +
2239 +    return NF_ACCEPT;
2240 +}
2241 +
2242 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
2243 +static char rtsp_names[MAX_PORTS][10];
2244 +
2245 +/* This function is intentionally _NOT_ defined as __exit */
2246 +static void
2247 +fini(void)
2248 +{
2249 +    int i;
2250 +    for (i = 0; i < num_ports; i++)
2251 +    {
2252 +        DEBUGP("unregistering port %d\n", ports[i]);
2253 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
2254 +    }
2255 +}
2256 +
2257 +static int __init
2258 +init(void)
2259 +{
2260 +    int i, ret;
2261 +    struct ip_conntrack_helper *hlpr;
2262 +    char *tmpname;
2263 +
2264 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
2265 +
2266 +    if (max_outstanding < 1)
2267 +    {
2268 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
2269 +        return -EBUSY;
2270 +    }
2271 +    if (setup_timeout < 0)
2272 +    {
2273 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
2274 +        return -EBUSY;
2275 +    }
2276 +
2277 +    /* If no port given, default to standard rtsp port */
2278 +    if (ports[0] == 0)
2279 +    {
2280 +        ports[0] = RTSP_PORT;
2281 +    }
2282 +
2283 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
2284 +    {
2285 +        hlpr = &rtsp_helpers[i];
2286 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
2287 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
2288 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
2289 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
2290 +        hlpr->mask.dst.protonum = 0xFFFF;
2291 +        hlpr->max_expected = max_outstanding;
2292 +        hlpr->timeout = setup_timeout;
2293 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
2294 +        hlpr->me = ip_conntrack_rtsp;
2295 +        hlpr->help = help;
2296 +
2297 +        tmpname = &rtsp_names[i][0];
2298 +        if (ports[i] == RTSP_PORT)
2299 +        {
2300 +            sprintf(tmpname, "rtsp");
2301 +        }
2302 +        else
2303 +        {
2304 +            sprintf(tmpname, "rtsp-%d", i);
2305 +        }
2306 +        hlpr->name = tmpname;
2307 +
2308 +        DEBUGP("port #%d: %d\n", i, ports[i]);
2309 +
2310 +        ret = ip_conntrack_helper_register(hlpr);
2311 +
2312 +        if (ret)
2313 +        {
2314 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
2315 +            fini();
2316 +            return -EBUSY;
2317 +        }
2318 +        num_ports++;
2319 +    }
2320 +    return 0;
2321 +}
2322 +
2323 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2324 +EXPORT_SYMBOL(ip_rtsp_lock);
2325 +#endif
2326 +
2327 +module_init(init);
2328 +module_exit(fini);
2329 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c
2330 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-03-16 12:00:23.000000000 +0000
2331 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-03-16 12:04:09.000000000 +0000
2332 @@ -110,6 +110,9 @@
2333                 len += sprintf(buffer + len, "[ASSURED] ");
2334         len += sprintf(buffer + len, "use=%u ",
2335                        atomic_read(&conntrack->ct_general.use));
2336 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
2337 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
2338 +#endif
2339         len += sprintf(buffer + len, "\n");
2340  
2341         return len;
2342 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.5-rc1/net/ipv4/netfilter/ip_nat_rtsp.c
2343 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_nat_rtsp.c        1970-01-01 00:00:00.000000000 +0000
2344 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ip_nat_rtsp.c    2004-03-16 12:04:49.000000000 +0000
2345 @@ -0,0 +1,625 @@
2346 +/*
2347 + * RTSP extension for TCP NAT alteration
2348 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
2349 + * based on ip_nat_irc.c
2350 + *
2351 + *      This program is free software; you can redistribute it and/or
2352 + *      modify it under the terms of the GNU General Public License
2353 + *      as published by the Free Software Foundation; either version
2354 + *      2 of the License, or (at your option) any later version.
2355 + *
2356 + * Module load syntax:
2357 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
2358 + *                           stunaddr=<address>
2359 + *                           destaction=[auto|strip|none]
2360 + *
2361 + * If no ports are specified, the default will be port 554 only.
2362 + *
2363 + * stunaddr specifies the address used to detect that a client is using STUN.
2364 + * If this address is seen in the destination parameter, it is assumed that
2365 + * the client has already punched a UDP hole in the firewall, so we don't
2366 + * mangle the client_port.  If none is specified, it is autodetected.  It
2367 + * only needs to be set if you have multiple levels of NAT.  It should be
2368 + * set to the external address that the STUN clients detect.  Note that in
2369 + * this case, it will not be possible for clients to use UDP with servers
2370 + * between the NATs.
2371 + *
2372 + * If no destaction is specified, auto is used.
2373 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
2374 + *   destaction=strip: always strip destination parameter (not recommended).
2375 + *   destaction=none:  do not touch destination parameter (not recommended).
2376 + */
2377 +
2378 +#include <linux/module.h>
2379 +#include <linux/netfilter_ipv4.h>
2380 +#include <linux/ip.h>
2381 +#include <linux/tcp.h>
2382 +#include <linux/kernel.h>
2383 +#include <net/tcp.h>
2384 +#include <linux/netfilter_ipv4/ip_nat.h>
2385 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
2386 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
2387 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
2388 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2389 +
2390 +#include <linux/inet.h>
2391 +#include <linux/ctype.h>
2392 +#define NF_NEED_STRNCASECMP
2393 +#define NF_NEED_STRTOU16
2394 +#include <linux/netfilter_helpers.h>
2395 +#define NF_NEED_MIME_NEXTLINE
2396 +#include <linux/netfilter_mime.h>
2397 +
2398 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
2399 +#ifdef IP_NF_RTSP_DEBUG
2400 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args);
2401 +#else
2402 +#define DEBUGP(args...)
2403 +#endif
2404 +
2405 +#define MAX_PORTS       8
2406 +#define DSTACT_AUTO     0
2407 +#define DSTACT_STRIP    1
2408 +#define DSTACT_NONE     2
2409 +
2410 +static int      ports[MAX_PORTS];
2411 +static char*    stunaddr = NULL;
2412 +static char*    destaction = NULL;
2413 +
2414 +static int       num_ports = 0;
2415 +static u_int32_t extip = 0;
2416 +static int       dstact = 0;
2417 +
2418 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
2419 +MODULE_DESCRIPTION("RTSP network address translation module");
2420 +MODULE_LICENSE("GPL");
2421 +#ifdef MODULE_PARM
2422 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2423 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
2424 +MODULE_PARM(stunaddr, "s");
2425 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
2426 +MODULE_PARM(destaction, "s");
2427 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
2428 +#endif
2429 +
2430 +/* protects rtsp part of conntracks */
2431 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
2432 +
2433 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
2434 +
2435 +/*** helper functions ***/
2436 +
2437 +static void
2438 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
2439 +{
2440 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
2441 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
2442 +
2443 +    *pptcpdata = (char*)tcph + tcph->doff*4;
2444 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
2445 +}
2446 +
2447 +/*** nat functions ***/
2448 +
2449 +/*
2450 + * Mangle the "Transport:" header:
2451 + *   - Replace all occurences of "client_port=<spec>"
2452 + *   - Handle destination parameter
2453 + *
2454 + * In:
2455 + *   ct, ctinfo = conntrack context
2456 + *   pskb       = packet
2457 + *   tranoff    = Transport header offset from TCP data
2458 + *   tranlen    = Transport header length (incl. CRLF)
2459 + *   rport_lo   = replacement low  port (host endian)
2460 + *   rport_hi   = replacement high port (host endian)
2461 + *
2462 + * Returns packet size difference.
2463 + *
2464 + * Assumes that a complete transport header is present, ending with CR or LF
2465 + */
2466 +static int
2467 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
2468 +                 struct ip_conntrack_expect* exp,
2469 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
2470 +{
2471 +    char*       ptcp;
2472 +    uint        tcplen;
2473 +    char*       ptran;
2474 +    char        rbuf1[16];      /* Replacement buffer (one port) */
2475 +    uint        rbuf1len;       /* Replacement len (one port) */
2476 +    char        rbufa[16];      /* Replacement buffer (all ports) */
2477 +    uint        rbufalen;       /* Replacement len (all ports) */
2478 +    u_int32_t   newip;
2479 +    u_int16_t   loport, hiport;
2480 +    uint        off = 0;
2481 +    uint        diff;           /* Number of bytes we removed */
2482 +
2483 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
2484 +    struct ip_conntrack_tuple t;
2485 +
2486 +    char    szextaddr[15+1];
2487 +    uint    extaddrlen;
2488 +    int     is_stun;
2489 +
2490 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
2491 +    ptran = ptcp+tranoff;
2492 +
2493 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
2494 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
2495 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
2496 +    {
2497 +        INFOP("sanity check failed\n");
2498 +        return 0;
2499 +    }
2500 +    off += 10;
2501 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
2502 +
2503 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
2504 +    t = exp->tuple;
2505 +    t.dst.ip = newip;
2506 +
2507 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
2508 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
2509 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
2510 +
2511 +    rbuf1len = rbufalen = 0;
2512 +    switch (prtspexp->pbtype)
2513 +    {
2514 +    case pb_single:
2515 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
2516 +        {
2517 +            t.dst.u.udp.port = htons(loport);
2518 +            if (ip_conntrack_change_expect(exp, &t) == 0)
2519 +            {
2520 +                DEBUGP("using port %hu\n", loport);
2521 +                break;
2522 +            }
2523 +        }
2524 +        if (loport != 0)
2525 +        {
2526 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
2527 +            rbufalen = sprintf(rbufa, "%hu", loport);
2528 +        }
2529 +        break;
2530 +    case pb_range:
2531 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
2532 +        {
2533 +            t.dst.u.udp.port = htons(loport);
2534 +            if (ip_conntrack_change_expect(exp, &t) == 0)
2535 +            {
2536 +                hiport = loport + ~exp->mask.dst.u.udp.port;
2537 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
2538 +                break;
2539 +            }
2540 +        }
2541 +        if (loport != 0)
2542 +        {
2543 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
2544 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
2545 +        }
2546 +        break;
2547 +    case pb_discon:
2548 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
2549 +        {
2550 +            t.dst.u.udp.port = htons(loport);
2551 +            if (ip_conntrack_change_expect(exp, &t) == 0)
2552 +            {
2553 +                DEBUGP("using port %hu (1 of 2)\n", loport);
2554 +                break;
2555 +            }
2556 +        }
2557 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
2558 +        {
2559 +            t.dst.u.udp.port = htons(hiport);
2560 +            if (ip_conntrack_change_expect(exp, &t) == 0)
2561 +            {
2562 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
2563 +                break;
2564 +            }
2565 +        }
2566 +        if (loport != 0 && hiport != 0)
2567 +        {
2568 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
2569 +            if (hiport == loport+1)
2570 +            {
2571 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
2572 +            }
2573 +            else
2574 +            {
2575 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
2576 +            }
2577 +        }
2578 +        break;
2579 +    default:
2580 +        /* oops */
2581 +    }
2582 +
2583 +    if (rbuf1len == 0)
2584 +    {
2585 +        return 0;   /* cannot get replacement port(s) */
2586 +    }
2587 +
2588 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
2589 +    while (off < tranlen)
2590 +    {
2591 +        uint        saveoff;
2592 +        const char* pparamend;
2593 +        uint        nextparamoff;
2594 +
2595 +        pparamend = memchr(ptran+off, ',', tranlen-off);
2596 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
2597 +        nextparamoff = pparamend-ptcp;
2598 +
2599 +        /*
2600 +         * We pass over each param twice.  On the first pass, we look for a
2601 +         * destination= field.  It is handled by the security policy.  If it
2602 +         * is present, allowed, and equal to our external address, we assume
2603 +         * that STUN is being used and we leave the client_port= field alone.
2604 +         */
2605 +        is_stun = 0;
2606 +        saveoff = off;
2607 +        while (off < nextparamoff)
2608 +        {
2609 +            const char* pfieldend;
2610 +            uint        nextfieldoff;
2611 +
2612 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
2613 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
2614 +
2615 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
2616 +            {
2617 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
2618 +                {
2619 +                    is_stun = 1;
2620 +                }
2621 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
2622 +                {
2623 +                    diff = nextfieldoff-off;
2624 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
2625 +                                                         off, diff, NULL, 0))
2626 +                    {
2627 +                        /* mangle failed, all we can do is bail */
2628 +                        return 0;
2629 +                    }
2630 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
2631 +                    ptran = ptcp+tranoff;
2632 +                    tranlen -= diff;
2633 +                    nextparamoff -= diff;
2634 +                    nextfieldoff -= diff;
2635 +                }
2636 +            }
2637 +
2638 +            off = nextfieldoff;
2639 +        }
2640 +        if (is_stun)
2641 +        {
2642 +            continue;
2643 +        }
2644 +        off = saveoff;
2645 +        while (off < nextparamoff)
2646 +        {
2647 +            const char* pfieldend;
2648 +            uint        nextfieldoff;
2649 +
2650 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
2651 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
2652 +
2653 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
2654 +            {
2655 +                u_int16_t   port;
2656 +                uint        numlen;
2657 +                uint        origoff;
2658 +                uint        origlen;
2659 +                char*       rbuf    = rbuf1;
2660 +                uint        rbuflen = rbuf1len;
2661 +
2662 +                off += 12;
2663 +                origoff = (ptran-ptcp)+off;
2664 +                origlen = 0;
2665 +                numlen = nf_strtou16(ptran+off, &port);
2666 +                off += numlen;
2667 +                origlen += numlen;
2668 +                if (port != prtspexp->loport)
2669 +                {
2670 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
2671 +                }
2672 +                else
2673 +                {
2674 +                    if (ptran[off] == '-' || ptran[off] == '/')
2675 +                    {
2676 +                        off++;
2677 +                        origlen++;
2678 +                        numlen = nf_strtou16(ptran+off, &port);
2679 +                        off += numlen;
2680 +                        origlen += numlen;
2681 +                        rbuf = rbufa;
2682 +                        rbuflen = rbufalen;
2683 +                    }
2684 +
2685 +                    /*
2686 +                     * note we cannot just memcpy() if the sizes are the same.
2687 +                     * the mangle function does skb resizing, checks for a
2688 +                     * cloned skb, and updates the checksums.
2689 +                     *
2690 +                     * parameter 4 below is offset from start of tcp data.
2691 +                     */
2692 +                    diff = origlen-rbuflen;
2693 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
2694 +                                              origoff, origlen, rbuf, rbuflen))
2695 +                    {
2696 +                        /* mangle failed, all we can do is bail */
2697 +                        return 0;
2698 +                    }
2699 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
2700 +                    ptran = ptcp+tranoff;
2701 +                    tranlen -= diff;
2702 +                    nextparamoff -= diff;
2703 +                    nextfieldoff -= diff;
2704 +                }
2705 +            }
2706 +
2707 +            off = nextfieldoff;
2708 +        }
2709 +
2710 +        off = nextparamoff;
2711 +    }
2712 +
2713 +    return 1;
2714 +}
2715 +
2716 +static unsigned int
2717 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
2718 +{
2719 +    struct ip_nat_multi_range mr;
2720 +    u_int32_t newdstip, newsrcip, newip;
2721 +
2722 +    struct ip_conntrack *master = master_ct(ct);
2723 +
2724 +    IP_NF_ASSERT(info);
2725 +    IP_NF_ASSERT(master);
2726 +
2727 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
2728 +
2729 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
2730 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
2731 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
2732 +
2733 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
2734 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
2735 +
2736 +    mr.rangesize = 1;
2737 +    /* We don't want to manip the per-protocol, just the IPs. */
2738 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
2739 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
2740 +
2741 +    return ip_nat_setup_info(ct, &mr, hooknum);
2742 +}
2743 +
2744 +static uint
2745 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
2746 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
2747 +{
2748 +    char*   ptcp;
2749 +    uint    tcplen;
2750 +    uint    hdrsoff;
2751 +    uint    hdrslen;
2752 +    uint    lineoff;
2753 +    uint    linelen;
2754 +    uint    off;
2755 +
2756 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
2757 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
2758 +
2759 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
2760 +
2761 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
2762 +
2763 +    hdrsoff = exp->seq - ntohl(tcph->seq);
2764 +    hdrslen = prtspexp->len;
2765 +    off = hdrsoff;
2766 +
2767 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
2768 +    {
2769 +        if (linelen == 0)
2770 +        {
2771 +            break;
2772 +        }
2773 +        if (off > hdrsoff+hdrslen)
2774 +        {
2775 +            INFOP("!! overrun !!");
2776 +            break;
2777 +        }
2778 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
2779 +
2780 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
2781 +        {
2782 +            uint oldtcplen = tcplen;
2783 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
2784 +            {
2785 +                break;
2786 +            }
2787 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
2788 +            hdrslen -= (oldtcplen-tcplen);
2789 +            off -= (oldtcplen-tcplen);
2790 +            lineoff -= (oldtcplen-tcplen);
2791 +            linelen -= (oldtcplen-tcplen);
2792 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
2793 +        }
2794 +    }
2795 +
2796 +    return NF_ACCEPT;
2797 +}
2798 +
2799 +static uint
2800 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
2801 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
2802 +{
2803 +    /* XXX: unmangle */
2804 +    return NF_ACCEPT;
2805 +}
2806 +
2807 +static uint
2808 +help(struct ip_conntrack* ct,
2809 +     struct ip_conntrack_expect* exp,
2810 +     struct ip_nat_info* info,
2811 +     enum ip_conntrack_info ctinfo,
2812 +     unsigned int hooknum,
2813 +     struct sk_buff** pskb)
2814 +{
2815 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
2816 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
2817 +    uint datalen;
2818 +    int dir;
2819 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
2820 +    int rc = NF_ACCEPT;
2821 +
2822 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
2823 +    {
2824 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
2825 +        return NF_ACCEPT;
2826 +    }
2827 +
2828 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
2829 +
2830 +    /*
2831 +     * Only mangle things once: original direction in POST_ROUTING
2832 +     * and reply direction on PRE_ROUTING.
2833 +     */
2834 +    dir = CTINFO2DIR(ctinfo);
2835 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
2836 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
2837 +    {
2838 +        DEBUGP("Not touching dir %s at hook %s\n",
2839 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
2840 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
2841 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
2842 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
2843 +        return NF_ACCEPT;
2844 +    }
2845 +    DEBUGP("got beyond not touching\n");
2846 +
2847 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
2848 +
2849 +    LOCK_BH(&ip_rtsp_lock);
2850 +    /* Ensure the packet contains all of the marked data */
2851 +    if (!between(exp->seq + ct_rtsp_info->len,
2852 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
2853 +    {
2854 +        /* Partial retransmission?  Probably a hacker. */
2855 +        if (net_ratelimit())
2856 +        {
2857 +            INFOP("partial packet %u/%u in %u/%u\n",
2858 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
2859 +        }
2860 +        UNLOCK_BH(&ip_rtsp_lock);
2861 +        return NF_DROP;
2862 +    }
2863 +
2864 +    switch (dir)
2865 +    {
2866 +    case IP_CT_DIR_ORIGINAL:
2867 +        rc = help_out(ct, ctinfo, exp, pskb);
2868 +        break;
2869 +    case IP_CT_DIR_REPLY:
2870 +        rc = help_in(ct, ctinfo, exp, pskb);
2871 +        break;
2872 +    default:
2873 +        /* oops */
2874 +    }
2875 +    UNLOCK_BH(&ip_rtsp_lock);
2876 +
2877 +    return rc;
2878 +}
2879 +
2880 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
2881 +static char rtsp_names[MAX_PORTS][10];
2882 +
2883 +/* This function is intentionally _NOT_ defined as  __exit */
2884 +static void
2885 +fini(void)
2886 +{
2887 +    int i;
2888 +
2889 +    for (i = 0; i < num_ports; i++)
2890 +    {
2891 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
2892 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
2893 +    }
2894 +}
2895 +
2896 +static int __init
2897 +init(void)
2898 +{
2899 +    int ret = 0;
2900 +    int i;
2901 +    struct ip_nat_helper* hlpr;
2902 +    char* tmpname;
2903 +
2904 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
2905 +
2906 +    if (ports[0] == 0)
2907 +    {
2908 +        ports[0] = RTSP_PORT;
2909 +    }
2910 +
2911 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
2912 +    {
2913 +        hlpr = &ip_nat_rtsp_helpers[i];
2914 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
2915 +
2916 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
2917 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
2918 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
2919 +        hlpr->mask.dst.protonum = 0xFFFF;
2920 +        hlpr->help = help;
2921 +        hlpr->flags = 0;
2922 +        hlpr->me = THIS_MODULE;
2923 +        hlpr->expect = expected;
2924 +
2925 +        tmpname = &rtsp_names[i][0];
2926 +        if (ports[i] == RTSP_PORT)
2927 +        {
2928 +                sprintf(tmpname, "rtsp");
2929 +        }
2930 +        else
2931 +        {
2932 +                sprintf(tmpname, "rtsp-%d", i);
2933 +        }
2934 +        hlpr->name = tmpname;
2935 +
2936 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
2937 +        ret = ip_nat_helper_register(hlpr);
2938 +
2939 +        if (ret)
2940 +        {
2941 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
2942 +            fini();
2943 +            return 1;
2944 +        }
2945 +        num_ports++;
2946 +    }
2947 +    if (stunaddr != NULL)
2948 +    {
2949 +        extip = in_aton(stunaddr);
2950 +    }
2951 +    if (destaction != NULL)
2952 +    {
2953 +        if (strcmp(destaction, "auto") == 0)
2954 +        {
2955 +            dstact = DSTACT_AUTO;
2956 +        }
2957 +        if (strcmp(destaction, "strip") == 0)
2958 +        {
2959 +            dstact = DSTACT_STRIP;
2960 +        }
2961 +        if (strcmp(destaction, "none") == 0)
2962 +        {
2963 +            dstact = DSTACT_NONE;
2964 +        }
2965 +    }
2966 +    return ret;
2967 +}
2968 +
2969 +module_init(init);
2970 +module_exit(fini);
2971 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_tables.c linux-2.6.5-rc1/net/ipv4/netfilter/ip_tables.c
2972 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ip_tables.c  2004-03-16 05:45:50.000000000 +0000
2973 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ip_tables.c      2004-03-16 12:04:36.000000000 +0000
2974 @@ -8,6 +8,10 @@
2975   * it under the terms of the GNU General Public License version 2 as
2976   * published by the Free Software Foundation.
2977   *
2978 + *  6 Mar 2002 Robert Olsson <robban@robtex.com>
2979 + * 17 Apr 2003 Chris  Wilson <chris@netservers.co.uk>
2980 + *     - mark_source_chains speedup for complex chains
2981 + *
2982   * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
2983   *     - increase module usage count as soon as we have rules inside
2984   *       a table
2985 @@ -498,6 +502,9 @@
2986  {
2987         unsigned int hook;
2988  
2989 +       /* keep track of where we have been: */
2990 +       unsigned char *been = vmalloc(newinfo->size);
2991 +
2992         /* No recursion; use packet counter to save back ptrs (reset
2993            to 0 as we leave), and comefrom to save source hook bitmask */
2994         for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
2995 @@ -510,6 +517,7 @@
2996  
2997                 /* Set initial back pointer. */
2998                 e->counters.pcnt = pos;
2999 +               memset(been, 0, newinfo->size);
3000  
3001                 for (;;) {
3002                         struct ipt_standard_target *t
3003 @@ -518,6 +526,7 @@
3004                         if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
3005                                 printk("iptables: loop hook %u pos %u %08X.\n",
3006                                        hook, pos, e->comefrom);
3007 +                               vfree(been);
3008                                 return 0;
3009                         }
3010                         e->comefrom
3011 @@ -565,10 +574,14 @@
3012                         } else {
3013                                 int newpos = t->verdict;
3014  
3015 -                               if (strcmp(t->target.u.user.name,
3016 +                               if ( (pos < 0 || pos >= newinfo->size
3017 +                                     || !been[pos]) 
3018 +                                   && strcmp(t->target.u.user.name,
3019                                            IPT_STANDARD_TARGET) == 0
3020                                     && newpos >= 0) {
3021                                         /* This a jump; chase it. */
3022 +                                       if (pos >= 0 && pos < newinfo->size)
3023 +                                               been[pos]++;
3024                                         duprintf("Jump rule %u -> %u\n",
3025                                                  pos, newpos);
3026                                 } else {
3027 @@ -584,6 +597,7 @@
3028                 next:
3029                 duprintf("Finished chain %u\n", hook);
3030         }
3031 +       vfree(been);
3032         return 1;
3033  }
3034  
3035 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_CONNMARK.c
3036 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c       1970-01-01 00:00:00.000000000 +0000
3037 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_CONNMARK.c   2004-03-16 12:04:09.000000000 +0000
3038 @@ -0,0 +1,118 @@
3039 +/* This kernel module is used to modify the connection mark values, or
3040 + * to optionally restore the skb nfmark from the connection mark
3041 + *
3042 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
3043 + * by Henrik Nordstrom <hno@marasystems.com>
3044 + *
3045 + * This program is free software; you can redistribute it and/or modify
3046 + * it under the terms of the GNU General Public License as published by
3047 + * the Free Software Foundation; either version 2 of the License, or
3048 + * (at your option) any later version.
3049 + *
3050 + * This program is distributed in the hope that it will be useful,
3051 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3052 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3053 + * GNU General Public License for more details.
3054 + *
3055 + * You should have received a copy of the GNU General Public License
3056 + * along with this program; if not, write to the Free Software
3057 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
3058 + */
3059 +#include <linux/module.h>
3060 +#include <linux/skbuff.h>
3061 +#include <linux/ip.h>
3062 +#include <net/checksum.h>
3063 +
3064 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
3065 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
3066 +MODULE_LICENSE("GPL");
3067 +
3068 +#include <linux/netfilter_ipv4/ip_tables.h>
3069 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
3070 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3071 +
3072 +static unsigned int
3073 +target(struct sk_buff **pskb,
3074 +       const struct net_device *in,
3075 +       const struct net_device *out,
3076 +       unsigned int hooknum,
3077 +       const void *targinfo,
3078 +       void *userinfo)
3079 +{
3080 +       const struct ipt_connmark_target_info *markinfo = targinfo;
3081 +       unsigned long diff;
3082 +       unsigned long nfmark;
3083 +       unsigned long newmark;
3084 +
3085 +       enum ip_conntrack_info ctinfo;
3086 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
3087 +       if (ct) {
3088 +           switch(markinfo->mode) {
3089 +           case IPT_CONNMARK_SET:
3090 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
3091 +               if (newmark != ct->mark)
3092 +                   ct->mark = newmark;
3093 +               break;
3094 +           case IPT_CONNMARK_SAVE:
3095 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
3096 +               if (ct->mark != newmark)
3097 +                   ct->mark = newmark;
3098 +               break;
3099 +           case IPT_CONNMARK_RESTORE:
3100 +               nfmark = (*pskb)->nfmark;
3101 +               diff = (ct->mark ^ nfmark & markinfo->mask);
3102 +               if (diff != 0) {
3103 +                   (*pskb)->nfmark = nfmark ^ diff;
3104 +                   (*pskb)->nfcache |= NFC_ALTERED;
3105 +               }
3106 +               break;
3107 +           }
3108 +       }
3109 +
3110 +       return IPT_CONTINUE;
3111 +}
3112 +
3113 +static int
3114 +checkentry(const char *tablename,
3115 +          const struct ipt_entry *e,
3116 +          void *targinfo,
3117 +          unsigned int targinfosize,
3118 +          unsigned int hook_mask)
3119 +{
3120 +       struct ipt_connmark_target_info *matchinfo = targinfo;
3121 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
3122 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
3123 +                      targinfosize,
3124 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
3125 +               return 0;
3126 +       }
3127 +
3128 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
3129 +           if (strcmp(tablename, "mangle") != 0) {
3130 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
3131 +                   return 0;
3132 +           }
3133 +       }
3134 +
3135 +       return 1;
3136 +}
3137 +
3138 +static struct ipt_target ipt_connmark_reg = {
3139 +       .name = "CONNMARK",
3140 +       .target = &target,
3141 +       .checkentry = &checkentry,
3142 +       .me = THIS_MODULE
3143 +};
3144 +
3145 +static int __init init(void)
3146 +{
3147 +       return ipt_register_target(&ipt_connmark_reg);
3148 +}
3149 +
3150 +static void __exit fini(void)
3151 +{
3152 +       ipt_unregister_target(&ipt_connmark_reg);
3153 +}
3154 +
3155 +module_init(init);
3156 +module_exit(fini);
3157 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_IPMARK.c
3158 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 00:00:00.000000000 +0000
3159 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_IPMARK.c     2004-03-16 12:04:10.000000000 +0000
3160 @@ -0,0 +1,81 @@
3161 +/* This is a module which is used for setting the NFMARK field of an skb. */
3162 +#include <linux/module.h>
3163 +#include <linux/skbuff.h>
3164 +#include <linux/ip.h>
3165 +#include <net/checksum.h>
3166 +
3167 +#include <linux/netfilter_ipv4/ip_tables.h>
3168 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
3169 +
3170 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
3171 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
3172 +MODULE_LICENSE("GPL");
3173 +
3174 +static unsigned int
3175 +target(struct sk_buff **pskb,
3176 +       const struct net_device *in,
3177 +       const struct net_device *out,
3178 +       unsigned int hooknum,
3179 +       const void *targinfo,
3180 +       void *userinfo)
3181 +{
3182 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
3183 +       struct iphdr *iph = (*pskb)->nh.iph;
3184 +       unsigned long mark;
3185 +
3186 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
3187 +               mark = (unsigned long) ntohl(iph->saddr);
3188 +       else
3189 +               mark = (unsigned long) ntohl(iph->daddr);
3190 +
3191 +       mark &= ipmarkinfo->andmask;
3192 +       mark |= ipmarkinfo->ormask;
3193 +       
3194 +       if ((*pskb)->nfmark != mark) {
3195 +               (*pskb)->nfmark = mark;
3196 +               (*pskb)->nfcache |= NFC_ALTERED;
3197 +       }
3198 +       return IPT_CONTINUE;
3199 +}
3200 +
3201 +static int
3202 +checkentry(const char *tablename,
3203 +          const struct ipt_entry *e,
3204 +           void *targinfo,
3205 +           unsigned int targinfosize,
3206 +           unsigned int hook_mask)
3207 +{
3208 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
3209 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
3210 +                      targinfosize,
3211 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
3212 +               return 0;
3213 +       }
3214 +
3215 +       if (strcmp(tablename, "mangle") != 0) {
3216 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
3217 +               return 0;
3218 +       }
3219 +
3220 +       return 1;
3221 +}
3222 +
3223 +static struct ipt_target ipt_ipmark_reg = { 
3224 +       .name = "IPMARK",
3225 +       .target = target,
3226 +       .checkentry = checkentry,
3227 +       .me = THIS_MODULE
3228 +};
3229 +
3230 +static int __init init(void)
3231 +{
3232 +       return ipt_register_target(&ipt_ipmark_reg);
3233 +}
3234 +
3235 +static void __exit fini(void)
3236 +{
3237 +       ipt_unregister_target(&ipt_ipmark_reg);
3238 +}
3239 +
3240 +module_init(init);
3241 +module_exit(fini);
3242 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_XOR.c
3243 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_XOR.c    1970-01-01 00:00:00.000000000 +0000
3244 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_XOR.c        2004-03-16 12:04:18.000000000 +0000
3245 @@ -0,0 +1,117 @@
3246 +/* XOR target for IP tables
3247 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
3248 + * Based on ipt_TTL.c
3249 + *
3250 + * Version 1.0
3251 + *
3252 + * This software is distributed under the terms of GNU GPL
3253 + */
3254 +
3255 +#include <linux/module.h>
3256 +#include <linux/skbuff.h>
3257 +#include <linux/ip.h>
3258 +#include <linux/tcp.h>
3259 +#include <linux/udp.h>
3260 +
3261 +#include <linux/netfilter_ipv4/ip_tables.h>
3262 +#include <linux/netfilter_ipv4/ipt_XOR.h>
3263 +
3264 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
3265 +MODULE_DESCRIPTION("IP tables XOR module");
3266 +MODULE_LICENSE("GPL");
3267 +
3268 +static unsigned int 
3269 +ipt_xor_target(struct sk_buff **pskb, 
3270 +               const struct net_device *in, const struct net_device *out, 
3271 +               unsigned int hooknum, const void *targinfo, void *userinfo)
3272 +{
3273 +       struct ipt_XOR_info *info = (void *) targinfo;
3274 +       struct iphdr *iph;
3275 +       struct tcphdr *tcph;
3276 +       struct udphdr *udph;
3277 +       int i, j, k;
3278 +
3279 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
3280 +               return NF_DROP;
3281 +
3282 +       iph = (*pskb)->nh.iph;
3283 +  
3284 +       if (iph->protocol == IPPROTO_TCP) {
3285 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
3286 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
3287 +                       for (k=0; k<=info->block_size; k++) {
3288 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
3289 +                                               info->key[j];
3290 +                               i++;
3291 +                       }
3292 +                       j++;
3293 +                       if (info->key[j] == 0x00)
3294 +                               j = 0;
3295 +               }
3296 +       } else if (iph->protocol == IPPROTO_UDP) {
3297 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
3298 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
3299 +                       for (k=0; k<=info->block_size; k++) {
3300 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
3301 +                                               info->key[j];
3302 +                               i++;
3303 +                       }
3304 +                       j++;
3305 +                       if (info->key[j] == 0x00)
3306 +                               j = 0;
3307 +               }
3308 +       }
3309 +  
3310 +       return IPT_CONTINUE;
3311 +}
3312 +
3313 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
3314 +               void *targinfo, unsigned int targinfosize, 
3315 +               unsigned int hook_mask)
3316 +{
3317 +       struct ipt_XOR_info *info = targinfo;
3318 +
3319 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
3320 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
3321 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
3322 +               return 0;
3323 +       }       
3324 +
3325 +       if (strcmp(tablename, "mangle")) {
3326 +               printk(KERN_WARNING "XOR: can only be called from"
3327 +                               "\"mangle\" table, not \"%s\"\n", tablename);
3328 +               return 0; 
3329 +       }
3330 +
3331 +       if (!strcmp(info->key, "")) {
3332 +               printk(KERN_WARNING "XOR: You must specify a key");
3333 +               return 0;
3334 +       }
3335 +
3336 +       if (info->block_size == 0) {
3337 +               printk(KERN_WARNING "XOR: You must specify a block-size");
3338 +               return 0;
3339 +       }
3340 +
3341 +       return 1;
3342 +}
3343 +
3344 +static struct ipt_target ipt_XOR = { 
3345 +       .name = "XOR",
3346 +       .target = ipt_xor_target, 
3347 +       .checkentry = ipt_xor_checkentry,
3348 +       .me = THIS_MODULE,
3349 +};
3350 +
3351 +static int __init init(void)
3352 +{
3353 +       return ipt_register_target(&ipt_XOR);
3354 +}
3355 +
3356 +static void __exit fini(void)
3357 +{
3358 +       ipt_unregister_target(&ipt_XOR);
3359 +}
3360 +
3361 +module_init(init);
3362 +module_exit(fini);
3363 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_addrtype.c
3364 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_addrtype.c       1970-01-01 00:00:00.000000000 +0000
3365 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_addrtype.c   2004-03-16 12:04:20.000000000 +0000
3366 @@ -0,0 +1,68 @@
3367 +/*
3368 + *  iptables module to match inet_addr_type() of an ip.
3369 + */
3370 +
3371 +#include <linux/module.h>
3372 +#include <linux/skbuff.h>
3373 +#include <linux/netdevice.h>
3374 +#include <net/route.h>
3375 +
3376 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
3377 +#include <linux/netfilter_ipv4/ip_tables.h>
3378 +
3379 +MODULE_LICENSE("GPL");
3380 +
3381 +static inline int match_type(u_int32_t addr, u_int16_t mask)
3382 +{
3383 +       return !!(mask & (1 << inet_addr_type(addr)));
3384 +}
3385 +
3386 +static int match(const struct sk_buff *skb, const struct net_device *in,
3387 +                const struct net_device *out, const void *matchinfo,
3388 +                int offset, int *hotdrop)
3389 +{
3390 +       const struct ipt_addrtype_info *info = matchinfo;
3391 +       const struct iphdr *iph = skb->nh.iph;
3392 +       int ret = 1;
3393 +
3394 +       if (info->source)
3395 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
3396 +       if (info->dest)
3397 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
3398 +       
3399 +       return ret;
3400 +}
3401 +
3402 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
3403 +                     void *matchinfo, unsigned int matchsize,
3404 +                     unsigned int hook_mask)
3405 +{
3406 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
3407 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
3408 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
3409 +               return 0;
3410 +       }
3411 +
3412 +       return 1;
3413 +}
3414 +
3415 +static struct ipt_match addrtype_match = { 
3416 +       .name = "addrtype",
3417 +       .match = match,
3418 +       .checkentry = checkentry,
3419 +       .me = THIS_MODULE
3420 +};
3421 +
3422 +static int __init init(void)
3423 +{
3424 +       return ipt_register_match(&addrtype_match);
3425 +}
3426 +
3427 +static void __exit fini(void)
3428 +{
3429 +       ipt_unregister_match(&addrtype_match);
3430 +
3431 +}
3432 +
3433 +module_init(init);
3434 +module_exit(fini);
3435 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_connmark.c
3436 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_connmark.c       1970-01-01 00:00:00.000000000 +0000
3437 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_connmark.c   2004-03-16 12:04:09.000000000 +0000
3438 @@ -0,0 +1,81 @@
3439 +/* This kernel module matches connection mark values set by the
3440 + * CONNMARK target
3441 + *
3442 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
3443 + * by Henrik Nordstrom <hno@marasystems.com>
3444 + *
3445 + * This program is free software; you can redistribute it and/or modify
3446 + * it under the terms of the GNU General Public License as published by
3447 + * the Free Software Foundation; either version 2 of the License, or
3448 + * (at your option) any later version.
3449 + *
3450 + * This program is distributed in the hope that it will be useful,
3451 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3452 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3453 + * GNU General Public License for more details.
3454 + *
3455 + * You should have received a copy of the GNU General Public License
3456 + * along with this program; if not, write to the Free Software
3457 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
3458 + */
3459 +
3460 +#include <linux/module.h>
3461 +#include <linux/skbuff.h>
3462 +
3463 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
3464 +MODULE_DESCRIPTION("IP tables connmark match module");
3465 +MODULE_LICENSE("GPL");
3466 +
3467 +#include <linux/netfilter_ipv4/ip_tables.h>
3468 +#include <linux/netfilter_ipv4/ipt_connmark.h>
3469 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3470 +
3471 +static int
3472 +match(const struct sk_buff *skb,
3473 +      const struct net_device *in,
3474 +      const struct net_device *out,
3475 +      const void *matchinfo,
3476 +      int offset,
3477 +      int *hotdrop)
3478 +{
3479 +       const struct ipt_connmark_info *info = matchinfo;
3480 +       enum ip_conntrack_info ctinfo;
3481 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
3482 +       if (!ct)
3483 +               return 0;
3484 +
3485 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
3486 +}
3487 +
3488 +static int
3489 +checkentry(const char *tablename,
3490 +          const struct ipt_ip *ip,
3491 +          void *matchinfo,
3492 +          unsigned int matchsize,
3493 +          unsigned int hook_mask)
3494 +{
3495 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
3496 +               return 0;
3497 +
3498 +       return 1;
3499 +}
3500 +
3501 +static struct ipt_match connmark_match = {
3502 +       .name = "connmark",
3503 +       .match = &match,
3504 +       .checkentry = &checkentry,
3505 +       .me = THIS_MODULE
3506 +};
3507 +
3508 +static int __init init(void)
3509 +{
3510 +       return ipt_register_match(&connmark_match);
3511 +}
3512 +
3513 +static void __exit fini(void)
3514 +{
3515 +       ipt_unregister_match(&connmark_match);
3516 +}
3517 +
3518 +module_init(init);
3519 +module_exit(fini);
3520 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_owner.c
3521 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_owner.c  2004-03-16 05:47:19.000000000 +0000
3522 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_owner.c      2004-03-16 12:04:38.000000000 +0000
3523 @@ -6,12 +6,19 @@
3524   * This program is free software; you can redistribute it and/or modify
3525   * it under the terms of the GNU General Public License version 2 as
3526   * published by the Free Software Foundation.
3527 + *
3528 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
3529   */
3530  
3531  #include <linux/module.h>
3532  #include <linux/skbuff.h>
3533  #include <linux/file.h>
3534 +#include <linux/ip.h>
3535 +#include <linux/tcp.h>
3536 +#include <linux/udp.h>
3537  #include <net/sock.h>
3538 +#include <net/tcp.h>
3539 +#include <net/udp.h>
3540  
3541  #include <linux/netfilter_ipv4/ipt_owner.h>
3542  #include <linux/netfilter_ipv4/ip_tables.h>
3543 @@ -21,7 +28,7 @@
3544  MODULE_DESCRIPTION("iptables owner match");
3545  
3546  static int
3547 -match_comm(const struct sk_buff *skb, const char *comm)
3548 +match_comm(const struct sock *sk, const char *comm)
3549  {
3550         struct task_struct *g, *p;
3551         struct files_struct *files;
3552 @@ -38,7 +45,7 @@
3553                         spin_lock(&files->file_lock);
3554                         for (i=0; i < files->max_fds; i++) {
3555                                 if (fcheck_files(files, i) ==
3556 -                                   skb->sk->sk_socket->file) {
3557 +                                   sk->sk_socket->file) {
3558                                         spin_unlock(&files->file_lock);
3559                                         task_unlock(p);
3560                                         read_unlock(&tasklist_lock);
3561 @@ -54,7 +61,7 @@
3562  }
3563  
3564  static int
3565 -match_pid(const struct sk_buff *skb, pid_t pid)
3566 +match_pid(const struct sock *sk, pid_t pid)
3567  {
3568         struct task_struct *p;
3569         struct files_struct *files;
3570 @@ -70,7 +77,7 @@
3571                 spin_lock(&files->file_lock);
3572                 for (i=0; i < files->max_fds; i++) {
3573                         if (fcheck_files(files, i) ==
3574 -                           skb->sk->sk_socket->file) {
3575 +                           sk->sk_socket->file) {
3576                                 spin_unlock(&files->file_lock);
3577                                 task_unlock(p);
3578                                 read_unlock(&tasklist_lock);
3579 @@ -86,10 +93,10 @@
3580  }
3581  
3582  static int
3583 -match_sid(const struct sk_buff *skb, pid_t sid)
3584 +match_sid(const struct sock *sk, pid_t sid)
3585  {
3586         struct task_struct *g, *p;
3587 -       struct file *file = skb->sk->sk_socket->file;
3588 +       struct file *file = sk->sk_socket->file;
3589         int i, found=0;
3590  
3591         read_lock(&tasklist_lock);
3592 @@ -129,41 +136,71 @@
3593        int *hotdrop)
3594  {
3595         const struct ipt_owner_info *info = matchinfo;
3596 +       struct iphdr *iph = skb->nh.iph;
3597 +       struct sock *sk = NULL;
3598 +       int ret = 0;
3599 +
3600 +       if (out) {
3601 +               sk = skb->sk;
3602 +       } else {
3603 +               if (iph->protocol == IPPROTO_TCP) {
3604 +                       struct tcphdr *tcph =
3605 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
3606 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
3607 +                                          iph->daddr, tcph->dest,
3608 +                                          skb->dev->ifindex);
3609 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
3610 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
3611 +                               return ret;
3612 +                       }
3613 +               } else if (iph->protocol == IPPROTO_UDP) {
3614 +                       struct udphdr *udph =
3615 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
3616 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
3617 +                                          udph->dest, skb->dev->ifindex);
3618 +               }
3619 +       }
3620  
3621 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
3622 -               return 0;
3623 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
3624 +               goto out;
3625  
3626         if(info->match & IPT_OWNER_UID) {
3627 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
3628 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
3629                     !!(info->invert & IPT_OWNER_UID))
3630 -                       return 0;
3631 +                       goto out;
3632         }
3633  
3634         if(info->match & IPT_OWNER_GID) {
3635 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
3636 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
3637                     !!(info->invert & IPT_OWNER_GID))
3638 -                       return 0;
3639 +                       goto out;
3640         }
3641  
3642         if(info->match & IPT_OWNER_PID) {
3643 -               if (!match_pid(skb, info->pid) ^
3644 +               if (!match_pid(sk, info->pid) ^
3645                     !!(info->invert & IPT_OWNER_PID))
3646 -                       return 0;
3647 +                       goto out;
3648         }
3649  
3650         if(info->match & IPT_OWNER_SID) {
3651 -               if (!match_sid(skb, info->sid) ^
3652 +               if (!match_sid(sk, info->sid) ^
3653                     !!(info->invert & IPT_OWNER_SID))
3654 -                       return 0;
3655 +                       goto out;
3656         }
3657  
3658         if(info->match & IPT_OWNER_COMM) {
3659 -               if (!match_comm(skb, info->comm) ^
3660 +               if (!match_comm(sk, info->comm) ^
3661                     !!(info->invert & IPT_OWNER_COMM))
3662 -                       return 0;
3663 +                       goto out;
3664         }
3665  
3666 -       return 1;
3667 +       ret = 1;
3668 +
3669 +out:
3670 +       if (in && sk)
3671 +               sock_put(sk);
3672 +
3673 +       return ret;
3674  }
3675  
3676  static int
3677 @@ -173,11 +210,19 @@
3678             unsigned int matchsize,
3679             unsigned int hook_mask)
3680  {
3681 -        if (hook_mask
3682 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
3683 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
3684 -                return 0;
3685 -        }
3686 +       if (hook_mask
3687 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
3688 +           (1 << NF_IP_LOCAL_IN))) {
3689 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
3690 +                      "or POST_ROUTING.\n");
3691 +               return 0;
3692 +       }
3693 +
3694 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
3695 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
3696 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
3697 +               return 0;
3698 +       }
3699  
3700         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
3701                 printk("Matchsize %u != %Zu\n", matchsize,
3702 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_policy.c
3703 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 00:00:00.000000000 +0000
3704 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_policy.c     2004-03-16 12:04:45.000000000 +0000
3705 @@ -0,0 +1,176 @@
3706 +/* IP tables module for matching IPsec policy
3707 + *
3708 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
3709 + *
3710 + * This program is free software; you can redistribute it and/or modify
3711 + * it under the terms of the GNU General Public License version 2 as
3712 + * published by the Free Software Foundation.
3713 + */
3714 +
3715 +#include <linux/kernel.h>
3716 +#include <linux/config.h>
3717 +#include <linux/module.h>
3718 +#include <linux/skbuff.h>
3719 +#include <linux/init.h>
3720 +#include <net/xfrm.h>
3721 +
3722 +#include <linux/netfilter_ipv4.h>
3723 +#include <linux/netfilter_ipv4/ipt_policy.h>
3724 +#include <linux/netfilter_ipv4/ip_tables.h>
3725 +
3726 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
3727 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
3728 +MODULE_LICENSE("GPL");
3729 +
3730 +
3731 +static inline int
3732 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
3733 +{
3734 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
3735 +
3736 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
3737 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
3738 +           MISMATCH(proto, x->id.proto) ||
3739 +           MISMATCH(mode, x->props.mode) ||
3740 +           MISMATCH(spi, x->id.spi) ||
3741 +           MISMATCH(reqid, x->props.reqid))
3742 +               return 0;
3743 +       return 1;
3744 +}
3745 +
3746 +static int
3747 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
3748 +{
3749 +       const struct ipt_policy_elem *e;
3750 +       struct sec_path *sp = skb->sp;
3751 +       int strict = info->flags & POLICY_MATCH_STRICT;
3752 +       int i, pos;
3753 +
3754 +       if (sp == NULL)
3755 +               return -1;
3756 +       if (strict && info->len != sp->len)
3757 +               return 0;
3758 +
3759 +       for (i = sp->len - 1; i >= 0; i--) {
3760 +               pos = strict ? i - sp->len + 1 : 0;
3761 +               if (pos >= info->len)
3762 +                       return 0;
3763 +               e = &info->pol[pos];
3764 +
3765 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
3766 +                       if (!strict)
3767 +                               return 1;
3768 +               } else if (strict)
3769 +                       return 0;
3770 +       }
3771 +
3772 +       return strict ? 1 : 0;
3773 +}
3774 +
3775 +static int
3776 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
3777 +{
3778 +       const struct ipt_policy_elem *e;
3779 +       struct dst_entry *dst = skb->dst;
3780 +       int strict = info->flags & POLICY_MATCH_STRICT;
3781 +       int i, pos;
3782 +
3783 +       if (dst->xfrm == NULL)
3784 +               return -1;
3785 +
3786 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
3787 +               pos = strict ? i : 0;
3788 +               if (pos >= info->len)
3789 +                       return 0;
3790 +               e = &info->pol[pos];
3791 +
3792 +               if (match_xfrm_state(dst->xfrm, e)) {
3793 +                       if (!strict)
3794 +                               return 1;
3795 +               } else if (strict)
3796 +                       return 0;
3797 +       }
3798 +
3799 +       return strict ? 1 : 0;
3800 +}
3801 +
3802 +static int match(const struct sk_buff *skb,
3803 +                 const struct net_device *in,
3804 +                 const struct net_device *out,
3805 +                 const void *matchinfo, int offset, int *hotdrop)
3806 +{
3807 +       const struct ipt_policy_info *info = matchinfo;
3808 +       int ret;
3809 +
3810 +       if (info->flags & POLICY_MATCH_IN)
3811 +               ret = match_policy_in(skb, info);
3812 +       else
3813 +               ret = match_policy_out(skb, info);
3814 +
3815 +       if (ret < 0) {
3816 +               if (info->flags & POLICY_MATCH_NONE)
3817 +                       ret = 1;
3818 +               else
3819 +                       ret = 0;
3820 +       } else if (info->flags & POLICY_MATCH_NONE)
3821 +               ret = 0;
3822 +
3823 +       return ret;
3824 +}
3825 +
3826 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
3827 +                      void *matchinfo, unsigned int matchsize,
3828 +                      unsigned int hook_mask)
3829 +{
3830 +       struct ipt_policy_info *info = matchinfo;
3831 +
3832 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
3833 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
3834 +                      matchsize, IPT_ALIGN(sizeof(*info)));
3835 +               return 0;
3836 +       }
3837 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
3838 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
3839 +                               "outgoing policy selected\n");
3840 +               return 0;
3841 +       }
3842 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
3843 +           && info->flags & POLICY_MATCH_OUT) {
3844 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
3845 +                               "PRE_ROUTING and INPUT\n");
3846 +               return 0;
3847 +       }
3848 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
3849 +           && info->flags & POLICY_MATCH_IN) {
3850 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
3851 +                               "POST_ROUTING and OUTPUT\n");
3852 +               return 0;
3853 +       }
3854 +       if (info->len > POLICY_MAX_ELEM) {
3855 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
3856 +               return 0;
3857 +       }
3858 +
3859 +       return 1;
3860 +}
3861 +
3862 +static struct ipt_match policy_match =
3863 +{
3864 +       .name           = "policy",
3865 +       .match          = match,
3866 +       .checkentry     = checkentry,
3867 +       .me             = THIS_MODULE,
3868 +};
3869 +
3870 +static int __init init(void)
3871 +{
3872 +       return ipt_register_match(&policy_match);
3873 +}
3874 +
3875 +static void __exit fini(void)
3876 +{
3877 +       ipt_unregister_match(&policy_match);
3878 +}
3879 +
3880 +module_init(init);
3881 +module_exit(fini);
3882 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_rpc.c
3883 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_rpc.c    1970-01-01 00:00:00.000000000 +0000
3884 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_rpc.c        2004-03-16 12:04:46.000000000 +0000
3885 @@ -0,0 +1,428 @@
3886 +/* RPC extension for IP connection matching, Version 2.2
3887 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3888 + *     - original rpc tracking module
3889 + *     - "recent" connection handling for kernel 2.3+ netfilter
3890 + *
3891 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3892 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3893 + *
3894 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3895 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
3896 + *     - extended matching to support filtering on procedures
3897 + *
3898 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
3899 + *
3900 + *     This program is free software; you can redistribute it and/or
3901 + *     modify it under the terms of the GNU General Public License
3902 + *     as published by the Free Software Foundation; either version
3903 + *     2 of the License, or (at your option) any later version.
3904 + **
3905 + *     Module load syntax:
3906 + *     insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
3907 + *
3908 + *     Please give the ports of all RPC servers you wish to connect to.
3909 + *     If you don't specify ports, the default will be port 111.
3910 + **
3911 + *     Note to all:
3912 + *
3913 + *     RPCs should not be exposed to the internet - ask the Pentagon;
3914 + *
3915 + *       "The unidentified crackers pleaded guilty in July to charges
3916 + *        of juvenile delinquency stemming from a string of Pentagon
3917 + *        network intrusions in February.
3918 + *
3919 + *        The youths, going by the names TooShort and Makaveli, used
3920 + *        a common server security hole to break in, according to
3921 + *        Dane Jasper, owner of the California Internet service
3922 + *        provider, Sonic. They used the hole, known as the 'statd'
3923 + *        exploit, to attempt more than 800 break-ins, Jasper said."
3924 + *
3925 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3926 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
3927 + **
3928 + */
3929 +
3930 +#include <linux/module.h>
3931 +#include <linux/skbuff.h>
3932 +#include <linux/list.h>
3933 +#include <linux/udp.h>
3934 +#include <linux/tcp.h>
3935 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3936 +#include <linux/netfilter_ipv4/ip_tables.h>
3937 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3938 +#include <linux/netfilter_ipv4/lockhelp.h>
3939 +#include <linux/netfilter_ipv4/ipt_rpc.h>
3940 +
3941 +#define MAX_PORTS 8
3942 +static int ports[MAX_PORTS];
3943 +static int ports_n_c = 0;
3944 +
3945 +#ifdef MODULE_PARM
3946 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3947 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3948 +#endif
3949 +
3950 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3951 +MODULE_DESCRIPTION("RPC connection matching module");
3952 +MODULE_LICENSE("GPL");
3953 +
3954 +#if 0
3955 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
3956 +                                       format, ## args)
3957 +#else
3958 +#define DEBUGP(format, args...)
3959 +#endif
3960 +
3961 +EXPORT_NO_SYMBOLS;
3962 +
3963 +/* vars from ip_conntrack_rpc_tcp */
3964 +extern struct list_head request_p_list_tcp;
3965 +extern struct module *ip_conntrack_rpc_tcp;
3966 +
3967 +/* vars from ip_conntrack_rpc_udp */
3968 +extern struct list_head request_p_list_udp;
3969 +extern struct module *ip_conntrack_rpc_udp;
3970 +
3971 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
3972 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
3973 +
3974 +#define ASSERT_READ_LOCK(x)                                    \
3975 +do {                                                           \
3976 +       if (x == &request_p_list_udp)                           \
3977 +               MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);        \
3978 +       else if (x == &request_p_list_tcp)                      \
3979 +               MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);        \
3980 +} while (0)
3981 +
3982 +#define ASSERT_WRITE_LOCK(x)                                   \
3983 +do {                                                           \
3984 +       if (x == &request_p_list_udp)                           \
3985 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);       \
3986 +       else if (x == &request_p_list_tcp)                      \
3987 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);       \
3988 +} while (0)
3989 +
3990 +#include <linux/netfilter_ipv4/listhelp.h>
3991 +
3992 +const int IPT_RPC_CHAR_LEN = 11;
3993 +
3994 +
3995 +static int k_atoi(char *string)
3996 +{
3997 +       unsigned int result = 0;
3998 +       int maxoctet = IPT_RPC_CHAR_LEN;
3999 +
4000 +       for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
4001 +               if (*string < 0)
4002 +                       return(0);
4003 +               if (*string == 0)
4004 +                       break;
4005 +               if (*string < 48 || *string > 57) {
4006 +                       return(0);
4007 +               }
4008 +               result = result * 10 + ( *string - 48 );
4009 +       }
4010 +       return(result);
4011 +}
4012 +
4013 +
4014 +static int match_rpcs(char *c_procs, int i_procs, int proc)
4015 +{
4016 +       int   proc_ctr;
4017 +       char *proc_ptr;
4018 +       unsigned int proc_num;
4019 +
4020 +       DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
4021 +
4022 +       if (i_procs == -1)
4023 +               return 1;
4024 +
4025 +       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
4026 +
4027 +               proc_ptr = c_procs;
4028 +               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
4029 +               proc_num = k_atoi(proc_ptr);
4030 +
4031 +               if (proc_num == proc)
4032 +                       return 1;
4033 +       }
4034 +
4035 +       return 0;
4036 +}
4037 +
4038 +
4039 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
4040 +                       int *hotdrop, int dir, struct ip_conntrack *ct,
4041 +                       int offset, struct list_head request_p_list)
4042 +{
4043 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
4044 +       struct request_p *req_p;
4045 +       u_int32_t xid;
4046 +
4047 +
4048 +       /* Get XID */
4049 +       xid = *data;
4050 +
4051 +       /* This does sanity checking on RPC payloads,
4052 +        * and permits only the RPC "get port" (3)
4053 +        * in authorised procedures in client
4054 +        * communications with the portmapper.
4055 +        */
4056 +
4057 +       data += 5;
4058 +
4059 +       /* Get RPC requestor */
4060 +       if (IXDR_GET_INT32(data) != 3) {
4061 +               DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
4062 +               if(rpcinfo->strict == 1)
4063 +                       *hotdrop = 1;
4064 +               return 0;
4065 +       }
4066 +       DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
4067 +
4068 +       data++;
4069 +
4070 +       /* Jump Credentials and Verfifier */
4071 +       data = data + IXDR_GET_INT32(data) + 2;
4072 +       data = data + IXDR_GET_INT32(data) + 2;
4073 +
4074 +       /* Get RPC procedure */
4075 +       if (match_rpcs((char *)&rpcinfo->c_procs,
4076 +           rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
4077 +               DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
4078 +                       (unsigned int)IXDR_GET_INT32(data));
4079 +
4080 +               /* If the RPC conntrack half entry already exists .. */
4081 +
4082 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
4083 +                       case IPPROTO_UDP:
4084 +                               WRITE_LOCK(&ipct_rpc_udp_lock);
4085 +                       case IPPROTO_TCP:
4086 +                               WRITE_LOCK(&ipct_rpc_tcp_lock);
4087 +               }
4088 +               req_p = LIST_FIND(&request_p_list, request_p_cmp,
4089 +                                 struct request_p *, xid,
4090 +                                 ct->tuplehash[dir].tuple.src.ip,
4091 +                                 ct->tuplehash[dir].tuple.src.u.all);
4092 +
4093 +               if (req_p) {
4094 +                       DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
4095 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
4096 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
4097 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
4098 +
4099 +                       /* .. remove it */
4100 +                       if (del_timer(&req_p->timeout))
4101 +                               req_p->timeout.expires = 0;
4102 +
4103 +                               LIST_DELETE(&request_p_list, req_p);
4104 +                       DEBUGP("RPC req_p removed. [done]\n");
4105 +
4106 +               } else {
4107 +                       DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
4108 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
4109 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
4110 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
4111 +
4112 +               }
4113 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
4114 +                       case IPPROTO_UDP:
4115 +                               WRITE_UNLOCK(&ipct_rpc_udp_lock);
4116 +                       case IPPROTO_TCP:
4117 +                               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
4118 +               }
4119 +
4120 +               if(rpcinfo->strict == 1)
4121 +                       *hotdrop = 1;
4122 +               return 0;
4123 +       }
4124 +
4125 +       DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
4126 +               (unsigned int)IXDR_GET_INT32(data));
4127 +       return (1 && (!offset));
4128 +}
4129 +
4130 +
4131 +static int match(const struct sk_buff *skb, const struct net_device *in,
4132 +                const struct net_device *out, const void *matchinfo,
4133 +                int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
4134 +{
4135 +       struct ip_conntrack *ct;
4136 +       enum ip_conntrack_info ctinfo;
4137 +       const u_int32_t *data;
4138 +       enum ip_conntrack_dir dir;
4139 +       const struct tcphdr *tcp;
4140 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
4141 +       int port, portsok;
4142 +       int tval;
4143 +
4144 +
4145 +       DEBUGP("new packet to evaluate ..\n");
4146 +
4147 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
4148 +       if (!ct) {
4149 +               DEBUGP("no ct available [skip]\n");
4150 +               return 0;
4151 +       }
4152 +
4153 +       DEBUGP("ct detected. [cont]\n");
4154 +       dir = CTINFO2DIR(ctinfo);
4155 +
4156 +       /* we only want the client to server packets for matching */
4157 +       if (dir != IP_CT_DIR_ORIGINAL)
4158 +               return 0;
4159 +
4160 +       /* This does sanity checking on UDP or TCP packets,
4161 +        * like their respective modules.
4162 +        */
4163 +
4164 +       switch (ct->tuplehash[0].tuple.dst.protonum) {
4165 +
4166 +               case IPPROTO_UDP:
4167 +                       DEBUGP("PROTO_UDP [cont]\n");
4168 +                       if (offset == 0 && datalen < sizeof(struct udphdr)) {
4169 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
4170 +                               return 0;
4171 +                       }
4172 +
4173 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
4174 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
4175 +                                       portsok++;
4176 +                                       break;
4177 +                               }
4178 +                       }
4179 +                       if (portsok == 0) {
4180 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
4181 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
4182 +                               return 0;
4183 +                       }
4184 +
4185 +                       if ((datalen - sizeof(struct udphdr)) != 56) {
4186 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
4187 +                               if (rpcinfo->strict == 1)
4188 +                                       *hotdrop = 1;
4189 +                               return 0;
4190 +                       }
4191 +                       DEBUGP("packet length is correct. [cont]\n");
4192 +
4193 +                       /* Get to the data */
4194 +                       data = (const u_int32_t *)hdr + 2;
4195 +
4196 +                       /* Check the RPC data */
4197 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
4198 +                                               dir, ct, offset,
4199 +                                               request_p_list_udp);
4200 +
4201 +                       return tval;
4202 +                       
4203 +               
4204 +               case IPPROTO_TCP:
4205 +                       DEBUGP("PROTO_TCP [cont]\n");
4206 +                       if (offset == 0 && datalen < sizeof(struct tcphdr)) {
4207 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
4208 +                               return 0;
4209 +                       }
4210 +       
4211 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
4212 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
4213 +                                       portsok++;
4214 +                                       break;
4215 +                               }
4216 +                       }
4217 +                       if (portsok == 0) {
4218 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
4219 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
4220 +                               return 0;
4221 +                       }
4222 +
4223 +                       tcp = hdr;
4224 +                       if (datalen == (tcp->doff * 4)) {
4225 +                               DEBUGP("packet does not contain any data. [match]\n");
4226 +                               return (1 && (!offset));
4227 +                       }
4228 +
4229 +                       /* Tests if packet len is ok */
4230 +                       if ((datalen - (tcp->doff * 4)) != 60) {
4231 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
4232 +                               if(rpcinfo->strict == 1)
4233 +                                       *hotdrop = 1;
4234 +                               return 0;
4235 +                       }
4236 +                       DEBUGP("packet length is correct. [cont]\n");
4237 +
4238 +                       /* Get to the data */
4239 +                       data = (const u_int32_t *)tcp + tcp->doff + 1;  
4240 +
4241 +                       /* Check the RPC data */
4242 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
4243 +                                               dir, ct, offset,
4244 +                                               request_p_list_tcp);
4245 +
4246 +                       return tval;
4247 +
4248 +       }
4249 +
4250 +       DEBUGP("transport protocol=%u, is not supported [skip]\n",
4251 +               ct->tuplehash[0].tuple.dst.protonum);
4252 +       return 0;
4253 +}
4254 +
4255 +
4256 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
4257 +                  unsigned int matchsize, unsigned int hook_mask)
4258 +{
4259 +       if (hook_mask
4260 +           & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
4261 +               | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
4262 +               printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
4263 +               return 0;
4264 +       }
4265 +
4266 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
4267 +               return 0;
4268 +
4269 +       return 1;
4270 +}
4271 +
4272 +
4273 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
4274 +                                       &match, &checkentry, NULL,
4275 +                                       THIS_MODULE };
4276 +
4277 +
4278 +static int __init init(void)
4279 +{
4280 +       int port;
4281 +
4282 +       DEBUGP("incrementing usage counts\n");
4283 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
4284 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
4285 +
4286 +       /* If no port given, default to standard RPC port */
4287 +       if (ports[0] == 0)
4288 +               ports[0] = RPC_PORT;
4289 +
4290 +       DEBUGP("registering match [%s] for;\n", rpc_match.name);
4291 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4292 +               DEBUGP("  port %i (UDP|TCP);\n", ports[port]);
4293 +               ports_n_c++;
4294 +       }
4295 +       
4296 +       return ipt_register_match(&rpc_match);
4297 +}
4298 +
4299 +
4300 +static void fini(void)
4301 +{
4302 +       DEBUGP("unregistering match\n");
4303 +       ipt_unregister_match(&rpc_match);
4304 +
4305 +       DEBUGP("decrementing usage counts\n");
4306 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
4307 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
4308 +}
4309 +
4310 +
4311 +module_init(init);
4312 +module_exit(fini);
4313 +
4314 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_string.c linux-2.6.5-rc1/net/ipv4/netfilter/ipt_string.c
4315 --- linux-2.6.5-rc1.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 00:00:00.000000000 +0000
4316 +++ linux-2.6.5-rc1/net/ipv4/netfilter/ipt_string.c     2004-03-16 12:06:26.000000000 +0000
4317 @@ -0,0 +1,218 @@
4318 +/* Kernel module to match a string into a packet.
4319 + *
4320 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
4321 + * 
4322 + * ChangeLog
4323 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
4324 + *             Fixed SMP re-entrancy problem using per-cpu data areas
4325 + *             for the skip/shift tables.
4326 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
4327 + *             Fixed kernel panic, due to overrunning boyer moore string
4328 + *             tables. Also slightly tweaked heuristic for deciding what
4329 + *             search algo to use.
4330 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
4331 + *             Implemented Boyer Moore Sublinear search algorithm
4332 + *             alongside the existing linear search based on memcmp().
4333 + *             Also a quick check to decide which method to use on a per
4334 + *             packet basis.
4335 + */
4336 +
4337 +#include <linux/smp.h>
4338 +#include <linux/module.h>
4339 +#include <linux/skbuff.h>
4340 +#include <linux/file.h>
4341 +#include <net/sock.h>
4342 +
4343 +#include <linux/netfilter_ipv4/ip_tables.h>
4344 +#include <linux/netfilter_ipv4/ipt_string.h>
4345 +
4346 +MODULE_LICENSE("GPL");
4347 +
4348 +struct string_per_cpu {
4349 +       int *skip;
4350 +       int *shift;
4351 +       int *len;
4352 +};
4353 +
4354 +struct string_per_cpu *bm_string_data=NULL;
4355 +
4356 +/* Boyer Moore Sublinear string search - VERY FAST */
4357 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
4358 +{
4359 +       int M1, right_end, sk, sh;  
4360 +       int ended, j, i;
4361 +
4362 +       int *skip, *shift, *len;
4363 +       
4364 +       /* use data suitable for this CPU */
4365 +       shift=bm_string_data[smp_processor_id()].shift;
4366 +       skip=bm_string_data[smp_processor_id()].skip;
4367 +       len=bm_string_data[smp_processor_id()].len;
4368 +       
4369 +       /* Setup skip/shift tables */
4370 +       M1 = right_end = needle_len-1;
4371 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
4372 +       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
4373 +
4374 +       for (i = 1; i < needle_len; i++) {   
4375 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
4376 +               len[i] = j;  
4377 +       }  
4378 +
4379 +       shift[0] = 1;  
4380 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
4381 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
4382 +       ended = 0;  
4383 +       
4384 +       for (i = 0; i < needle_len; i++) {  
4385 +               if (len[i] == M1 - i) ended = i;  
4386 +               if (ended) shift[i] = ended;  
4387 +       }  
4388 +
4389 +       /* Do the search*/  
4390 +       while (right_end < haystack_len)
4391 +       {
4392 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
4393 +               if (i == needle_len) {
4394 +                       return haystack+(right_end - M1);
4395 +               }
4396 +               
4397 +               sk = skip[haystack[right_end - i]];  
4398 +               sh = shift[i];
4399 +               right_end = max(right_end - i + sk, right_end + sh);  
4400 +       }
4401 +
4402 +       return NULL;
4403 +}  
4404 +
4405 +/* Linear string search based on memcmp() */
4406 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
4407 +{
4408 +       char *k = haystack + (haystack_len-needle_len);
4409 +       char *t = haystack;
4410 +       
4411 +       while ( t <= k ) {
4412 +               if (memcmp(t, needle, needle_len) == 0)
4413 +                       return t;
4414 +               t++;
4415 +       }
4416 +
4417 +       return NULL;
4418 +}
4419 +
4420 +
4421 +static int
4422 +match(const struct sk_buff *skb,
4423 +      const struct net_device *in,
4424 +      const struct net_device *out,
4425 +      const void *matchinfo,
4426 +      int offset,
4427 +      const void *hdr,
4428 +      u_int16_t datalen,
4429 +      int *hotdrop)
4430 +{
4431 +       const struct ipt_string_info *info = matchinfo;
4432 +       struct iphdr *ip = skb->nh.iph;
4433 +       int hlen, nlen;
4434 +       char *needle, *haystack;
4435 +       proc_ipt_search search=search_linear;
4436 +
4437 +       if ( !ip ) return 0;
4438 +
4439 +       /* get lenghts, and validate them */
4440 +       nlen=info->len;
4441 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
4442 +       if ( nlen > hlen ) return 0;
4443 +
4444 +       needle=(char *)&info->string;
4445 +       haystack=(char *)ip+(ip->ihl*4);
4446 +
4447 +       /* The sublinear search comes in to its own
4448 +        * on the larger packets */
4449 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
4450 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
4451 +               if ( hlen < BM_MAX_HLEN ) {
4452 +                       search=search_sublinear;
4453 +               }else{
4454 +                       if (net_ratelimit())
4455 +                               printk(KERN_INFO "ipt_string: Packet too big "
4456 +                                       "to attempt sublinear string search "
4457 +                                       "(%d bytes)\n", hlen );
4458 +               }
4459 +       }
4460 +       
4461 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
4462 +}
4463 +
4464 +static int
4465 +checkentry(const char *tablename,
4466 +           const struct ipt_ip *ip,
4467 +           void *matchinfo,
4468 +           unsigned int matchsize,
4469 +           unsigned int hook_mask)
4470 +{
4471 +
4472 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
4473 +               return 0;
4474 +
4475 +       return 1;
4476 +}
4477 +
4478 +void string_freeup_data(void)
4479 +{
4480 +       int c;
4481 +       
4482 +       if ( bm_string_data ) {
4483 +               for(c=0; c<smp_num_cpus; c++) {
4484 +                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
4485 +                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
4486 +                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
4487 +               }
4488 +               kfree(bm_string_data);
4489 +       }
4490 +}
4491 +
4492 +static struct ipt_match string_match
4493 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
4494 +
4495 +static int __init init(void)
4496 +{
4497 +       int c;
4498 +       size_t tlen;
4499 +       size_t alen;
4500 +
4501 +       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
4502 +       alen=sizeof(int)*BM_MAX_HLEN;
4503 +       
4504 +       /* allocate array of structures */
4505 +       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
4506 +               return 0;
4507 +       }
4508 +       
4509 +       memset(bm_string_data, 0, tlen);
4510 +       
4511 +       /* allocate our skip/shift tables */
4512 +       for(c=0; c<smp_num_cpus; c++) {
4513 +               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
4514 +                       goto alloc_fail;
4515 +               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
4516 +                       goto alloc_fail;
4517 +               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
4518 +                       goto alloc_fail;
4519 +       }
4520 +       
4521 +       return ipt_register_match(&string_match);
4522 +
4523 +alloc_fail:
4524 +       string_freeup_data();
4525 +       return 0;
4526 +}
4527 +
4528 +static void __exit fini(void)
4529 +{
4530 +       ipt_unregister_match(&string_match);
4531 +       string_freeup_data();
4532 +}
4533 +
4534 +module_init(init);
4535 +module_exit(fini);
4536 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/tcp_ipv4.c linux-2.6.5-rc1/net/ipv4/tcp_ipv4.c
4537 --- linux-2.6.5-rc1.org/net/ipv4/tcp_ipv4.c     2004-03-16 05:45:58.000000000 +0000
4538 +++ linux-2.6.5-rc1/net/ipv4/tcp_ipv4.c 2004-03-16 12:04:38.000000000 +0000
4539 @@ -2667,6 +2667,7 @@
4540  EXPORT_SYMBOL(tcp_v4_connect);
4541  EXPORT_SYMBOL(tcp_v4_do_rcv);
4542  EXPORT_SYMBOL(tcp_v4_lookup_listener);
4543 +EXPORT_SYMBOL(tcp_v4_lookup);
4544  EXPORT_SYMBOL(tcp_v4_rebuild_header);
4545  EXPORT_SYMBOL(tcp_v4_remember_stamp);
4546  EXPORT_SYMBOL(tcp_v4_send_check);
4547 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv4/udp.c linux-2.6.5-rc1/net/ipv4/udp.c
4548 --- linux-2.6.5-rc1.org/net/ipv4/udp.c  2004-03-16 05:45:49.000000000 +0000
4549 +++ linux-2.6.5-rc1/net/ipv4/udp.c      2004-03-16 12:04:38.000000000 +0000
4550 @@ -1543,6 +1543,7 @@
4551  EXPORT_SYMBOL(udp_port_rover);
4552  EXPORT_SYMBOL(udp_prot);
4553  EXPORT_SYMBOL(udp_sendmsg);
4554 +EXPORT_SYMBOL(udp_v4_lookup);
4555  
4556  #ifdef CONFIG_PROC_FS
4557  EXPORT_SYMBOL(udp_proc_register);
4558 diff -Nur --exclude '*.orig' linux-2.6.5-rc1.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.5-rc1/net/ipv6/netfilter/ip6t_owner.c
4559 --- linux-2.6.5-rc1.org/net/ipv6/netfilter/ip6t_owner.c 2004-03-16 05:47:17.000000000 +0000
4560 +++ linux-2.6.5-rc1/net/ipv6/netfilter/ip6t_owner.c     2004-03-16 12:04:42.000000000 +0000
4561 @@ -21,6 +21,38 @@
4562  MODULE_LICENSE("GPL");
4563  
4564  static int
4565 +match_comm(const struct sk_buff *skb, const char *comm)
4566 +{
4567 +       struct task_struct *p;
4568 +       struct files_struct *files;
4569 +       int i;
4570 +
4571 +       read_lock(&tasklist_lock);
4572 +       for_each_task(p) {
4573 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
4574 +                       continue;
4575 +
4576 +               task_lock(p);
4577 +               files = p->files;
4578 +               if(files) {
4579 +                       read_lock(&files->file_lock);
4580 +                       for (i=0; i < files->max_fds; i++) {
4581 +                               if (fcheck_files(files, i) == skb->sk->socket->file) {
4582 +                                       read_unlock(&files->file_lock);
4583 +                                       task_unlock(p);
4584 +                                       read_unlock(&tasklist_lock);
4585 +                                       return 1;
4586 +                               }
4587 +                       }
4588 +                       read_unlock(&files->file_lock);
4589 +               }
4590 +               task_unlock(p);
4591 +       }
4592 +       read_unlock(&tasklist_lock);
4593 +       return 0;
4594 +}
4595 +
4596 +static int
4597  match_pid(const struct sk_buff *skb, pid_t pid)
4598  {
4599         struct task_struct *p;
4600 @@ -125,6 +157,12 @@
4601                         return 0;
4602         }
4603  
4604 +       if(info->match & IP6T_OWNER_COMM) {
4605 +               if (!match_comm(skb, info->comm) ^
4606 +                   !!(info->invert & IP6T_OWNER_COMM))
4607 +                       return 0;
4608 +       }
4609 +
4610         return 1;
4611  }
4612  
This page took 0.346799 seconds and 3 git commands to generate.