]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.0-t11-netfilter-20031210.patch
- obsolete (new driver name sym53c8xx_2 doesn't conflict now)
[packages/kernel.git] / 2.6.0-t11-netfilter-20031210.patch
1 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter.h linux-2.6.0-test11/include/linux/netfilter.h
2 --- linux-2.6.0-test11.org/include/linux/netfilter.h    2003-11-26 21:44:11.000000000 +0100
3 +++ linux-2.6.0-test11/include/linux/netfilter.h        2003-12-10 23:13:24.656327752 +0100
4 @@ -23,6 +23,7 @@
5     <= 0x2000 is used for protocol-flags. */
6  #define NFC_UNKNOWN 0x4000
7  #define NFC_ALTERED 0x8000
8 +#define NFC_TRACE   0x10000
9  
10  #ifdef __KERNEL__
11  #include <linux/config.h>
12 @@ -99,6 +100,24 @@
13  
14  extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
15  
16 +typedef void nf_logfn(unsigned int hooknum,
17 +                     const struct sk_buff *skb,
18 +                     const struct net_device *in,
19 +                     const struct net_device *out,
20 +                     const char *prefix);
21 +
22 +/* Function to register/unregister log function. */
23 +int nf_log_register(int pf, nf_logfn *logfn);
24 +void nf_log_unregister(int pf, nf_logfn *logfn);
25 +
26 +/* Calls the registered backend logging function */
27 +void nf_log_packet(int pf,
28 +                  unsigned int hooknum,
29 +                  const struct sk_buff *skb,
30 +                  const struct net_device *in,
31 +                  const struct net_device *out,
32 +                  const char *fmt, ...);
33 +                   
34  /* Activate hook; either okfn or kfree_skb called, unless a hook
35     returns NF_STOLEN (in which case, it's up to the hook to deal with
36     the consequences).
37 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_helpers.h linux-2.6.0-test11/include/linux/netfilter_helpers.h
38 --- linux-2.6.0-test11.org/include/linux/netfilter_helpers.h    1970-01-01 01:00:00.000000000 +0100
39 +++ linux-2.6.0-test11/include/linux/netfilter_helpers.h        2003-12-10 23:14:12.889995120 +0100
40 @@ -0,0 +1,133 @@
41 +/*
42 + * Helpers for netfiler modules.  This file provides implementations for basic
43 + * functions such as strncasecmp(), etc.
44 + *
45 + * gcc will warn for defined but unused functions, so we only include the
46 + * functions requested.  The following macros are used:
47 + *   NF_NEED_STRNCASECMP        nf_strncasecmp()
48 + *   NF_NEED_STRTOU16           nf_strtou16()
49 + *   NF_NEED_STRTOU32           nf_strtou32()
50 + */
51 +#ifndef _NETFILTER_HELPERS_H
52 +#define _NETFILTER_HELPERS_H
53 +
54 +/* Only include these functions for kernel code. */
55 +#ifdef __KERNEL__
56 +
57 +#include <linux/ctype.h>
58 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
59 +
60 +/*
61 + * The standard strncasecmp()
62 + */
63 +#ifdef NF_NEED_STRNCASECMP
64 +static int
65 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
66 +{
67 +    if (s1 == NULL || s2 == NULL)
68 +    {
69 +        if (s1 == NULL && s2 == NULL)
70 +        {
71 +            return 0;
72 +        }
73 +        return (s1 == NULL) ? -1 : 1;
74 +    }
75 +    while (len > 0 && tolower(*s1) == tolower(*s2))
76 +    {
77 +        len--;
78 +        s1++;
79 +        s2++;
80 +    }
81 +    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
82 +}
83 +#endif /* NF_NEED_STRNCASECMP */
84 +
85 +/*
86 + * Parse a string containing a 16-bit unsigned integer.
87 + * Returns the number of chars used, or zero if no number is found.
88 + */
89 +#ifdef NF_NEED_STRTOU16
90 +static int
91 +nf_strtou16(const char* pbuf, u_int16_t* pval)
92 +{
93 +    int n = 0;
94 +
95 +    *pval = 0;
96 +    while (isdigit(pbuf[n]))
97 +    {
98 +        *pval = (*pval * 10) + (pbuf[n] - '0');
99 +        n++;
100 +    }
101 +
102 +    return n;
103 +}
104 +#endif /* NF_NEED_STRTOU16 */
105 +
106 +/*
107 + * Parse a string containing a 32-bit unsigned integer.
108 + * Returns the number of chars used, or zero if no number is found.
109 + */
110 +#ifdef NF_NEED_STRTOU32
111 +static int
112 +nf_strtou32(const char* pbuf, u_int32_t* pval)
113 +{
114 +    int n = 0;
115 +
116 +    *pval = 0;
117 +    while (pbuf[n] >= '0' && pbuf[n] <= '9')
118 +    {
119 +        *pval = (*pval * 10) + (pbuf[n] - '0');
120 +        n++;
121 +    }
122 +
123 +    return n;
124 +}
125 +#endif /* NF_NEED_STRTOU32 */
126 +
127 +/*
128 + * Given a buffer and length, advance to the next line and mark the current
129 + * line.
130 + */
131 +#ifdef NF_NEED_NEXTLINE
132 +static int
133 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
134 +{
135 +    uint    off = *poff;
136 +    uint    physlen = 0;
137 +
138 +    if (off >= len)
139 +    {
140 +        return 0;
141 +    }
142 +
143 +    while (p[off] != '\n')
144 +    {
145 +        if (len-off <= 1)
146 +        {
147 +            return 0;
148 +        }
149 +
150 +        physlen++;
151 +        off++;
152 +    }
153 +
154 +    /* if we saw a crlf, physlen needs adjusted */
155 +    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
156 +    {
157 +        physlen--;
158 +    }
159 +
160 +    /* advance past the newline */
161 +    off++;
162 +
163 +    *plineoff = *poff;
164 +    *plinelen = physlen;
165 +    *poff = off;
166 +
167 +    return 1;
168 +}
169 +#endif /* NF_NEED_NEXTLINE */
170 +
171 +#endif /* __KERNEL__ */
172 +
173 +#endif /* _NETFILTER_HELPERS_H */
174 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
175 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h  1970-01-01 01:00:00.000000000 +0100
176 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h      2003-12-10 23:13:55.776596752 +0100
177 @@ -0,0 +1,70 @@
178 +#ifndef _IP_CT_CUSEEME
179 +#define _IP_CT_CUSEEME
180 +
181 +#define CUSEEME_PORT 7648
182 +
183 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
184 +
185 +#pragma pack(1)
186 +/* CuSeeMe data header */
187 +struct cu_header {
188 +       u_int16_t       dest_family;
189 +       u_int16_t       dest_port;
190 +       u_int32_t       dest_addr;
191 +       int16_t         family;
192 +       u_int16_t       port;
193 +       u_int32_t       addr;
194 +       u_int32_t       seq;
195 +       u_int16_t       msg;
196 +       u_int16_t       data_type;
197 +                               /* possible values:
198 +                                * 1    small video
199 +                                * 2    big video
200 +                                * 3    audio
201 +                                * 100  acknowledge connectivity when there
202 +                                *      is nothing else to send
203 +                                * 101  OpenContinue packet
204 +                                * 104  display a text message and 
205 +                                *      disconnect (used by reflector to
206 +                                *      kick clients off)
207 +                                * 105  display a text message (welcome
208 +                                *      message from reflector)
209 +                                * 106  exchanged among reflectors for
210 +                                *      reflector interoperation
211 +                                * 107  carry aux stream data when there is
212 +                                *      no video to piggy-back on
213 +                                * 108  obsolete (used in Mac alpha version)
214 +                                * 109  obsolete (used in Mac alpha version)
215 +                                * 110  used for data rate control
216 +                                * 111  used for data rate control
217 +                                * 256  aux data control messages
218 +                                * 257  aux data packets
219 +                                * */
220 +       u_int16_t       packet_len;
221 +};
222 +
223 +/* Open Continue Header */
224 +struct oc_header {
225 +       struct cu_header        cu_head;
226 +       u_int16_t       client_count; /* Number of client info structs */
227 +       u_int32_t       seq_no;
228 +       char            user_name[20];
229 +       char            stuff[4];     /* Flags, version stuff, etc */
230 +};
231 +
232 +/* Client info structures */
233 +struct client_info {
234 +       u_int32_t       address;      /* Client address */
235 +       char            stuff[8];     /* Flags, pruning bitfield, packet counts, etc */
236 +};
237 +#pragma pack()
238 +
239 +/* This structure is per expected connection */
240 +struct ip_ct_cuseeme_expect {
241 +};
242 +
243 +/* This structure exists only once per master */
244 +struct ip_ct_cuseeme_master {
245 +};
246 +
247 +#endif /* _IP_CT_CUSEEME */
248 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack.h
249 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack.h  2003-11-26 21:45:37.000000000 +0100
250 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack.h      2003-12-10 23:22:29.227540344 +0100
251 @@ -51,10 +51,13 @@
252  
253  #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
254  #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
255 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
256  
257  /* per conntrack: protocol private data */
258  union ip_conntrack_proto {
259         /* insert conntrack proto private data here */
260 +       struct ip_ct_gre_expect gre;
261 +       struct ip_ct_gre gre;
262         struct ip_ct_tcp tcp;
263         struct ip_ct_icmp icmp;
264  };
265 @@ -64,6 +67,13 @@
266  };
267  
268  /* Add protocol helper include file here */
269 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
270 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
271 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
272 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
273 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
274 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
275 +
276  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
277  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
278  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
279 @@ -71,6 +81,13 @@
280  /* per expectation: application helper private data */
281  union ip_conntrack_expect_help {
282         /* insert conntrack helper private data (expect) here */
283 +       struct ip_ct_pptp_expect exp_pptp_info;
284 +       struct ip_ct_talk_expect exp_talk_info;
285 +       struct ip_ct_rtsp_master ct_rtsp_info;
286 +       struct ip_ct_rtsp_expect exp_rtsp_info;
287 +       struct ip_ct_rsh_expect exp_rsh_info;
288 +       struct ip_ct_mms_expect exp_mms_info;
289 +       struct ip_ct_h225_expect exp_h225_info;
290         struct ip_ct_amanda_expect exp_amanda_info;
291         struct ip_ct_ftp_expect exp_ftp_info;
292         struct ip_ct_irc_expect exp_irc_info;
293 @@ -85,16 +102,23 @@
294  /* per conntrack: application helper private data */
295  union ip_conntrack_help {
296         /* insert conntrack helper private data (master) here */
297 +       struct ip_ct_pptp_master ct_pptp_info;
298 +       struct ip_ct_talk_master ct_talk_info;
299 +       struct ip_ct_rsh_master ct_rsh_info;
300 +       struct ip_ct_mms_master ct_mms_info;
301 +       struct ip_ct_h225_master ct_h225_info;
302         struct ip_ct_ftp_master ct_ftp_info;
303         struct ip_ct_irc_master ct_irc_info;
304  };
305  
306  #ifdef CONFIG_IP_NF_NAT_NEEDED
307  #include <linux/netfilter_ipv4/ip_nat.h>
308 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
309  
310  /* per conntrack: nat application helper private data */
311  union ip_conntrack_nat_help {
312         /* insert nat helper private data here */
313 +       struct ip_nat_pptp nat_pptp_info;
314  };
315  #endif
316  
317 @@ -206,6 +230,9 @@
318         } nat;
319  #endif /* CONFIG_IP_NF_NAT_NEEDED */
320  
321 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
322 +       unsigned long mark;
323 +#endif
324  };
325  
326  /* get master conntrack via master expectation */
327 @@ -247,6 +274,9 @@
328  extern void ip_ct_refresh(struct ip_conntrack *ct,
329                           unsigned long extra_jiffies);
330  
331 +/* Kill conntrack */
332 +extern void ip_ct_death_by_timeout(unsigned long ul_conntrack);
333 +
334  /* These are for NAT.  Icky. */
335  /* Call me when a conntrack is destroyed. */
336  extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
337 @@ -268,6 +298,9 @@
338  
339  extern unsigned int ip_conntrack_htable_size;
340  
341 +/* A fake conntrack entry which never vanishes. */
342 +extern struct ip_conntrack ip_conntrack_untracked;
343 +
344  /* eg. PROVIDES_CONNTRACK(ftp); */
345  #define PROVIDES_CONNTRACK(name)                        \
346          int needs_ip_conntrack_##name;                  \
347 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_h323.h
348 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h     1970-01-01 01:00:00.000000000 +0100
349 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2003-12-10 23:13:58.176231952 +0100
350 @@ -0,0 +1,30 @@
351 +#ifndef _IP_CONNTRACK_H323_H
352 +#define _IP_CONNTRACK_H323_H
353 +/* H.323 connection tracking. */
354 +
355 +#ifdef __KERNEL__
356 +/* Protects H.323 related data */
357 +DECLARE_LOCK_EXTERN(ip_h323_lock);
358 +#endif
359 +
360 +/* Default H.225 port */
361 +#define H225_PORT      1720
362 +
363 +/* This structure is per expected connection */
364 +struct ip_ct_h225_expect {
365 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
366 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
367 +       unsigned int offset;            /* offset of the address in the payload */
368 +};
369 +
370 +/* This structure exists only once per master */
371 +struct ip_ct_h225_master {
372 +       int is_h225;                            /* H.225 or H.245 connection */
373 +#ifdef CONFIG_IP_NF_NAT_NEEDED
374 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
375 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
376 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
377 +#endif
378 +};
379 +
380 +#endif /* _IP_CONNTRACK_H323_H */
381 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_mms.h
382 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h      1970-01-01 01:00:00.000000000 +0100
383 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_mms.h  2003-12-10 23:14:02.755535792 +0100
384 @@ -0,0 +1,31 @@
385 +#ifndef _IP_CONNTRACK_MMS_H
386 +#define _IP_CONNTRACK_MMS_H
387 +/* MMS tracking. */
388 +
389 +#ifdef __KERNEL__
390 +#include <linux/netfilter_ipv4/lockhelp.h>
391 +
392 +DECLARE_LOCK_EXTERN(ip_mms_lock);
393 +
394 +#define MMS_PORT                         1755
395 +#define MMS_SRV_MSG_ID                   196610
396 +
397 +#define MMS_SRV_MSG_OFFSET               36
398 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
399 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
400 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
401 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
402 +#endif
403 +
404 +/* This structure is per expected connection */
405 +struct ip_ct_mms_expect {
406 +       u_int32_t len;
407 +       u_int32_t padding;
408 +       u_int16_t port;
409 +};
410 +
411 +/* This structure exists only once per master */
412 +struct ip_ct_mms_master {
413 +};
414 +
415 +#endif /* _IP_CONNTRACK_MMS_H */
416 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
417 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h     1970-01-01 01:00:00.000000000 +0100
418 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 2003-11-17 09:09:34.000000000 +0100
419 @@ -0,0 +1,313 @@
420 +/* PPTP constants and structs */
421 +#ifndef _CONNTRACK_PPTP_H
422 +#define _CONNTRACK_PPTP_H
423 +
424 +/* state of the control session */
425 +enum pptp_ctrlsess_state {
426 +       PPTP_SESSION_NONE,                      /* no session present */
427 +       PPTP_SESSION_ERROR,                     /* some session error */
428 +       PPTP_SESSION_STOPREQ,                   /* stop_sess request seen */
429 +       PPTP_SESSION_REQUESTED,                 /* start_sess request seen */
430 +       PPTP_SESSION_CONFIRMED,                 /* session established */
431 +};
432 +
433 +/* state of the call inside the control session */
434 +enum pptp_ctrlcall_state {
435 +       PPTP_CALL_NONE,
436 +       PPTP_CALL_ERROR,
437 +       PPTP_CALL_OUT_REQ,
438 +       PPTP_CALL_OUT_CONF,
439 +       PPTP_CALL_IN_REQ,
440 +       PPTP_CALL_IN_REP,
441 +       PPTP_CALL_IN_CONF,
442 +       PPTP_CALL_CLEAR_REQ,
443 +};
444 +
445 +
446 +/* conntrack private data */
447 +struct ip_ct_pptp_master {
448 +       enum pptp_ctrlsess_state sstate;        /* session state */
449 +
450 +       /* everything below is going to be per-expectation in newnat,
451 +        * since there could be more than one call within one session */
452 +       enum pptp_ctrlcall_state cstate;        /* call state */
453 +       u_int16_t pac_call_id;                  /* call id of PAC, host byte order */
454 +       u_int16_t pns_call_id;                  /* call id of PNS, host byte order */
455 +};
456 +
457 +/* conntrack_expect private member */
458 +struct ip_ct_pptp_expect {
459 +       enum pptp_ctrlcall_state cstate;        /* call state */
460 +       u_int16_t pac_call_id;                  /* call id of PAC */
461 +       u_int16_t pns_call_id;                  /* call id of PNS */
462 +};
463 +
464 +
465 +#ifdef __KERNEL__
466 +
467 +#include <linux/netfilter_ipv4/lockhelp.h>
468 +DECLARE_LOCK_EXTERN(ip_pptp_lock);
469 +
470 +#define IP_CONNTR_PPTP         PPTP_CONTROL_PORT
471 +
472 +union pptp_ctrl_union {
473 +                void                           *rawreq;
474 +               struct PptpStartSessionRequest  *sreq;
475 +               struct PptpStartSessionReply    *srep;
476 +               struct PptpStopSessionReqest    *streq;
477 +               struct PptpStopSessionReply     *strep;
478 +                struct PptpOutCallRequest       *ocreq;
479 +                struct PptpOutCallReply         *ocack;
480 +                struct PptpInCallRequest        *icreq;
481 +                struct PptpInCallReply          *icack;
482 +                struct PptpInCallConnected      *iccon;
483 +               struct PptpClearCallRequest     *clrreq;
484 +                struct PptpCallDisconnectNotify *disc;
485 +                struct PptpWanErrorNotify       *wanerr;
486 +                struct PptpSetLinkInfo          *setlink;
487 +};
488 +
489 +
490 +
491 +#define PPTP_CONTROL_PORT      1723
492 +
493 +#define PPTP_PACKET_CONTROL    1
494 +#define PPTP_PACKET_MGMT       2
495 +
496 +#define PPTP_MAGIC_COOKIE      0x1a2b3c4d
497 +
498 +struct pptp_pkt_hdr {
499 +       __u16   packetLength;
500 +       __u16   packetType;
501 +       __u32   magicCookie;
502 +};
503 +
504 +/* PptpControlMessageType values */
505 +#define PPTP_START_SESSION_REQUEST     1
506 +#define PPTP_START_SESSION_REPLY       2
507 +#define PPTP_STOP_SESSION_REQUEST      3
508 +#define PPTP_STOP_SESSION_REPLY                4
509 +#define PPTP_ECHO_REQUEST              5
510 +#define PPTP_ECHO_REPLY                        6
511 +#define PPTP_OUT_CALL_REQUEST          7
512 +#define PPTP_OUT_CALL_REPLY            8
513 +#define PPTP_IN_CALL_REQUEST           9
514 +#define PPTP_IN_CALL_REPLY             10
515 +#define PPTP_IN_CALL_CONNECT           11
516 +#define PPTP_CALL_CLEAR_REQUEST                12
517 +#define PPTP_CALL_DISCONNECT_NOTIFY    13
518 +#define PPTP_WAN_ERROR_NOTIFY          14
519 +#define PPTP_SET_LINK_INFO             15
520 +
521 +#define PPTP_MSG_MAX                   15
522 +
523 +/* PptpGeneralError values */
524 +#define PPTP_ERROR_CODE_NONE           0
525 +#define PPTP_NOT_CONNECTED             1
526 +#define PPTP_BAD_FORMAT                        2
527 +#define PPTP_BAD_VALUE                 3
528 +#define PPTP_NO_RESOURCE               4
529 +#define PPTP_BAD_CALLID                        5
530 +#define PPTP_REMOVE_DEVICE_ERROR       6
531 +
532 +struct PptpControlHeader {
533 +       __u16   messageType;
534 +       __u16   reserved;
535 +};
536 +
537 +/* FramingCapability Bitmap Values */
538 +#define PPTP_FRAME_CAP_ASYNC           0x1
539 +#define PPTP_FRAME_CAP_SYNC            0x2
540 +
541 +/* BearerCapability Bitmap Values */
542 +#define PPTP_BEARER_CAP_ANALOG         0x1
543 +#define PPTP_BEARER_CAP_DIGITAL                0x2
544 +
545 +struct PptpStartSessionRequest {
546 +       __u16   protocolVersion;
547 +       __u8    reserved1;
548 +       __u8    reserved2;
549 +       __u32   framingCapability;
550 +       __u32   bearerCapability;
551 +       __u16   maxChannels;
552 +       __u16   firmwareRevision;
553 +       __u8    hostName[64];
554 +       __u8    vendorString[64];
555 +};
556 +
557 +/* PptpStartSessionResultCode Values */
558 +#define PPTP_START_OK                  1
559 +#define PPTP_START_GENERAL_ERROR       2
560 +#define PPTP_START_ALREADY_CONNECTED   3
561 +#define PPTP_START_NOT_AUTHORIZED      4
562 +#define PPTP_START_UNKNOWN_PROTOCOL    5
563 +
564 +struct PptpStartSessionReply {
565 +       __u16   protocolVersion;
566 +       __u8    resultCode;
567 +       __u8    generalErrorCode;
568 +       __u32   framingCapability;
569 +       __u32   bearerCapability;
570 +       __u16   maxChannels;
571 +       __u16   firmwareRevision;
572 +       __u8    hostName[64];
573 +       __u8    vendorString[64];
574 +};
575 +
576 +/* PptpStopReasons */
577 +#define PPTP_STOP_NONE                 1
578 +#define PPTP_STOP_PROTOCOL             2
579 +#define PPTP_STOP_LOCAL_SHUTDOWN       3
580 +
581 +struct PptpStopSessionRequest {
582 +       __u8    reason;
583 +};
584 +
585 +/* PptpStopSessionResultCode */
586 +#define PPTP_STOP_OK                   1
587 +#define PPTP_STOP_GENERAL_ERROR                2
588 +
589 +struct PptpStopSessionReply {
590 +       __u8    resultCode;
591 +       __u8    generalErrorCode;
592 +};
593 +
594 +struct PptpEchoRequest {
595 +       __u32 identNumber;
596 +};
597 +
598 +/* PptpEchoReplyResultCode */
599 +#define PPTP_ECHO_OK                   1
600 +#define PPTP_ECHO_GENERAL_ERROR                2
601 +
602 +struct PptpEchoReply {
603 +       __u32   identNumber;
604 +       __u8    resultCode;
605 +       __u8    generalErrorCode;
606 +       __u16   reserved;
607 +};
608 +
609 +/* PptpFramingType */
610 +#define PPTP_ASYNC_FRAMING             1
611 +#define PPTP_SYNC_FRAMING              2
612 +#define PPTP_DONT_CARE_FRAMING         3
613 +
614 +/* PptpCallBearerType */
615 +#define PPTP_ANALOG_TYPE               1
616 +#define PPTP_DIGITAL_TYPE              2
617 +#define PPTP_DONT_CARE_BEARER_TYPE     3
618 +
619 +struct PptpOutCallRequest {
620 +       __u16   callID;
621 +       __u16   callSerialNumber;
622 +       __u32   minBPS;
623 +       __u32   maxBPS;
624 +       __u32   bearerType;
625 +       __u32   framingType;
626 +       __u16   packetWindow;
627 +       __u16   packetProcDelay;
628 +       __u16   reserved1;
629 +       __u16   phoneNumberLength;
630 +       __u16   reserved2;
631 +       __u8    phoneNumber[64];
632 +       __u8    subAddress[64];
633 +};
634 +
635 +/* PptpCallResultCode */
636 +#define PPTP_OUTCALL_CONNECT           1
637 +#define PPTP_OUTCALL_GENERAL_ERROR     2
638 +#define PPTP_OUTCALL_NO_CARRIER                3
639 +#define PPTP_OUTCALL_BUSY              4
640 +#define PPTP_OUTCALL_NO_DIAL_TONE      5
641 +#define PPTP_OUTCALL_TIMEOUT           6
642 +#define PPTP_OUTCALL_DONT_ACCEPT       7
643 +
644 +struct PptpOutCallReply {
645 +       __u16   callID;
646 +       __u16   peersCallID;
647 +       __u8    resultCode;
648 +       __u8    generalErrorCode;
649 +       __u16   causeCode;
650 +       __u32   connectSpeed;
651 +       __u16   packetWindow;
652 +       __u16   packetProcDelay;
653 +       __u32   physChannelID;
654 +};
655 +
656 +struct PptpInCallRequest {
657 +       __u16   callID;
658 +       __u16   callSerialNumber;
659 +       __u32   callBearerType;
660 +       __u32   physChannelID;
661 +       __u16   dialedNumberLength;
662 +       __u16   dialingNumberLength;
663 +       __u8    dialedNumber[64];
664 +       __u8    dialingNumber[64];
665 +       __u8    subAddress[64];
666 +};
667 +
668 +/* PptpInCallResultCode */
669 +#define PPTP_INCALL_ACCEPT             1
670 +#define PPTP_INCALL_GENERAL_ERROR      2
671 +#define PPTP_INCALL_DONT_ACCEPT                3
672 +
673 +struct PptpInCallReply {
674 +       __u16   callID;
675 +       __u16   peersCallID;
676 +       __u8    resultCode;
677 +       __u8    generalErrorCode;
678 +       __u16   packetWindow;
679 +       __u16   packetProcDelay;
680 +       __u16   reserved;
681 +};
682 +
683 +struct PptpInCallConnected {
684 +       __u16   peersCallID;
685 +       __u16   reserved;
686 +       __u32   connectSpeed;
687 +       __u16   packetWindow;
688 +       __u16   packetProcDelay;
689 +       __u32   callFramingType;
690 +};
691 +
692 +struct PptpClearCallRequest {
693 +       __u16   callID;
694 +       __u16   reserved;
695 +};
696 +
697 +struct PptpCallDisconnectNotify {
698 +       __u16   callID;
699 +       __u8    resultCode;
700 +       __u8    generalErrorCode;
701 +       __u16   causeCode;
702 +       __u16   reserved;
703 +       __u8    callStatistics[128];
704 +};
705 +
706 +struct PptpWanErrorNotify {
707 +       __u16   peersCallID;
708 +       __u16   reserved;
709 +       __u32   crcErrors;
710 +       __u32   framingErrors;
711 +       __u32   hardwareOverRuns;
712 +       __u32   bufferOverRuns;
713 +       __u32   timeoutErrors;
714 +       __u32   alignmentErrors;
715 +};
716 +
717 +struct PptpSetLinkInfo {
718 +       __u16   peersCallID;
719 +       __u16   reserved;
720 +       __u32   sendAccm;
721 +       __u32   recvAccm;
722 +};
723 +
724 +
725 +struct pptp_priv_data {
726 +       __u16   call_id;
727 +       __u16   mcall_id;
728 +       __u16   pcall_id;
729 +};
730 +
731 +#endif /* __KERNEL__ */
732 +#endif /* _CONNTRACK_PPTP_H */
733 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
734 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h        1970-01-01 01:00:00.000000000 +0100
735 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h    2003-11-17 09:09:34.000000000 +0100
736 @@ -0,0 +1,123 @@
737 +#ifndef _CONNTRACK_PROTO_GRE_H
738 +#define _CONNTRACK_PROTO_GRE_H
739 +#include <asm/byteorder.h>
740 +
741 +/* GRE PROTOCOL HEADER */
742 +
743 +/* GRE Version field */
744 +#define GRE_VERSION_1701       0x0
745 +#define GRE_VERSION_PPTP       0x1
746 +
747 +/* GRE Protocol field */
748 +#define GRE_PROTOCOL_PPTP      0x880B
749 +
750 +/* GRE Flags */
751 +#define GRE_FLAG_C             0x80
752 +#define GRE_FLAG_R             0x40
753 +#define GRE_FLAG_K             0x20
754 +#define GRE_FLAG_S             0x10
755 +#define GRE_FLAG_A             0x80
756 +
757 +#define GRE_IS_C(f)    ((f)&GRE_FLAG_C)
758 +#define GRE_IS_R(f)    ((f)&GRE_FLAG_R)
759 +#define GRE_IS_K(f)    ((f)&GRE_FLAG_K)
760 +#define GRE_IS_S(f)    ((f)&GRE_FLAG_S)
761 +#define GRE_IS_A(f)    ((f)&GRE_FLAG_A)
762 +
763 +/* GRE is a mess: Four different standards */
764 +struct gre_hdr {
765 +#if defined(__LITTLE_ENDIAN_BITFIELD)
766 +       __u16   rec:3,
767 +               srr:1,
768 +               seq:1,
769 +               key:1,
770 +               routing:1,
771 +               csum:1,
772 +               version:3,
773 +               reserved:4,
774 +               ack:1;
775 +#elif defined(__BIG_ENDIAN_BITFIELD)
776 +       __u16   csum:1,
777 +               routing:1,
778 +               key:1,
779 +               seq:1,
780 +               srr:1,
781 +               rec:3,
782 +               ack:1,
783 +               reserved:4,
784 +               version:3;
785 +#else
786 +#error "Adjust your <asm/byteorder.h> defines"
787 +#endif
788 +       __u16   protocol;
789 +};
790 +
791 +/* modified GRE header for PPTP */
792 +struct gre_hdr_pptp {
793 +       __u8  flags;            /* bitfield */
794 +       __u8  version;          /* should be GRE_VERSION_PPTP */
795 +       __u16 protocol;         /* should be GRE_PROTOCOL_PPTP */
796 +       __u16 payload_len;      /* size of ppp payload, not inc. gre header */
797 +       __u16 call_id;          /* peer's call_id for this session */
798 +       __u32 seq;              /* sequence number.  Present if S==1 */
799 +       __u32 ack;              /* seq number of highest packet recieved by */
800 +                               /*  sender in this session */
801 +};
802 +
803 +
804 +/* this is part of ip_conntrack */
805 +struct ip_ct_gre {
806 +       unsigned int stream_timeout;
807 +       unsigned int timeout;
808 +};
809 +
810 +/* this is part of ip_conntrack_expect */
811 +struct ip_ct_gre_expect {
812 +       struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
813 +};
814 +
815 +#ifdef __KERNEL__
816 +struct ip_conntrack_expect;
817 +
818 +/* structure for original <-> reply keymap */
819 +struct ip_ct_gre_keymap {
820 +       struct list_head list;
821 +
822 +       struct ip_conntrack_tuple tuple;
823 +};
824 +
825 +
826 +/* add new tuple->key_reply pair to keymap */
827 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
828 +                        struct ip_conntrack_tuple *t,
829 +                        int reply);
830 +
831 +/* change an existing keymap entry */
832 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
833 +                            struct ip_conntrack_tuple *t);
834 +
835 +/* delete keymap entries */
836 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
837 +
838 +
839 +/* get pointer to gre key, if present */
840 +static inline u_int32_t *gre_key(struct gre_hdr *greh)
841 +{
842 +       if (!greh->key)
843 +               return NULL;
844 +       if (greh->csum || greh->routing)
845 +               return (u_int32_t *) (greh+sizeof(*greh)+4);
846 +       return (u_int32_t *) (greh+sizeof(*greh));
847 +}
848 +
849 +/* get pointer ot gre csum, if present */
850 +static inline u_int16_t *gre_csum(struct gre_hdr *greh)
851 +{
852 +       if (!greh->csum)
853 +               return NULL;
854 +       return (u_int16_t *) (greh+sizeof(*greh));
855 +}
856 +
857 +#endif /* __KERNEL__ */
858 +
859 +#endif /* _CONNTRACK_PROTO_GRE_H */
860 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
861 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h   1970-01-01 01:00:00.000000000 +0100
862 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_quake3.h       2003-12-10 23:14:06.243005616 +0100
863 @@ -0,0 +1,21 @@
864 +#ifndef _IP_CT_QUAKE3
865 +#define _IP_CT_QUAKE3
866 +
867 +/* Don't confuse with 27960, often used as the Server Port */
868 +#define QUAKE3_MASTER_PORT 27950
869 +
870 +struct quake3_search {
871 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
872 +       const char *pattern;
873 +       size_t plen;
874 +}; 
875 +
876 +/* This structure is per expected connection */
877 +struct ip_ct_quake3_expect {
878 +};
879 +
880 +/* This structure exists only once per master */
881 +struct ip_ct_quake3_master {
882 +};
883 +
884 +#endif /* _IP_CT_QUAKE3 */
885 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
886 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h      1970-01-01 01:00:00.000000000 +0100
887 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rpc.h  2003-12-10 23:14:10.155410840 +0100
888 @@ -0,0 +1,68 @@
889 +/* RPC extension for IP connection tracking, Version 2.2
890 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
891 + *     - original rpc tracking module
892 + *     - "recent" connection handling for kernel 2.3+ netfilter
893 + *
894 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
895 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
896 + *
897 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
898 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
899 + *     - extended matching to support filtering on procedures
900 + *
901 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
902 + *
903 + *     This program is free software; you can redistribute it and/or
904 + *     modify it under the terms of the GNU General Public License
905 + *     as published by the Free Software Foundation; either version
906 + *     2 of the License, or (at your option) any later version.
907 + **
908 + */
909 +
910 +#include <asm/param.h>
911 +#include <linux/sched.h>
912 +#include <linux/timer.h>
913 +#include <linux/stddef.h>
914 +#include <linux/list.h>
915 +
916 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
917 +
918 +#ifndef _IP_CONNTRACK_RPC_H
919 +#define _IP_CONNTRACK_RPC_H
920 +
921 +#define RPC_PORT       111
922 +
923 +
924 +/* Datum in RPC packets are encoded in XDR */
925 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
926 +
927 +/* Fast timeout, to deny DoS atacks */
928 +#define EXP (60 * HZ)
929 +
930 +/* Normal timeouts */
931 +#define EXPIRES (180 * HZ)
932 +
933 +/* For future conections RPC, using client's cache bindings
934 + * I'll use ip_conntrack_lock to lock these lists      */
935 +
936 +/* This identifies each request and stores protocol */
937 +struct request_p {
938 +       struct list_head list;
939 +
940 +       u_int32_t xid;   
941 +       u_int32_t ip;
942 +       u_int16_t port;
943 +       
944 +       /* Protocol */
945 +       u_int16_t proto;
946 +
947 +       struct timer_list timeout;
948 +};
949 +
950 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
951 +                               u_int32_t ip, u_int32_t port) {
952 +       return (p->xid == xid && p->ip == ip && p->port);
953 +
954 +}
955 +
956 +#endif /* _IP_CONNTRACK_RPC_H */
957 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
958 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h      1970-01-01 01:00:00.000000000 +0100
959 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rsh.h  2003-12-10 23:14:11.556197888 +0100
960 @@ -0,0 +1,35 @@
961 +/* RSH extension for IP connection tracking, Version 1.0
962 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
963 + * based on HW's ip_conntrack_irc.c     
964 + *
965 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
966 + *
967 + *      This program is free software; you can redistribute it and/or
968 + *      modify it under the terms of the GNU General Public License
969 + *      as published by the Free Software Foundation; either version
970 + *      2 of the License, or (at your option) any later version.
971 + */
972 +#ifndef _IP_CONNTRACK_RSH_H
973 +#define _IP_CONNTRACK_RSH_H
974 +
975 +#ifdef __KERNEL__
976 +#include <linux/netfilter_ipv4/lockhelp.h>
977 +
978 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
979 +#endif
980 +
981 +
982 +#define RSH_PORT       514
983 +
984 +/* This structure is per expected connection */
985 +struct ip_ct_rsh_expect
986 +{
987 +       u_int16_t port;
988 +};
989 +
990 +/* This structure exists only once per master */
991 +struct ip_ct_rsh_master {
992 +};
993 +
994 +#endif /* _IP_CONNTRACK_RSH_H */
995 +
996 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
997 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h     1970-01-01 01:00:00.000000000 +0100
998 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2003-12-10 23:14:12.890994968 +0100
999 @@ -0,0 +1,68 @@
1000 +/*
1001 + * RTSP extension for IP connection tracking.
1002 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
1003 + * based on ip_conntrack_irc.h
1004 + *
1005 + *      This program is free software; you can redistribute it and/or
1006 + *      modify it under the terms of the GNU General Public License
1007 + *      as published by the Free Software Foundation; either version
1008 + *      2 of the License, or (at your option) any later version.
1009 + */
1010 +#ifndef _IP_CONNTRACK_RTSP_H
1011 +#define _IP_CONNTRACK_RTSP_H
1012 +
1013 +/* #define IP_NF_RTSP_DEBUG */
1014 +#define IP_NF_RTSP_VERSION "0.01"
1015 +
1016 +/* port block types */
1017 +typedef enum {
1018 +    pb_single,  /* client_port=x */
1019 +    pb_range,   /* client_port=x-y */
1020 +    pb_discon   /* client_port=x/y (rtspbis) */
1021 +} portblock_t;
1022 +
1023 +/* We record seq number and length of rtsp headers here, all in host order. */
1024 +
1025 +/*
1026 + * This structure is per expected connection.  It is a member of struct
1027 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
1028 + * there and we are expected to only store the length of the data which
1029 + * needs replaced.  If a packet contains multiple RTSP messages, we create
1030 + * one expected connection per message.
1031 + *
1032 + * We use these variables to mark the entire header block.  This may seem
1033 + * like overkill, but the nature of RTSP requires it.  A header may appear
1034 + * multiple times in a message.  We must treat two Transport headers the
1035 + * same as one Transport header with two entries.
1036 + */
1037 +struct ip_ct_rtsp_expect
1038 +{
1039 +    u_int32_t   len;        /* length of header block */
1040 +    portblock_t pbtype;     /* Type of port block that was requested */
1041 +    u_int16_t   loport;     /* Port that was requested, low or first */
1042 +    u_int16_t   hiport;     /* Port that was requested, high or second */
1043 +#if 0
1044 +    uint        method;     /* RTSP method */
1045 +    uint        cseq;       /* CSeq from request */
1046 +#endif
1047 +};
1048 +
1049 +/* This structure exists only once per master */
1050 +struct ip_ct_rtsp_master
1051 +{
1052 +    /* Empty (?) */
1053 +};
1054 +
1055 +
1056 +#ifdef __KERNEL__
1057 +
1058 +#include <linux/netfilter_ipv4/lockhelp.h>
1059 +
1060 +#define RTSP_PORT   554
1061 +
1062 +/* Protects rtsp part of conntracks */
1063 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
1064 +
1065 +#endif /* __KERNEL__ */
1066 +
1067 +#endif /* _IP_CONNTRACK_RTSP_H */
1068 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_talk.h
1069 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h     1970-01-01 01:00:00.000000000 +0100
1070 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2003-12-10 23:14:15.479601440 +0100
1071 @@ -0,0 +1,152 @@
1072 +#ifndef _IP_CONNTRACK_TALK_H
1073 +#define _IP_CONNTRACK_TALK_H
1074 +/* TALK tracking. */
1075 +
1076 +#ifdef __KERNEL__
1077 +#include <linux/in.h>
1078 +#include <linux/netfilter_ipv4/lockhelp.h>
1079 +
1080 +/* Protects talk part of conntracks */
1081 +DECLARE_LOCK_EXTERN(ip_talk_lock);
1082 +#endif
1083 +
1084 +
1085 +#define TALK_PORT      517
1086 +#define NTALK_PORT     518
1087 +
1088 +/* talk structures and constants from <protocols/talkd.h> */
1089 +
1090 +/*
1091 + * 4.3BSD struct sockaddr
1092 + */
1093 +struct talk_addr {
1094 +       u_int16_t ta_family;
1095 +       u_int16_t ta_port;
1096 +       u_int32_t ta_addr;
1097 +       u_int32_t ta_junk1;
1098 +       u_int32_t ta_junk2;
1099 +};
1100 +
1101 +#define        TALK_OLD_NSIZE  9
1102 +#define        TALK_NSIZE      12
1103 +#define        TALK_TTY_NSIZE  16
1104 +
1105 +/*
1106 + * Client->server request message formats.
1107 + */
1108 +struct talk_msg {
1109 +       u_char  type;           /* request type, see below */
1110 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
1111 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
1112 +       u_char  pad;
1113 +       u_int32_t id_num;       /* message id */
1114 +       int32_t pid;            /* caller's process id */
1115 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1116 +       struct  talk_addr addr;         /* old (4.3) style */
1117 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
1118 +};
1119 +
1120 +struct ntalk_msg {
1121 +       u_char  vers;           /* protocol version */
1122 +       u_char  type;           /* request type, see below */
1123 +       u_char  answer;         /* not used */
1124 +       u_char  pad;
1125 +       u_int32_t id_num;       /* message id */
1126 +       struct  talk_addr addr;         /* old (4.3) style */
1127 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
1128 +       int32_t pid;            /* caller's process id */
1129 +       char    l_name[TALK_NSIZE];/* caller's name */
1130 +       char    r_name[TALK_NSIZE];/* callee's name */
1131 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1132 +};
1133 +
1134 +struct ntalk2_msg {
1135 +       u_char  vers;           /* talk protocol version    */
1136 +       u_char  type;           /* request type             */
1137 +       u_char  answer;         /*  */
1138 +       u_char  extended;       /* !0 if additional parts   */
1139 +       u_int32_t id_num;       /* message id number (dels) */
1140 +       struct  talk_addr addr;         /* target address   */
1141 +       struct  talk_addr ctl_addr;     /* reply to address */
1142 +       int32_t pid;            /* caller's process id */
1143 +       char    l_name[TALK_NSIZE];  /* caller's name */
1144 +       char    r_name[TALK_NSIZE];  /* callee's name */
1145 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
1146 +};
1147 +
1148 +/*
1149 + * Server->client response message formats.
1150 + */
1151 +struct talk_response {
1152 +       u_char  type;           /* type of request message, see below */
1153 +       u_char  answer;         /* response to request message, see below */
1154 +       u_char  pad[2];
1155 +       u_int32_t id_num;       /* message id */
1156 +       struct  talk_addr addr; /* address for establishing conversation */
1157 +};
1158 +
1159 +struct ntalk_response {
1160 +       u_char  vers;           /* protocol version */
1161 +       u_char  type;           /* type of request message, see below */
1162 +       u_char  answer;         /* response to request message, see below */
1163 +       u_char  pad;
1164 +       u_int32_t id_num;       /* message id */
1165 +       struct  talk_addr addr; /* address for establishing conversation */
1166 +};
1167 +
1168 +struct ntalk2_response {
1169 +       u_char  vers;           /* protocol version         */
1170 +       u_char  type;           /* type of request message  */
1171 +       u_char  answer;         /* response to request      */
1172 +       u_char  rvers;          /* Version of answering vers*/
1173 +       u_int32_t id_num;       /* message id number        */
1174 +       struct  talk_addr addr; /* address for connection   */
1175 +       /* This is at the end to compatiblize this with NTALK version.   */
1176 +       char    r_name[TALK_NSIZE]; /* callee's name            */
1177 +};
1178 +
1179 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
1180 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
1181 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
1182 +
1183 +#define        TALK_VERSION    0               /* protocol versions */
1184 +#define        NTALK_VERSION   1
1185 +#define        NTALK2_VERSION  2
1186 +
1187 +/* message type values */
1188 +#define LEAVE_INVITE   0       /* leave invitation with server */
1189 +#define LOOK_UP                1       /* check for invitation by callee */
1190 +#define DELETE         2       /* delete invitation by caller */
1191 +#define ANNOUNCE       3       /* announce invitation by caller */
1192 +/* NTALK2 */
1193 +#define REPLY_QUERY    4       /* request reply data from local daemon */
1194 +
1195 +/* answer values */
1196 +#define SUCCESS                0       /* operation completed properly */
1197 +#define NOT_HERE       1       /* callee not logged in */
1198 +#define FAILED         2       /* operation failed for unexplained reason */
1199 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
1200 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
1201 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
1202 +#define        BADVERSION      6       /* request has invalid protocol version */
1203 +#define        BADADDR         7       /* request has invalid addr value */
1204 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
1205 +/* NTALK2 */
1206 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
1207 +#define TRY_HERE       10      /* Not on this machine, try this      */
1208 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
1209 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
1210 +
1211 +/* We don't really need much for talk */
1212 +struct ip_ct_talk_expect
1213 +{
1214 +       /* Port that was to be used */
1215 +       u_int16_t port;
1216 +};
1217 +
1218 +/* This structure exists only once per master */
1219 +struct ip_ct_talk_master
1220 +{
1221 +};
1222 +
1223 +#endif /* _IP_CONNTRACK_TALK_H */
1224 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
1225 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h    2003-11-26 21:44:58.000000000 +0100
1226 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h        2003-12-10 23:13:04.122449376 +0100
1227 @@ -14,7 +14,7 @@
1228  union ip_conntrack_manip_proto
1229  {
1230         /* Add other protocols here. */
1231 -       u_int16_t all;
1232 +       u_int32_t all;
1233  
1234         struct {
1235                 u_int16_t port;
1236 @@ -25,6 +25,9 @@
1237         struct {
1238                 u_int16_t id;
1239         } icmp;
1240 +       struct {
1241 +               u_int32_t key;
1242 +       } gre;
1243  };
1244  
1245  /* The manipulable part of the tuple. */
1246 @@ -44,7 +47,7 @@
1247                 u_int32_t ip;
1248                 union {
1249                         /* Add other protocols here. */
1250 -                       u_int16_t all;
1251 +                       u_int64_t all;
1252  
1253                         struct {
1254                                 u_int16_t port;
1255 @@ -55,6 +58,11 @@
1256                         struct {
1257                                 u_int8_t type, code;
1258                         } icmp;
1259 +                       struct {
1260 +                               u_int16_t protocol;
1261 +                               u_int8_t version;
1262 +                               u_int32_t key;
1263 +                       } gre;
1264                 } u;
1265  
1266                 /* The protocol. */
1267 @@ -80,10 +88,16 @@
1268  #ifdef __KERNEL__
1269  
1270  #define DUMP_TUPLE(tp)                                         \
1271 -DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n",    \
1272 +DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",      \
1273         (tp), (tp)->dst.protonum,                               \
1274 -       NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all),          \
1275 -       NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
1276 +       NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all),          \
1277 +       NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all))
1278 +
1279 +#define DUMP_TUPLE_RAW(x)                                              \
1280 +       DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\
1281 +       (x), (x)->dst.protonum,                                         \
1282 +       NIPQUAD((x)->src.ip), ntohl((x)->src.u.all),                    \
1283 +       NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all))
1284  
1285  #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
1286  
1287 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_nat_pptp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_nat_pptp.h
1288 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_nat_pptp.h   1970-01-01 01:00:00.000000000 +0100
1289 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_nat_pptp.h       2003-11-17 09:09:34.000000000 +0100
1290 @@ -0,0 +1,11 @@
1291 +/* PPTP constants and structs */
1292 +#ifndef _NAT_PPTP_H
1293 +#define _NAT_PPTP_H
1294 +
1295 +/* conntrack private data */
1296 +struct ip_nat_pptp {
1297 +       u_int16_t pns_call_id;          /* NAT'ed PNS call id */
1298 +       u_int16_t pac_call_id;          /* NAT'ed PAC call id */
1299 +};
1300 +
1301 +#endif /* _NAT_PPTP_H */
1302 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_pool.h
1303 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_pool.h       1970-01-01 01:00:00.000000000 +0100
1304 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_pool.h   2003-12-10 23:13:39.981997896 +0100
1305 @@ -0,0 +1,64 @@
1306 +#ifndef _IP_POOL_H
1307 +#define _IP_POOL_H
1308 +
1309 +/***************************************************************************/
1310 +/*  This program is free software; you can redistribute it and/or modify   */
1311 +/*  it under the terms of the GNU General Public License as published by   */
1312 +/*  the Free Software Foundation; either version 2 of the License, or     */
1313 +/*  (at your option) any later version.                                           */
1314 +/*                                                                        */
1315 +/*  This program is distributed in the hope that it will be useful,       */
1316 +/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
1317 +/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
1318 +/*  GNU General Public License for more details.                          */
1319 +/*                                                                        */
1320 +/*  You should have received a copy of the GNU General Public License     */
1321 +/*  along with this program; if not, write to the Free Software                   */
1322 +/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
1323 +/***************************************************************************/
1324 +
1325 +/* A sockopt of such quality has hardly ever been seen before on the open
1326 + * market!  This little beauty, hardly ever used: above 64, so it's
1327 + * traditionally used for firewalling, not touched (even once!) by the
1328 + * 2.0, 2.2 and 2.4 kernels!
1329 + *
1330 + * Comes with its own certificate of authenticity, valid anywhere in the
1331 + * Free world!
1332 + *
1333 + * Rusty, 19.4.2000
1334 + */
1335 +#define SO_IP_POOL 81
1336 +
1337 +typedef int ip_pool_t;                 /* pool index */
1338 +#define IP_POOL_NONE   ((ip_pool_t)-1)
1339 +
1340 +struct ip_pool_request {
1341 +       int op;
1342 +       ip_pool_t index;
1343 +       u_int32_t addr;
1344 +       u_int32_t addr2;
1345 +};
1346 +
1347 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
1348 +
1349 +#define IP_POOL_BAD001         0x00000010
1350 +
1351 +#define IP_POOL_FLUSH          0x00000011      /* req.index, no arguments */
1352 +#define IP_POOL_INIT           0x00000012      /* from addr to addr2 incl. */
1353 +#define IP_POOL_DESTROY                0x00000013      /* req.index, no arguments */
1354 +#define IP_POOL_ADD_ADDR       0x00000014      /* add addr to pool */
1355 +#define IP_POOL_DEL_ADDR       0x00000015      /* del addr from pool */
1356 +#define IP_POOL_HIGH_NR                0x00000016      /* result in req.index */
1357 +#define IP_POOL_LOOKUP         0x00000017      /* result in addr and addr2 */
1358 +#define IP_POOL_USAGE          0x00000018      /* result in addr */
1359 +#define IP_POOL_TEST_ADDR      0x00000019      /* result (0/1) returned */
1360 +
1361 +#ifdef __KERNEL__
1362 +
1363 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
1364 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
1365 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
1366 +
1367 +#endif
1368 +
1369 +#endif /*_IP_POOL_H*/
1370 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_queue.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_queue.h
1371 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_queue.h      2003-11-26 21:45:32.000000000 +0100
1372 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_queue.h  2003-12-10 23:14:19.439999368 +0100
1373 @@ -47,10 +47,20 @@
1374         unsigned char payload[0];       /* Optional replacement packet */
1375  } ipq_verdict_msg_t;
1376  
1377 +typedef struct ipq_vwmark_msg {
1378 +       unsigned int value;             /* Verdict to hand to netfilter */
1379 +       unsigned long id;               /* Packet ID for this verdict */
1380 +       size_t data_len;                /* Length of replacement data */
1381 +       unsigned char payload[0];       /* Optional replacement packet */
1382 +       unsigned long nfmark;           /* Mark for the Packet */
1383 +} ipq_vwmark_msg_t;
1384 +
1385 +
1386  typedef struct ipq_peer_msg {
1387         union {
1388                 ipq_verdict_msg_t verdict;
1389                 ipq_mode_msg_t mode;
1390 +                ipq_vwmark_msg_t vwmark;
1391         } msg;
1392  } ipq_peer_msg_t;
1393  
1394 @@ -67,6 +77,7 @@
1395  #define IPQM_MODE      (IPQM_BASE + 1)         /* Mode request from peer */
1396  #define IPQM_VERDICT   (IPQM_BASE + 2)         /* Verdict from peer */ 
1397  #define IPQM_PACKET    (IPQM_BASE + 3)         /* Packet from kernel */
1398 -#define IPQM_MAX       (IPQM_BASE + 4)
1399 +#define IPQM_VWMARK    (IPQM_BASE + 4)         /* Verdict and mark from peer */
1400 +#define IPQM_MAX       (IPQM_BASE + 5)
1401  
1402  #endif /*_IP_QUEUE_H*/
1403 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_tables.h
1404 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_tables.h     2003-11-26 21:44:17.000000000 +0100
1405 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_tables.h 2003-12-10 23:13:24.656327752 +0100
1406 @@ -134,6 +134,12 @@
1407         /* Back pointer */
1408         unsigned int comefrom;
1409  
1410 +       /* Name of the chain */
1411 +       char *chainname;
1412 +       
1413 +       /* Rule number in the chain. */
1414 +       u_int32_t rulenum;
1415 +
1416         /* Packet and byte counters. */
1417         struct ipt_counters counters;
1418  
1419 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_addrtype.h
1420 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_addrtype.h  1970-01-01 01:00:00.000000000 +0100
1421 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_addrtype.h      2003-12-10 23:13:51.091309024 +0100
1422 @@ -0,0 +1,11 @@
1423 +#ifndef _IPT_ADDRTYPE_H
1424 +#define _IPT_ADDRTYPE_H
1425 +
1426 +struct ipt_addrtype_info {
1427 +       u_int16_t       source;         /* source-type mask */
1428 +       u_int16_t       dest;           /* dest-type mask */
1429 +       int             invert_source;
1430 +       int             invert_dest;
1431 +};
1432 +
1433 +#endif
1434 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_condition.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_condition.h
1435 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_condition.h 1970-01-01 01:00:00.000000000 +0100
1436 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_condition.h     2003-12-10 23:13:53.355964744 +0100
1437 @@ -0,0 +1,11 @@
1438 +#ifndef __IPT_CONDITION_MATCH__
1439 +#define __IPT_CONDITION_MATCH__
1440 +
1441 +#define CONDITION_NAME_LEN  32
1442 +
1443 +struct condition_info {
1444 +       char name[CONDITION_NAME_LEN];
1445 +       int  invert;
1446 +};
1447 +
1448 +#endif
1449 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connlimit.h
1450 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
1451 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connlimit.h     2003-12-10 23:13:26.810000344 +0100
1452 @@ -0,0 +1,12 @@
1453 +#ifndef _IPT_CONNLIMIT_H
1454 +#define _IPT_CONNLIMIT_H
1455 +
1456 +struct ipt_connlimit_data;
1457 +
1458 +struct ipt_connlimit_info {
1459 +       int limit;
1460 +       int inverse;
1461 +       u_int32_t mask;
1462 +       struct ipt_connlimit_data *data;
1463 +};
1464 +#endif /* _IPT_CONNLIMIT_H */
1465 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connmark.h
1466 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connmark.h  1970-01-01 01:00:00.000000000 +0100
1467 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connmark.h      2003-12-10 23:13:54.582778240 +0100
1468 @@ -0,0 +1,9 @@
1469 +#ifndef _IPT_CONNMARK_H
1470 +#define _IPT_CONNMARK_H
1471 +
1472 +struct ipt_connmark_info {
1473 +       unsigned long mark, mask;
1474 +       u_int8_t invert;
1475 +};
1476 +
1477 +#endif /*_IPT_CONNMARK_H*/
1478 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_CONNMARK.h
1479 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h  1970-01-01 01:00:00.000000000 +0100
1480 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_CONNMARK.h      2003-12-10 23:13:54.582778240 +0100
1481 @@ -0,0 +1,15 @@
1482 +#ifndef _IPT_CONNMARK_H_target
1483 +#define _IPT_CONNMARK_H_target
1484 +
1485 +enum {
1486 +    IPT_CONNMARK_SET = 0,
1487 +    IPT_CONNMARK_SAVE,
1488 +    IPT_CONNMARK_RESTORE
1489 +};
1490 +
1491 +struct ipt_connmark_target_info {
1492 +       unsigned long mark;
1493 +       u_int8_t mode;
1494 +};
1495 +
1496 +#endif /*_IPT_CONNMARK_H_target*/
1497 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_conntrack.h
1498 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-11-26 21:45:07.000000000 +0100
1499 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_conntrack.h     2003-12-10 23:13:24.657327600 +0100
1500 @@ -10,6 +10,7 @@
1501  
1502  #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
1503  #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
1504 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
1505  
1506  /* flags, invflags: */
1507  #define IPT_CONNTRACK_STATE    0x01
1508 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_dstlimit.h
1509 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_dstlimit.h  1970-01-01 01:00:00.000000000 +0100
1510 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_dstlimit.h      2003-12-10 23:13:27.868839376 +0100
1511 @@ -0,0 +1,36 @@
1512 +#ifndef _IPT_DSTLIMIT_H
1513 +#define _IPT_DSTLIMIT_H
1514 +
1515 +/* timings are in milliseconds. */
1516 +#define IPT_DSTLIMIT_SCALE 10000
1517 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
1518 +   seconds, or one every 59 hours. */
1519 +
1520 +/* details of this structure hidden by the implementation */
1521 +struct ipt_dstlimit_htable;
1522 +
1523 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
1524 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
1525 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
1526 +
1527 +struct ipt_dstlimit_info {
1528 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
1529 +       u_int32_t avg;    /* Average secs between packets * scale */
1530 +       u_int32_t burst;  /* Period multiplier for upper limit. */
1531 +
1532 +       /* user specified */
1533 +       unsigned int size;              /* how many buckets */
1534 +       unsigned int max;               /* max number of entries */
1535 +       unsigned int gc_interval;       /* gc interval */
1536 +       unsigned int expire;            /* when do entries expire? */
1537 +       char name [IFNAMSIZ];           /* name */
1538 +
1539 +       struct ipt_dstlimit_htable *hinfo;
1540 +
1541 +       /* Used internally by the kernel */
1542 +       union {
1543 +               void *ptr;
1544 +               struct ipt_dstlimit_info *master;
1545 +       } u;
1546 +};
1547 +#endif /*_IPT_DSTLIMIT_H*/
1548 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_fuzzy.h
1549 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_fuzzy.h     1970-01-01 01:00:00.000000000 +0100
1550 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_fuzzy.h 2003-12-10 23:13:30.016512880 +0100
1551 @@ -0,0 +1,21 @@
1552 +#ifndef _IPT_FUZZY_H
1553 +#define _IPT_FUZZY_H
1554 +
1555 +#include <linux/param.h>
1556 +#include <linux/types.h>
1557 +
1558 +#define MAXFUZZYRATE 10000000
1559 +#define MINFUZZYRATE 3
1560 +
1561 +struct ipt_fuzzy_info {
1562 +       u_int32_t minimum_rate;
1563 +       u_int32_t maximum_rate;
1564 +       u_int32_t packets_total;
1565 +       u_int32_t bytes_total;
1566 +       u_int32_t previous_time;
1567 +       u_int32_t present_time;
1568 +       u_int32_t mean_rate;
1569 +       u_int8_t acceptance_rate;
1570 +};
1571 +
1572 +#endif /*_IPT_FUZZY_H*/
1573 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_IPMARK.h
1574 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_IPMARK.h    1970-01-01 01:00:00.000000000 +0100
1575 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_IPMARK.h        2003-12-10 23:13:59.369050616 +0100
1576 @@ -0,0 +1,13 @@
1577 +#ifndef _IPT_IPMARK_H_target
1578 +#define _IPT_IPMARK_H_target
1579 +
1580 +struct ipt_ipmark_target_info {
1581 +       unsigned long andmask;
1582 +       unsigned long ormask;
1583 +       unsigned int addr;
1584 +};
1585 +
1586 +#define IPT_IPMARK_SRC    0
1587 +#define IPT_IPMARK_DST    1
1588 +
1589 +#endif /*_IPT_IPMARK_H_target*/
1590 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipv4options.h
1591 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipv4options.h       1970-01-01 01:00:00.000000000 +0100
1592 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipv4options.h   2003-12-10 23:13:32.270170272 +0100
1593 @@ -0,0 +1,21 @@
1594 +#ifndef __ipt_ipv4options_h_included__
1595 +#define __ipt_ipv4options_h_included__
1596 +
1597 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
1598 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
1599 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
1600 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
1601 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
1602 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
1603 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
1604 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
1605 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1606 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
1607 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
1608 +
1609 +struct ipt_ipv4options_info {
1610 +       u_int16_t options;
1611 +};
1612 +
1613 +
1614 +#endif /* __ipt_ipv4options_h_included__ */
1615 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mark.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mark.h
1616 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mark.h      2003-11-26 21:45:46.000000000 +0100
1617 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mark.h  2003-12-10 23:14:21.806639584 +0100
1618 @@ -1,9 +1,16 @@
1619  #ifndef _IPT_MARK_H
1620  #define _IPT_MARK_H
1621  
1622 +enum {
1623 +        IPT_MARK_BIT_OP_NONE,
1624 +        IPT_MARK_BIT_OP_AND,
1625 +        IPT_MARK_BIT_OP_OR
1626 +};
1627 +
1628  struct ipt_mark_info {
1629      unsigned long mark, mask;
1630      u_int8_t invert;
1631 +    u_int8_t bit_op;
1632  };
1633  
1634  #endif /*_IPT_MARK_H*/
1635 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mport.h
1636 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mport.h     1970-01-01 01:00:00.000000000 +0100
1637 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mport.h 2003-12-10 23:13:34.440840280 +0100
1638 @@ -0,0 +1,24 @@
1639 +#ifndef _IPT_MPORT_H
1640 +#define _IPT_MPORT_H
1641 +#include <linux/netfilter_ipv4/ip_tables.h>
1642 +
1643 +#define IPT_MPORT_SOURCE (1<<0)
1644 +#define IPT_MPORT_DESTINATION (1<<1)
1645 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1646 +
1647 +#define IPT_MULTI_PORTS        15
1648 +
1649 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1650 +/* every entry in ports[] except for the last one has one bit in pflags
1651 + * associated with it. If this bit is set, the port is the first port of
1652 + * a portrange, with the next entry being the last.
1653 + * End of list is marked with pflags bit set and port=65535.
1654 + * If 14 ports are used (last one does not have a pflag), the last port
1655 + * is repeated to fill the last entry in ports[] */
1656 +struct ipt_mport
1657 +{
1658 +       u_int8_t flags:2;                       /* Type of comparison */
1659 +       u_int16_t pflags:14;                    /* Port flags */
1660 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
1661 +};
1662 +#endif /*_IPT_MPORT_H*/
1663 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_NETLINK.h
1664 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_NETLINK.h   1970-01-01 01:00:00.000000000 +0100
1665 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_NETLINK.h       2003-12-10 23:13:35.507678096 +0100
1666 @@ -0,0 +1,27 @@
1667 +#ifndef _IPT_FWMON_H
1668 +#define _IPT_FWMON_H
1669 +
1670 +/* Bitmask macros */
1671 +#define MASK(x,y) (x & y)
1672 +#define MASK_SET(x,y) x |= y
1673 +#define MASK_UNSET(x,y) x &= ~y
1674 +
1675 +#define USE_MARK       0x00000001
1676 +#define USE_DROP       0x00000002
1677 +#define USE_SIZE       0x00000004
1678 +
1679 +struct ipt_nldata
1680 +{      
1681 +       unsigned int flags;
1682 +       unsigned int mark;
1683 +       unsigned int size;
1684 +};
1685 +
1686 +/* Old header */
1687 +struct netlink_t {
1688 +       unsigned int len;
1689 +       unsigned int mark;
1690 +       char iface[IFNAMSIZ];
1691 +};
1692 +
1693 +#endif /*_IPT_FWMON_H*/
1694 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_nth.h
1695 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_nth.h       1970-01-01 01:00:00.000000000 +0100
1696 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_nth.h   2003-12-10 23:13:37.748337464 +0100
1697 @@ -0,0 +1,19 @@
1698 +#ifndef _IPT_NTH_H
1699 +#define _IPT_NTH_H
1700 +
1701 +#include <linux/param.h>
1702 +#include <linux/types.h>
1703 +
1704 +#ifndef IPT_NTH_NUM_COUNTERS
1705 +#define IPT_NTH_NUM_COUNTERS 16
1706 +#endif
1707 +
1708 +struct ipt_nth_info {
1709 +       u_int8_t every;
1710 +       u_int8_t not;
1711 +       u_int8_t startat;
1712 +       u_int8_t counter;
1713 +       u_int8_t packet;
1714 +};
1715 +
1716 +#endif /*_IPT_NTH_H*/
1717 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_osf.h
1718 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_osf.h       1970-01-01 01:00:00.000000000 +0100
1719 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_osf.h   2003-12-10 23:13:38.897162816 +0100
1720 @@ -0,0 +1,121 @@
1721 +/*
1722 + * ipt_osf.h
1723 + *
1724 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1725 + *
1726 + *
1727 + * This program is free software; you can redistribute it and/or modify
1728 + * it under the terms of the GNU General Public License as published by
1729 + * the Free Software Foundation; either version 2 of the License, or
1730 + * (at your option) any later version.
1731 + *
1732 + * This program is distributed in the hope that it will be useful,
1733 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1734 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1735 + * GNU General Public License for more details.
1736 + *
1737 + * You should have received a copy of the GNU General Public License
1738 + * along with this program; if not, write to the Free Software
1739 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1740 + */
1741 +
1742 +#ifndef _IPT_OSF_H
1743 +#define _IPT_OSF_H
1744 +
1745 +#define MAXGENRELEN            32
1746 +#define MAXDETLEN              64
1747 +
1748 +#include <linux/list.h>
1749 +
1750 +struct ipt_osf_info
1751 +{
1752 +       char                    genre[MAXGENRELEN];
1753 +       int                     len;
1754 +       int                     invert; /* UNSUPPORTED */
1755 +};
1756 +
1757 +struct osf_wc
1758 +{
1759 +       char                    wc;
1760 +       unsigned long           val;
1761 +};
1762 +
1763 +/* This struct represents IANA options
1764 + * http://www.iana.org/assignments/tcp-parameters
1765 + */
1766 +struct osf_opt
1767 +{
1768 +       unsigned char           kind;
1769 +       unsigned char           length;
1770 +       struct osf_wc           wc;
1771 +};
1772 +
1773 +#ifdef __KERNEL__
1774 +
1775 +struct osf_finger
1776 +{
1777 +       struct list_head        flist;
1778 +       struct osf_wc           wss;
1779 +       unsigned char           ttl;
1780 +       unsigned char           df;
1781 +       unsigned long           ss;
1782 +       char                    genre[MAXGENRELEN];
1783 +       char                    version[MAXGENRELEN], subtype[MAXGENRELEN];
1784 +       
1785 +       /* Not needed, but for consistency with original table from Michal Zalewski */
1786 +       char                    details[MAXDETLEN]; 
1787 +
1788 +       int                     opt_num;
1789 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1790 +
1791 +};
1792 +
1793 +/* Defines for IANA option kinds */
1794 +
1795 +#define OSFOPT_EOL             0       /* End of options */
1796 +#define OSFOPT_NOP             1       /* NOP */
1797 +#define OSFOPT_MSS             2       /* Maximum segment size */
1798 +#define OSFOPT_WSO             3       /* Window scale option */
1799 +#define OSFOPT_SACKP           4       /* SACK permitted */
1800 +#define OSFOPT_SACK            5       /* SACK */
1801 +#define OSFOPT_ECHO            6       
1802 +#define OSFOPT_ECHOREPLY       7
1803 +#define OSFOPT_TS              8       /* Timestamp option */
1804 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
1805 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
1806 +/* Others are not used in current OSF */
1807 +
1808 +static struct osf_opt IANA_opts[] = 
1809 +{
1810 +       {0, 1,},
1811 +       {1, 1,},
1812 +       {2, 4,},
1813 +       {3, 3,},
1814 +       {4, 2,},
1815 +       {5, 1 ,}, /* SACK length is not defined */
1816 +       {6, 6,},
1817 +       {7, 6,},
1818 +       {8, 10,},
1819 +       {9, 2,},
1820 +       {10, 3,},
1821 +       {11, 1,}, /* CC: Suppose 1 */
1822 +       {12, 1,}, /* the same */
1823 +       {13, 1,}, /* and here too */
1824 +       {14, 3,},
1825 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1826 +       {16, 1,},
1827 +       {17, 1,},
1828 +       {18, 3,},
1829 +       {19, 18,},
1830 +       {20, 1,},
1831 +       {21, 1,},
1832 +       {22, 1,},
1833 +       {23, 1,},
1834 +       {24, 1,},
1835 +       {25, 1,},
1836 +       {26, 1,},
1837 +};
1838 +
1839 +#endif /* __KERNEL__ */
1840 +
1841 +#endif /* _IPT_OSF_H */
1842 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_pool.h
1843 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_pool.h      1970-01-01 01:00:00.000000000 +0100
1844 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_pool.h  2003-12-10 23:13:39.981997896 +0100
1845 @@ -0,0 +1,25 @@
1846 +#ifndef _IPT_POOL_H
1847 +#define _IPT_POOL_H
1848 +
1849 +#include <linux/netfilter_ipv4/ip_pool.h>
1850 +
1851 +#define IPT_POOL_INV_SRC       0x00000001
1852 +#define IPT_POOL_INV_DST       0x00000002
1853 +#define IPT_POOL_DEL_SRC       0x00000004
1854 +#define IPT_POOL_DEL_DST       0x00000008
1855 +#define IPT_POOL_INV_MOD_SRC   0x00000010
1856 +#define IPT_POOL_INV_MOD_DST   0x00000020
1857 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
1858 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
1859 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
1860 +#define IPT_POOL_MOD_DST_DROP  0x00000200
1861 +
1862 +/* match info */
1863 +struct ipt_pool_info
1864 +{
1865 +       ip_pool_t src;
1866 +       ip_pool_t dst;
1867 +       unsigned flags;
1868 +};
1869 +
1870 +#endif /*_IPT_POOL_H*/
1871 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_psd.h
1872 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_psd.h       1970-01-01 01:00:00.000000000 +0100
1873 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_psd.h   2003-12-10 23:13:41.104827200 +0100
1874 @@ -0,0 +1,40 @@
1875 +#ifndef _IPT_PSD_H
1876 +#define _IPT_PSD_H
1877 +
1878 +#include <linux/param.h>
1879 +#include <linux/types.h>
1880 +
1881 +/*
1882 + * High port numbers have a lower weight to reduce the frequency of false
1883 + * positives, such as from passive mode FTP transfers.
1884 + */
1885 +#define PORT_WEIGHT_PRIV               3
1886 +#define PORT_WEIGHT_HIGH               1
1887 +
1888 +/*
1889 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1890 + * from the same source, with no longer than DELAY ticks between ports.
1891 + */
1892 +#define SCAN_MIN_COUNT                 7
1893 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1894 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
1895 +#define SCAN_DELAY_THRESHOLD           (HZ * 3)
1896 +
1897 +/*
1898 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1899 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1900 + * HASH_MAX source addresses per the same hash value.
1901 + */
1902 +#define LIST_SIZE                      0x100
1903 +#define HASH_LOG                       9
1904 +#define HASH_SIZE                      (1 << HASH_LOG)
1905 +#define HASH_MAX                       0x10
1906 +
1907 +struct ipt_psd_info {
1908 +       unsigned int weight_threshold;
1909 +       unsigned int delay_threshold;
1910 +       unsigned short lo_ports_weight;
1911 +       unsigned short hi_ports_weight;
1912 +};
1913 +
1914 +#endif /*_IPT_PSD_H*/
1915 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_quota.h
1916 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_quota.h     1970-01-01 01:00:00.000000000 +0100
1917 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_quota.h 2003-12-10 23:13:42.203660152 +0100
1918 @@ -0,0 +1,11 @@
1919 +#ifndef _IPT_QUOTA_H
1920 +#define _IPT_QUOTA_H
1921 +
1922 +/* print debug info in both kernel/netfilter module & iptable library */
1923 +//#define DEBUG_IPT_QUOTA
1924 +
1925 +struct ipt_quota_info {
1926 +        u_int64_t quota;
1927 +};
1928 +
1929 +#endif /*_IPT_QUOTA_H*/
1930 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_random.h
1931 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_random.h    1970-01-01 01:00:00.000000000 +0100
1932 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_random.h        2003-12-10 23:13:44.404325600 +0100
1933 @@ -0,0 +1,11 @@
1934 +#ifndef _IPT_RAND_H
1935 +#define _IPT_RAND_H
1936 +
1937 +#include <linux/param.h>
1938 +#include <linux/types.h>
1939 +
1940 +struct ipt_rand_info {
1941 +       u_int8_t average;
1942 +};
1943 +
1944 +#endif /*_IPT_RAND_H*/
1945 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_realm.h
1946 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_realm.h     1970-01-01 01:00:00.000000000 +0100
1947 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_realm.h 2003-12-10 23:13:45.528154752 +0100
1948 @@ -0,0 +1,9 @@
1949 +#ifndef _IPT_REALM_H
1950 +#define _IPT_REALM_H
1951 +
1952 +struct ipt_realm_info {
1953 +       u_int32_t id;
1954 +       u_int32_t mask;
1955 +       u_int8_t invert;
1956 +};
1957 +#endif /*_IPT_REALM_H*/
1958 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_REJECT.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_REJECT.h
1959 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_REJECT.h    2003-11-26 21:45:21.000000000 +0100
1960 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_REJECT.h        2003-12-10 23:14:20.642816512 +0100
1961 @@ -15,6 +15,7 @@
1962  
1963  struct ipt_reject_info {
1964         enum ipt_reject_with with;      /* reject type */
1965 +       u_int8_t fake_source_address;  /* 1: fake src addr with original packet dest, 0: no fake */
1966  };
1967  
1968 -#endif /*_IPT_REJECT_H*/
1969 +#endif /* _IPT_REJECT_H */
1970 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ROUTE.h
1971 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ROUTE.h     1970-01-01 01:00:00.000000000 +0100
1972 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ROUTE.h 2003-12-10 23:14:07.501814248 +0100
1973 @@ -0,0 +1,22 @@
1974 +/* Header file for iptables ipt_ROUTE target
1975 + *
1976 + * (C) 2002 by CĆ©dric de Launois <delaunois@info.ucl.ac.be>
1977 + *
1978 + * This software is distributed under GNU GPL v2, 1991
1979 + */
1980 +#ifndef _IPT_ROUTE_H_target
1981 +#define _IPT_ROUTE_H_target
1982 +
1983 +#define IPT_ROUTE_IFNAMSIZ 16
1984 +
1985 +struct ipt_route_target_info {
1986 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
1987 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
1988 +       u_int32_t gw;                           /* IP address of gateway */
1989 +       u_int8_t  flags;
1990 +};
1991 +
1992 +/* Values for "flags" field */
1993 +#define IPT_ROUTE_CONTINUE        0x01
1994 +
1995 +#endif /*_IPT_ROUTE_H_target*/
1996 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_rpc.h
1997 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_rpc.h       1970-01-01 01:00:00.000000000 +0100
1998 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_rpc.h   2003-12-10 23:14:10.155410840 +0100
1999 @@ -0,0 +1,35 @@
2000 +/* RPC extension for IP netfilter matching, Version 2.2
2001 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2002 + *     - original rpc tracking module
2003 + *     - "recent" connection handling for kernel 2.3+ netfilter
2004 + *
2005 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2006 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2007 + *
2008 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2009 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
2010 + *     - extended matching to support filtering on procedures
2011 + *
2012 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
2013 + *
2014 + *     This program is free software; you can redistribute it and/or
2015 + *     modify it under the terms of the GNU General Public License
2016 + *     as published by the Free Software Foundation; either version
2017 + *     2 of the License, or (at your option) any later version.
2018 + **
2019 + */
2020 +
2021 +#ifndef _IPT_RPC_H
2022 +#define _IPT_RPC_H
2023 +
2024 +struct ipt_rpc_data;
2025 +
2026 +struct ipt_rpc_info {
2027 +       int inverse;
2028 +       int strict;
2029 +       const char c_procs[1408];
2030 +       int i_procs;
2031 +       struct ipt_rpc_data *data;
2032 +};
2033 +
2034 +#endif /* _IPT_RPC_H */
2035 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_sctp.h
2036 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_sctp.h      1970-01-01 01:00:00.000000000 +0100
2037 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_sctp.h  2003-12-10 23:13:25.744162376 +0100
2038 @@ -0,0 +1,25 @@
2039 +/* iptables module for matching the SCTP header
2040 + *
2041 + * (C) 2003 Harald Welte <laforge@gnumonks.org>
2042 + *
2043 + * This software is distributed under GNU GPL v2, 1991
2044 + *
2045 + * $Id$
2046 + */
2047 +#ifndef _IPT_SCTP_H
2048 +#define _IPT_SCTP_H
2049 +
2050 +struct ipt_sctp_info {
2051 +       u_int16_t spts[2];                      /* Souce port range */
2052 +       u_int16_t dpts[2];                      /* Destination port range */
2053 +       u_int32_t chunks;                       /* chunks to be matched */
2054 +       u_int32_t chunk_mask;                   /* chunk mask to be matched */
2055 +       u_int8_t invflags;                      /* Inverse flags */
2056 +};
2057 +
2058 +#define IPT_SCTP_INV_SRCPT     0x01    /* Invert the sense of source ports */
2059 +#define IPT_SCTP_INV_DSTPT     0x02    /* Invert the sense of dest ports */
2060 +#define IPT_SCTP_INV_CHUNKS    0x03    /* Invert the sense of chunks */
2061 +#define IPT_SCTP_INV_MASK      0x03    /* All possible flags */
2062 +
2063 +#endif /* _IPT_SCTP_H */
2064 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_state.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_state.h
2065 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_state.h     2003-11-26 21:45:27.000000000 +0100
2066 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_state.h 2003-12-10 23:13:24.657327600 +0100
2067 @@ -4,6 +4,8 @@
2068  #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
2069  #define IPT_STATE_INVALID (1 << 0)
2070  
2071 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
2072 +
2073  struct ipt_state_info
2074  {
2075         unsigned int statemask;
2076 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_string.h
2077 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_string.h    1970-01-01 01:00:00.000000000 +0100
2078 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_string.h        2003-12-10 23:14:14.164801320 +0100
2079 @@ -0,0 +1,21 @@
2080 +#ifndef _IPT_STRING_H
2081 +#define _IPT_STRING_H
2082 +
2083 +/* *** PERFORMANCE TWEAK ***
2084 + * Packet size and search string threshold,
2085 + * above which sublinear searches is used. */
2086 +#define IPT_STRING_HAYSTACK_THRESH     100
2087 +#define IPT_STRING_NEEDLE_THRESH       20
2088 +
2089 +#define BM_MAX_NLEN 256
2090 +#define BM_MAX_HLEN 1024
2091 +
2092 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
2093 +
2094 +struct ipt_string_info {
2095 +    char string[BM_MAX_NLEN];
2096 +    u_int16_t invert;
2097 +    u_int16_t len;
2098 +};
2099 +
2100 +#endif /* _IPT_STRING_H */
2101 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TCPLAG.h
2102 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h    1970-01-01 01:00:00.000000000 +0100
2103 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TCPLAG.h        2003-12-10 23:14:16.739409920 +0100
2104 @@ -0,0 +1,10 @@
2105 +#ifndef _IPT_TCPLAG_H
2106 +#define _IPT_TCPLAG_H
2107 +
2108 +struct ipt_tcplag
2109 +{
2110 +       unsigned char level;
2111 +       unsigned char prefix[ 15 ];
2112 +};
2113 +
2114 +#endif
2115 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_time.h
2116 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_time.h      1970-01-01 01:00:00.000000000 +0100
2117 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_time.h  2003-12-10 23:13:47.814807128 +0100
2118 @@ -0,0 +1,13 @@
2119 +#ifndef __ipt_time_h_included__
2120 +#define __ipt_time_h_included__
2121 +
2122 +
2123 +struct ipt_time_info {
2124 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
2125 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
2126 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
2127 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
2128 +};
2129 +
2130 +
2131 +#endif /* __ipt_time_h_included__ */
2132 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TTL.h
2133 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TTL.h       1970-01-01 01:00:00.000000000 +0100
2134 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TTL.h   2003-12-10 23:13:48.933637040 +0100
2135 @@ -0,0 +1,21 @@
2136 +/* TTL modification module for IP tables
2137 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
2138 +
2139 +#ifndef _IPT_TTL_H
2140 +#define _IPT_TTL_H
2141 +
2142 +enum {
2143 +       IPT_TTL_SET = 0,
2144 +       IPT_TTL_INC,
2145 +       IPT_TTL_DEC
2146 +};
2147 +
2148 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
2149 +
2150 +struct ipt_TTL_info {
2151 +       u_int8_t        mode;
2152 +       u_int8_t        ttl;
2153 +};
2154 +
2155 +
2156 +#endif
2157 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_u32.h
2158 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_u32.h       1970-01-01 01:00:00.000000000 +0100
2159 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_u32.h   2003-12-10 23:13:50.005474096 +0100
2160 @@ -0,0 +1,40 @@
2161 +#ifndef _IPT_U32_H
2162 +#define _IPT_U32_H
2163 +#include <linux/netfilter_ipv4/ip_tables.h>
2164 +
2165 +enum ipt_u32_ops
2166 +{
2167 +       IPT_U32_AND,
2168 +       IPT_U32_LEFTSH,
2169 +       IPT_U32_RIGHTSH,
2170 +       IPT_U32_AT
2171 +};
2172 +
2173 +struct ipt_u32_location_element
2174 +{
2175 +       u_int32_t number;
2176 +       u_int8_t nextop;
2177 +};
2178 +struct ipt_u32_value_element
2179 +{
2180 +       u_int32_t min;
2181 +       u_int32_t max;
2182 +};
2183 +/* *** any way to allow for an arbitrary number of elements?
2184 +   for now I settle for a limit of 10 of each */
2185 +#define U32MAXSIZE 10
2186 +struct ipt_u32_test
2187 +{
2188 +       u_int8_t nnums;
2189 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
2190 +       u_int8_t nvalues;
2191 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
2192 +};
2193 +
2194 +struct ipt_u32
2195 +{
2196 +       u_int8_t ntests;
2197 +       struct ipt_u32_test tests[U32MAXSIZE+1];
2198 +};
2199 +
2200 +#endif /*_IPT_U32_H*/
2201 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ULOG.h
2202 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ULOG.h      2003-11-26 21:43:39.000000000 +0100
2203 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ULOG.h  2003-12-10 23:13:22.344679176 +0100
2204 @@ -11,6 +11,9 @@
2205  #define NETLINK_NFLOG  5
2206  #endif
2207  
2208 +#define NFLOG_DEFAULT_NLGROUP          1
2209 +#define NFLOG_DEFAULT_QTHRESHOLD       1
2210 +
2211  #define ULOG_MAC_LEN   80
2212  #define ULOG_PREFIX_LEN        32
2213  
2214 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_XOR.h
2215 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_XOR.h       1970-01-01 01:00:00.000000000 +0100
2216 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_XOR.h   2003-12-10 23:14:18.223184352 +0100
2217 @@ -0,0 +1,9 @@
2218 +#ifndef _IPT_XOR_H
2219 +#define _IPT_XOR_H
2220 +
2221 +struct ipt_XOR_info {
2222 +       char            key[30];
2223 +       u_int8_t        block_size;
2224 +};
2225 +
2226 +#endif /* _IPT_XOR_H */
2227 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h linux-2.6.0-test11/include/linux/netfilter_ipv4.h
2228 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h       2003-11-26 21:45:25.000000000 +0100
2229 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4.h   2003-12-10 23:13:24.657327600 +0100
2230 @@ -51,6 +51,8 @@
2231  
2232  enum nf_ip_hook_priorities {
2233         NF_IP_PRI_FIRST = INT_MIN,
2234 +       NF_IP_PRI_CONNTRACK_DEFRAG = -400,
2235 +       NF_IP_PRI_RAW = -300,
2236         NF_IP_PRI_CONNTRACK = -200,
2237         NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
2238         NF_IP_PRI_MANGLE = -150,
2239 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6_tables.h
2240 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6_tables.h    2003-11-26 21:45:41.000000000 +0100
2241 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6_tables.h        2003-12-10 23:13:24.657327600 +0100
2242 @@ -140,6 +140,12 @@
2243         /* Back pointer */
2244         unsigned int comefrom;
2245  
2246 +       /* Name of the chain */
2247 +       char *chainname;
2248 +       
2249 +       /* Rule number in the chain. */
2250 +       u_int32_t rulenum;
2251 +
2252         /* Packet and byte counters. */
2253         struct ip6t_counters counters;
2254  
2255 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_condition.h
2256 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_condition.h        1970-01-01 01:00:00.000000000 +0100
2257 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_condition.h    2003-12-10 23:13:52.255132096 +0100
2258 @@ -0,0 +1,11 @@
2259 +#ifndef __IP6T_CONDITION_MATCH__
2260 +#define __IP6T_CONDITION_MATCH__
2261 +
2262 +#define CONDITION6_NAME_LEN  32
2263 +
2264 +struct condition6_info {
2265 +       char name[CONDITION6_NAME_LEN];
2266 +       int  invert;
2267 +};
2268 +
2269 +#endif
2270 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_fuzzy.h
2271 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h    1970-01-01 01:00:00.000000000 +0100
2272 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_fuzzy.h        2003-12-10 23:13:28.962673088 +0100
2273 @@ -0,0 +1,21 @@
2274 +#ifndef _IP6T_FUZZY_H
2275 +#define _IP6T_FUZZY_H
2276 +
2277 +#include <linux/param.h>
2278 +#include <linux/types.h>
2279 +
2280 +#define MAXFUZZYRATE 10000000
2281 +#define MINFUZZYRATE 3
2282 +
2283 +struct ip6t_fuzzy_info {
2284 +       u_int32_t minimum_rate;
2285 +       u_int32_t maximum_rate;
2286 +       u_int32_t packets_total;
2287 +       u_int32_t bytes_total;
2288 +       u_int32_t previous_time;
2289 +       u_int32_t present_time;
2290 +       u_int32_t mean_rate;
2291 +       u_int8_t acceptance_rate;
2292 +};
2293 +
2294 +#endif /*_IP6T_FUZZY_H*/
2295 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_HL.h
2296 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_HL.h       1970-01-01 01:00:00.000000000 +0100
2297 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_HL.h   2003-12-10 23:13:31.107347048 +0100
2298 @@ -0,0 +1,22 @@
2299 +/* Hop Limit modification module for ip6tables
2300 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
2301 + * Based on HW's TTL module */
2302 +
2303 +#ifndef _IP6T_HL_H
2304 +#define _IP6T_HL_H
2305 +
2306 +enum {
2307 +       IP6T_HL_SET = 0,
2308 +       IP6T_HL_INC,
2309 +       IP6T_HL_DEC
2310 +};
2311 +
2312 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
2313 +
2314 +struct ip6t_HL_info {
2315 +       u_int8_t        mode;
2316 +       u_int8_t        hop_limit;
2317 +};
2318 +
2319 +
2320 +#endif
2321 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_nth.h
2322 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_nth.h      1970-01-01 01:00:00.000000000 +0100
2323 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_nth.h  2003-12-10 23:13:36.622508616 +0100
2324 @@ -0,0 +1,19 @@
2325 +#ifndef _IP6T_NTH_H
2326 +#define _IP6T_NTH_H
2327 +
2328 +#include <linux/param.h>
2329 +#include <linux/types.h>
2330 +
2331 +#ifndef IP6T_NTH_NUM_COUNTERS
2332 +#define IP6T_NTH_NUM_COUNTERS 16
2333 +#endif
2334 +
2335 +struct ip6t_nth_info {
2336 +       u_int8_t every;
2337 +       u_int8_t not;
2338 +       u_int8_t startat;
2339 +       u_int8_t counter;
2340 +       u_int8_t packet;
2341 +};
2342 +
2343 +#endif /*_IP6T_NTH_H*/
2344 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_owner.h
2345 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_owner.h    2003-11-26 21:44:32.000000000 +0100
2346 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_owner.h        2003-12-10 23:14:05.028190296 +0100
2347 @@ -6,12 +6,14 @@
2348  #define IP6T_OWNER_GID 0x02
2349  #define IP6T_OWNER_PID 0x04
2350  #define IP6T_OWNER_SID 0x08
2351 +#define IP6T_OWNER_COMM 0x10
2352  
2353  struct ip6t_owner_info {
2354      uid_t uid;
2355      gid_t gid;
2356      pid_t pid;
2357      pid_t sid;
2358 +    char comm[16];
2359      u_int8_t match, invert;    /* flags */
2360  };
2361  
2362 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_random.h
2363 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_random.h   1970-01-01 01:00:00.000000000 +0100
2364 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_random.h       2003-12-10 23:13:43.304492800 +0100
2365 @@ -0,0 +1,11 @@
2366 +#ifndef _IP6T_RAND_H
2367 +#define _IP6T_RAND_H
2368 +
2369 +#include <linux/param.h>
2370 +#include <linux/types.h>
2371 +
2372 +struct ip6t_rand_info {
2373 +       u_int8_t average;
2374 +};
2375 +
2376 +#endif /*_IP6T_RAND_H*/
2377 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_REJECT.h
2378 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_REJECT.h   2003-11-26 21:42:47.000000000 +0100
2379 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_REJECT.h       2003-12-10 23:13:46.679979648 +0100
2380 @@ -2,15 +2,17 @@
2381  #define _IP6T_REJECT_H
2382  
2383  enum ip6t_reject_with {
2384 -       IP6T_ICMP_NET_UNREACHABLE,
2385 -       IP6T_ICMP_HOST_UNREACHABLE,
2386 -       IP6T_ICMP_PROT_UNREACHABLE,
2387 -       IP6T_ICMP_PORT_UNREACHABLE,
2388 -       IP6T_ICMP_ECHOREPLY
2389 +       IP6T_ICMP6_NO_ROUTE,
2390 +       IP6T_ICMP6_ADM_PROHIBITED,
2391 +       IP6T_ICMP6_NOT_NEIGHBOUR,
2392 +       IP6T_ICMP6_ADDR_UNREACH,
2393 +       IP6T_ICMP6_PORT_UNREACH,
2394 +       IP6T_ICMP6_ECHOREPLY,
2395 +       IP6T_TCP_RESET
2396  };
2397  
2398  struct ip6t_reject_info {
2399         enum ip6t_reject_with with;      /* reject type */
2400  };
2401  
2402 -#endif /*_IPT_REJECT_H*/
2403 +#endif /*_IP6T_REJECT_H*/
2404 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_ROUTE.h
2405 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h    1970-01-01 01:00:00.000000000 +0100
2406 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_ROUTE.h        2003-12-10 23:14:08.745625160 +0100
2407 @@ -0,0 +1,22 @@
2408 +/* Header file for iptables ip6t_ROUTE target
2409 + *
2410 + * (C) 2003 by CĆ©dric de Launois <delaunois@info.ucl.ac.be>
2411 + *
2412 + * This software is distributed under GNU GPL v2, 1991
2413 + */
2414 +#ifndef _IPT_ROUTE_H_target
2415 +#define _IPT_ROUTE_H_target
2416 +
2417 +#define IP6T_ROUTE_IFNAMSIZ 16
2418 +
2419 +struct ip6t_route_target_info {
2420 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
2421 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
2422 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
2423 +       u_int8_t  flags;
2424 +};
2425 +
2426 +/* Values for "flags" field */
2427 +#define IP6T_ROUTE_CONTINUE        0x01
2428 +
2429 +#endif /*_IP6T_ROUTE_H_target*/
2430 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_mime.h linux-2.6.0-test11/include/linux/netfilter_mime.h
2431 --- linux-2.6.0-test11.org/include/linux/netfilter_mime.h       1970-01-01 01:00:00.000000000 +0100
2432 +++ linux-2.6.0-test11/include/linux/netfilter_mime.h   2003-12-10 23:14:12.890994968 +0100
2433 @@ -0,0 +1,89 @@
2434 +/*
2435 + * MIME functions for netfilter modules.  This file provides implementations
2436 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
2437 + * HTTP, RTSP, SIP, etc.
2438 + *
2439 + * gcc will warn for defined but unused functions, so we only include the
2440 + * functions requested.  The following macros are used:
2441 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
2442 + */
2443 +#ifndef _NETFILTER_MIME_H
2444 +#define _NETFILTER_MIME_H
2445 +
2446 +/* Only include these functions for kernel code. */
2447 +#ifdef __KERNEL__
2448 +
2449 +#include <linux/ctype.h>
2450 +
2451 +/*
2452 + * Given a buffer and length, advance to the next line and mark the current
2453 + * line.  If the current line is empty, *plinelen will be set to zero.  If
2454 + * not, it will be set to the actual line length (including CRLF).
2455 + *
2456 + * 'line' in this context means logical line (includes LWS continuations).
2457 + * Returns 1 on success, 0 on failure.
2458 + */
2459 +#ifdef NF_NEED_MIME_NEXTLINE
2460 +static int
2461 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2462 +{
2463 +    uint    off = *poff;
2464 +    uint    physlen = 0;
2465 +    int     is_first_line = 1;
2466 +
2467 +    if (off >= len)
2468 +    {
2469 +        return 0;
2470 +    }
2471 +
2472 +    do
2473 +    {
2474 +        while (p[off] != '\n')
2475 +        {
2476 +            if (len-off <= 1)
2477 +            {
2478 +                return 0;
2479 +            }
2480 +
2481 +            physlen++;
2482 +            off++;
2483 +        }
2484 +
2485 +        /* if we saw a crlf, physlen needs adjusted */
2486 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2487 +        {
2488 +            physlen--;
2489 +        }
2490 +
2491 +        /* advance past the newline */
2492 +        off++;
2493 +
2494 +        /* check for an empty line */
2495 +        if (physlen == 0)
2496 +        {
2497 +            break;
2498 +        }
2499 +
2500 +        /* check for colon on the first physical line */
2501 +        if (is_first_line)
2502 +        {
2503 +            is_first_line = 0;
2504 +            if (memchr(p+(*poff), ':', physlen) == NULL)
2505 +            {
2506 +                return 0;
2507 +            }
2508 +        }
2509 +    }
2510 +    while (p[off] == ' ' || p[off] == '\t');
2511 +
2512 +    *plineoff = *poff;
2513 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
2514 +    *poff = off;
2515 +
2516 +    return 1;
2517 +}
2518 +#endif /* NF_NEED_MIME_NEXTLINE */
2519 +
2520 +#endif /* __KERNEL__ */
2521 +
2522 +#endif /* _NETFILTER_MIME_H */
2523 diff -Nur linux-2.6.0-test11.org/net/core/netfilter.c linux-2.6.0-test11/net/core/netfilter.c
2524 --- linux-2.6.0-test11.org/net/core/netfilter.c 2003-11-26 21:43:56.000000000 +0100
2525 +++ linux-2.6.0-test11/net/core/netfilter.c     2003-12-10 23:14:03.998346856 +0100
2526 @@ -8,8 +8,10 @@
2527   *
2528   * February 2000: Modified by James Morris to have 1 queue per protocol.
2529   * 15-Mar-2000:   Added NF_REPEAT --RR.
2530 + * 08-May-2003:          Internal logging interface added by Jozsef Kadlecsik.
2531   */
2532  #include <linux/config.h>
2533 +#include <linux/kernel.h>
2534  #include <linux/netfilter.h>
2535  #include <net/protocol.h>
2536  #include <linux/init.h>
2537 @@ -61,6 +63,10 @@
2538  } queue_handler[NPROTO];
2539  static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
2540  
2541 +/**
2542 + * nf_register_hook - Register with a netfilter hook
2543 + * @reg: Hook operations to be registered
2544 + */
2545  int nf_register_hook(struct nf_hook_ops *reg)
2546  {
2547         struct list_head *i;
2548 @@ -77,6 +83,10 @@
2549         return 0;
2550  }
2551  
2552 +/**
2553 + * nf_unregister_hook - Unregister from a netfilter hook
2554 + * @reg: hook operations to be unregistered
2555 + */
2556  void nf_unregister_hook(struct nf_hook_ops *reg)
2557  {
2558         spin_lock_bh(&nf_hook_lock);
2559 @@ -389,6 +399,18 @@
2560         return NF_ACCEPT;
2561  }
2562  
2563 +/**
2564 + * nf_register_queue_handler - Registere a queue handler with netfilter
2565 + * @pf: protocol family
2566 + * @outfn: function called by core to enqueue a packet
2567 + * @data: opaque parameter, passed through
2568 + *
2569 + * This function registers a queue handler with netfilter.  There can only
2570 + * be one queue handler for every protocol family.
2571 + *
2572 + * A queue handler _must_ reinject every packet via nf_reinject, no
2573 + * matter what.
2574 + */
2575  int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
2576  {      
2577         int ret;
2578 @@ -406,7 +428,12 @@
2579         return ret;
2580  }
2581  
2582 -/* The caller must flush their queue before this */
2583 +/**
2584 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
2585 + * @pf: protocol family
2586 + *
2587 + * The caller must flush their queue before unregistering
2588 + */
2589  int nf_unregister_queue_handler(int pf)
2590  {
2591         write_lock_bh(&queue_handler_lock);
2592 @@ -549,6 +576,15 @@
2593         return ret;
2594  }
2595  
2596 +/**
2597 + * nf_reinject - Reinject a packet from a queue handler
2598 + * @skb: the packet to be reinjected
2599 + * @info: info which was passed to the outfn() of the queue handler
2600 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
2601 + *
2602 + * This is the function called by a queue handler to reinject a
2603 + * packet.
2604 + */
2605  void nf_reinject(struct sk_buff *skb, struct nf_info *info,
2606                  unsigned int verdict)
2607  {
2608 @@ -743,7 +779,70 @@
2609  EXPORT_SYMBOL(skb_ip_make_writable);
2610  #endif /*CONFIG_INET*/
2611  
2612 +/* Internal logging interface, which relies on the real 
2613 +   LOG target modules */
2614 +
2615 +#define NF_LOG_PREFIXLEN               128
2616 +
2617 +static nf_logfn *nf_logging[NPROTO]; /* = NULL */
2618 +static int reported = 0;
2619 +static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
2620 +
2621 +int nf_log_register(int pf, nf_logfn *logfn)
2622 +{
2623 +       int ret = -EBUSY;
2624 +
2625 +       /* Any setup of logging members must be done before
2626 +        * substituting pointer. */
2627 +       smp_wmb();
2628 +       spin_lock(&nf_log_lock);
2629 +       if (!nf_logging[pf]) {
2630 +               nf_logging[pf] = logfn;
2631 +               ret = 0;
2632 +       }
2633 +       spin_unlock(&nf_log_lock);
2634 +       return ret;
2635 +}              
2636  
2637 +void nf_log_unregister(int pf, nf_logfn *logfn)
2638 +{
2639 +       spin_lock(&nf_log_lock);
2640 +       if (nf_logging[pf] == logfn)
2641 +               nf_logging[pf] = NULL;
2642 +       spin_unlock(&nf_log_lock);
2643 +
2644 +       /* Give time to concurrent readers. */
2645 +       synchronize_net();
2646 +}              
2647 +
2648 +void nf_log_packet(int pf,
2649 +                  unsigned int hooknum,
2650 +                  const struct sk_buff *skb,
2651 +                  const struct net_device *in,
2652 +                  const struct net_device *out,
2653 +                  const char *fmt, ...)
2654 +{
2655 +       va_list args;
2656 +       char prefix[NF_LOG_PREFIXLEN];
2657 +       nf_logfn *logfn;
2658 +       
2659 +       rcu_read_lock();
2660 +       logfn = nf_logging[pf];
2661 +       if (logfn) {
2662 +               va_start(args, fmt);
2663 +               vsnprintf(prefix, sizeof(prefix), fmt, args);
2664 +               va_end(args);
2665 +               /* We must read logging before nf_logfn[pf] */
2666 +               smp_read_barrier_depends();
2667 +               logfn(hooknum, skb, in, out, prefix);
2668 +       } else if (!reported) {
2669 +               printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
2670 +                      "no backend logging module loaded in!\n");
2671 +               reported++;
2672 +       }
2673 +       rcu_read_unlock();
2674 +}
2675
2676  /* This does not belong here, but ipt_REJECT needs it if connection
2677     tracking in use: without this, connection may not be in hash table,
2678     and hence manufactured ICMP or RST packets will not be associated
2679 @@ -763,6 +862,9 @@
2680  EXPORT_SYMBOL(ip_ct_attach);
2681  EXPORT_SYMBOL(ip_route_me_harder);
2682  EXPORT_SYMBOL(nf_getsockopt);
2683 +EXPORT_SYMBOL(nf_log_register);
2684 +EXPORT_SYMBOL(nf_log_unregister);
2685 +EXPORT_SYMBOL(nf_log_packet);
2686  EXPORT_SYMBOL(nf_hook_slow);
2687  EXPORT_SYMBOL(nf_hooks);
2688  EXPORT_SYMBOL(nf_register_hook);
2689 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_core.c
2690 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_core.c       2003-11-26 21:42:40.000000000 +0100
2691 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_core.c   2003-12-10 23:14:22.975461896 +0100
2692 @@ -4,6 +4,7 @@
2693  
2694  /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
2695   * Public Licence. 
2696 + * (C) 2000-2003 by the netfilter core team <coreteam@netfilter.org>
2697   *
2698   * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
2699   *     - new API and handling of conntrack/nat helpers
2700 @@ -11,6 +12,8 @@
2701   * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
2702   *     - add usage/reference counts to ip_conntrack_expect
2703   *     - export ip_conntrack[_expect]_{find_get,put} functions
2704 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
2705 + *     - added DocBook-style comments for public API
2706   * */
2707  
2708  #include <linux/config.h>
2709 @@ -29,8 +32,7 @@
2710  #include <linux/slab.h>
2711  #include <linux/random.h>
2712  #include <linux/jhash.h>
2713 -/* For ERR_PTR().  Yeah, I know... --RR */
2714 -#include <linux/fs.h>
2715 +#include <linux/err.h>
2716  
2717  /* This rwlock protects the main hash table, protocol/helper/expected
2718     registrations, conntrack timers*/
2719 @@ -63,6 +65,7 @@
2720  static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
2721  struct list_head *ip_conntrack_hash;
2722  static kmem_cache_t *ip_conntrack_cachep;
2723 +struct ip_conntrack ip_conntrack_untracked;
2724  
2725  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
2726  
2727 @@ -85,6 +88,10 @@
2728         return p;
2729  }
2730  
2731 +/**
2732 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
2733 + * @protocol: protocol number
2734 + */
2735  struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
2736  {
2737         struct ip_conntrack_protocol *p;
2738 @@ -150,6 +157,8 @@
2739         inverse->dst.ip = orig->src.ip;
2740         inverse->dst.protonum = orig->dst.protonum;
2741  
2742 +       inverse->src.u.all = inverse->dst.u.all = 0;
2743 +
2744         return protocol->invert_tuple(inverse, orig);
2745  }
2746  
2747 @@ -342,7 +351,7 @@
2748         atomic_dec(&ip_conntrack_count);
2749  }
2750  
2751 -static void death_by_timeout(unsigned long ul_conntrack)
2752 +void ip_ct_death_by_timeout(unsigned long ul_conntrack)
2753  {
2754         struct ip_conntrack *ct = (void *)ul_conntrack;
2755  
2756 @@ -377,7 +386,14 @@
2757         return h;
2758  }
2759  
2760 -/* Find a connection corresponding to a tuple. */
2761 +/**
2762 + * ip_conntrack_find_get - find conntrack according to tuple
2763 + * @tuple: conntrack tuple for which we search conntrack
2764 + * @ignored_conntrack: ignore this conntrack during search
2765 + *
2766 + * This function increments the reference count of the found
2767 + * conntrack (if any).
2768 + */
2769  struct ip_conntrack_tuple_hash *
2770  ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
2771                       const struct ip_conntrack *ignored_conntrack)
2772 @@ -405,7 +421,14 @@
2773         return ct;
2774  }
2775  
2776 -/* Return conntrack and conntrack_info given skb->nfct->master */
2777 +/**
2778 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
2779 + * @skb: skb for which we want to find conntrack and conntrack_info
2780 + * @ctinfo: pointer to ctinfo, used as return value
2781 + *
2782 + * This function resolves the respective conntrack and conntrack_info
2783 + * structures for the connection this packet (skb) is part of.
2784 + */
2785  struct ip_conntrack *
2786  ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
2787  {
2788 @@ -475,8 +498,14 @@
2789         return NF_DROP;
2790  }
2791  
2792 -/* Returns true if a connection correspondings to the tuple (required
2793 -   for NAT). */
2794 +/**
2795 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
2796 + * @tuple: tuple to be used for this test
2797 + * @ignored_conntrack: conntrack which is excluded from result
2798 + *
2799 + * This function is called by the NAT code in order to find out if
2800 + * a particular tuple is already in use by some connection.
2801 + */
2802  int
2803  ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
2804                          const struct ip_conntrack *ignored_conntrack)
2805 @@ -590,7 +619,7 @@
2806                 return dropped;
2807  
2808         if (del_timer(&h->ctrack->timeout)) {
2809 -               death_by_timeout((unsigned long)h->ctrack);
2810 +               ip_ct_death_by_timeout((unsigned long)h->ctrack);
2811                 dropped = 1;
2812         }
2813         ip_conntrack_put(h->ctrack);
2814 @@ -602,7 +631,13 @@
2815  {
2816         return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
2817  }
2818 -
2819 +/**
2820 + * ip_ct_find_helper - Find application helper according to tuple
2821 + * @tuple: tuple for which helper needs to be found
2822 + *
2823 + * This function is used to determine if any registered conntrack helper
2824 + * is to be used for the given tuple.
2825 + */
2826  struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
2827  {
2828         return LIST_FIND(&helpers, helper_cmp,
2829 @@ -676,7 +711,7 @@
2830         /* Don't set timer yet: wait for confirmation */
2831         init_timer(&conntrack->timeout);
2832         conntrack->timeout.data = (unsigned long)conntrack;
2833 -       conntrack->timeout.function = death_by_timeout;
2834 +       conntrack->timeout.function = ip_ct_death_by_timeout;
2835  
2836         INIT_LIST_HEAD(&conntrack->sibling_list);
2837  
2838 @@ -713,6 +748,9 @@
2839                 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
2840                 conntrack->master = expected;
2841                 expected->sibling = conntrack;
2842 +#if CONFIG_IP_NF_CONNTRACK_MARK
2843 +               conntrack->mark = expected->expectant->mark;
2844 +#endif
2845                 LIST_DELETE(&ip_conntrack_expect_list, expected);
2846                 expected->expectant->expecting--;
2847                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
2848 @@ -790,6 +828,15 @@
2849         int set_reply;
2850         int ret;
2851  
2852 +       /* Never happen */
2853 +       if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
2854 +               if (net_ratelimit()) {
2855 +               printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
2856 +                      (*pskb)->nh.iph->protocol, hooknum);
2857 +               }
2858 +               return NF_DROP;
2859 +       }
2860 +
2861         /* FIXME: Do this right please. --RR */
2862         (*pskb)->nfcache |= NFC_UNKNOWN;
2863  
2864 @@ -808,18 +855,10 @@
2865         }
2866  #endif
2867  
2868 -       /* Previously seen (loopback)?  Ignore.  Do this before
2869 -           fragment check. */
2870 +       /* Previously seen (loopback or untracked)?  Ignore. */
2871         if ((*pskb)->nfct)
2872                 return NF_ACCEPT;
2873  
2874 -       /* Gather fragments. */
2875 -       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
2876 -               *pskb = ip_ct_gather_frags(*pskb);
2877 -               if (!*pskb)
2878 -                       return NF_STOLEN;
2879 -       }
2880 -
2881         proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
2882  
2883         /* It may be an icmp error... */
2884 @@ -896,6 +935,14 @@
2885         return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
2886  }
2887  
2888 +/**
2889 + * ip_conntrack_unexpect_related - Unexpect a related connection
2890 + * @expect: expecattin to be removed
2891 + *
2892 + * This function removes an existing expectation, that has not yet been
2893 + * confirmed (i.e. expectation was issued, but expected connection didn't
2894 + * arrive yet)
2895 + */
2896  inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
2897  {
2898         WRITE_LOCK(&ip_conntrack_lock);
2899 @@ -913,7 +960,20 @@
2900         WRITE_UNLOCK(&ip_conntrack_lock);
2901  }
2902  
2903 -/* Add a related connection. */
2904 +/**
2905 + * ip_conntrack_expect_related - Expect a related connection
2906 + * @related_to: master conntrack
2907 + * @expect: expectation with all values filled in
2908 + *
2909 + * This function is called by conntrack application helpers who
2910 + * have detected that the control (master) connection is just about
2911 + * to negotiate a related slave connection. 
2912 + *
2913 + * Note: This function allocates it's own struct ip_conntrack_expect,
2914 + * copying the values from the 'expect' parameter.  Thus, 'expect' can
2915 + * be allocated on the stack and does not need to be valid after this
2916 + * function returns.
2917 + */
2918  int ip_conntrack_expect_related(struct ip_conntrack *related_to,
2919                                 struct ip_conntrack_expect *expect)
2920  {
2921 @@ -925,8 +985,8 @@
2922          * so there is no need to use the tuple lock too */
2923  
2924         DEBUGP("ip_conntrack_expect_related %p\n", related_to);
2925 -       DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
2926 -       DEBUGP("mask:  "); DUMP_TUPLE(&expect->mask);
2927 +       DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
2928 +       DEBUGP("mask:  "); DUMP_TUPLE_RAW(&expect->mask);
2929  
2930         old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
2931                         struct ip_conntrack_expect *, &expect->tuple, 
2932 @@ -953,7 +1013,6 @@
2933                 }
2934         } else if (related_to->helper->max_expected && 
2935                    related_to->expecting >= related_to->helper->max_expected) {
2936 -               struct list_head *cur_item;
2937                 /* old == NULL */
2938                 if (!(related_to->helper->flags & 
2939                       IP_CT_HELPER_F_REUSE_EXPECT)) {
2940 @@ -978,21 +1037,14 @@
2941                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
2942   
2943                 /* choose the the oldest expectation to evict */
2944 -               list_for_each(cur_item, &related_to->sibling_list) { 
2945 -                       struct ip_conntrack_expect *cur;
2946 -
2947 -                       cur = list_entry(cur_item, 
2948 -                                        struct ip_conntrack_expect,
2949 -                                        expected_list);
2950 -                       if (cur->sibling == NULL) {
2951 -                               old = cur;
2952 +               list_for_each_entry(old, &related_to->sibling_list, 
2953 +                                                     expected_list)
2954 +                       if (old->sibling == NULL)
2955                                 break;
2956 -                       }
2957 -               }
2958  
2959 -               /* (!old) cannot happen, since related_to->expecting is the
2960 -                * number of unconfirmed expects */
2961 -               IP_NF_ASSERT(old);
2962 +               /* We cannot fail since related_to->expecting is the number
2963 +                * of unconfirmed expectations */
2964 +               IP_NF_ASSERT(old && old->sibling == NULL);
2965  
2966                 /* newnat14 does not reuse the real allocated memory
2967                  * structures but rather unexpects the old and
2968 @@ -1024,7 +1076,7 @@
2969         atomic_set(&new->use, 1);
2970         
2971         /* add to expected list for this connection */  
2972 -       list_add(&new->expected_list, &related_to->sibling_list);
2973 +       list_add_tail(&new->expected_list, &related_to->sibling_list);
2974         /* add to global list of expectations */
2975         list_prepend(&ip_conntrack_expect_list, &new->list);
2976         /* add and start timer if required */
2977 @@ -1043,7 +1095,15 @@
2978         return ret;
2979  }
2980  
2981 -/* Change tuple in an existing expectation */
2982 +/**
2983 + * ip_conntrack_change_expect - Change tuple in existing expectation
2984 + * @expect: expectation which is to be changed
2985 + * @newtuple: new tuple for expect
2986 + *
2987 + * This function is mostly called by NAT application helpers, who want to
2988 + * change an expectation issued by their respective conntrack application
2989 + * helper counterpart.
2990 + */
2991  int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
2992                                struct ip_conntrack_tuple *newtuple)
2993  {
2994 @@ -1051,15 +1111,14 @@
2995  
2996         MUST_BE_READ_LOCKED(&ip_conntrack_lock);
2997         WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
2998 -
2999         DEBUGP("change_expect:\n");
3000 -       DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
3001 -       DEBUGP("exp mask:  "); DUMP_TUPLE(&expect->mask);
3002 -       DEBUGP("newtuple:  "); DUMP_TUPLE(newtuple);
3003 +       DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
3004 +       DEBUGP("exp mask:  "); DUMP_TUPLE_RAW(&expect->mask);
3005 +       DEBUGP("newtuple:  "); DUMP_TUPLE_RAW(newtuple);
3006         if (expect->ct_tuple.dst.protonum == 0) {
3007                 /* Never seen before */
3008                 DEBUGP("change expect: never seen before\n");
3009 -               if (!ip_ct_tuple_equal(&expect->tuple, newtuple) 
3010 +               if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask)
3011                     && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
3012                                  struct ip_conntrack_expect *, newtuple, &expect->mask)) {
3013                         /* Force NAT to find an unused tuple */
3014 @@ -1084,8 +1143,15 @@
3015         return ret;
3016  }
3017  
3018 -/* Alter reply tuple (maybe alter helper).  If it's already taken,
3019 -   return 0 and don't do alteration. */
3020 +/**
3021 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
3022 + * @conntrack: conntrack whose reply tuple we want to alter
3023 + * @newreply: designated reply tuple for this conntrack
3024 + *
3025 + * This function alters the reply tuple of a conntrack to the given
3026 + * newreply tuple.  If this newreply tuple is already taken, return 0
3027 + * and don't do alteration
3028 + */
3029  int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
3030                              const struct ip_conntrack_tuple *newreply)
3031  {
3032 @@ -1110,6 +1176,13 @@
3033         return 1;
3034  }
3035  
3036 +/**
3037 + * ip_conntrack_helper_register - Register a conntrack application helper
3038 + * @me: structure describing the helper
3039 + *
3040 + * This function is called by conntrack application helpers to register
3041 + * themselves with the conntrack core.
3042 + */
3043  int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
3044  {
3045         WRITE_LOCK(&ip_conntrack_lock);
3046 @@ -1131,6 +1204,13 @@
3047         return 0;
3048  }
3049  
3050 +/**
3051 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
3052 + * @me: structure describing the helper
3053 + *
3054 + * This function is called by conntrack application helpers to unregister
3055 + * themselvers from the conntrack core.
3056 + */
3057  void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
3058  {
3059         unsigned int i;
3060 @@ -1149,7 +1229,14 @@
3061         synchronize_net();
3062  }
3063  
3064 -/* Refresh conntrack for this many jiffies. */
3065 +/**
3066 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
3067 + * @ct: conntrack which we want to refresh
3068 + * @extra_jiffies: number of jiffies to add
3069 + *
3070 + * This function is called by protocol helpers and application helpers in
3071 + * order to change the expiration timer of a conntrack entry.
3072 + */
3073  void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
3074  {
3075         IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
3076 @@ -1159,8 +1246,10 @@
3077         if (!is_confirmed(ct))
3078                 ct->timeout.expires = extra_jiffies;
3079         else {
3080 -               /* Need del_timer for race avoidance (may already be dying). */
3081 -               if (del_timer(&ct->timeout)) {
3082 +               /* Don't update timer for each packet, only if it's been >HZ
3083 +                * ticks since last update.
3084 +                * Need del_timer for race avoidance (may already be dying). */
3085 +               if (abs(jiffies + extra_jiffies - ct->timeout.expires) >= HZ && del_timer(&ct->timeout)) {
3086                         ct->timeout.expires = jiffies + extra_jiffies;
3087                         add_timer(&ct->timeout);
3088                 }
3089 @@ -1168,7 +1257,16 @@
3090         WRITE_UNLOCK(&ip_conntrack_lock);
3091  }
3092  
3093 -/* Returns new sk_buff, or NULL */
3094 +
3095 +/**
3096 + * ip_ct_gather_frags - Gather fragments of a particular skb
3097 + * @skb: pointer to sk_buff of fragmented IP packet
3098 + *
3099 + * This code is just a wrapper around the defragmentation code in the core IPv4
3100 + * stack.  It also takes care of nonlinear skb's.
3101 + *
3102 + * Returns new sk_buff, or NULL
3103 + */
3104  struct sk_buff *
3105  ip_ct_gather_frags(struct sk_buff *skb)
3106  {
3107 @@ -1253,6 +1351,16 @@
3108         return h;
3109  }
3110  
3111 +/**
3112 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
3113 + * @kill: callback function selecting which entries to delete
3114 + * @data: opaque data pointer, becomes 2nd argument for kill function
3115 + *
3116 + * This function can be used to selectively delete elements of the conntrack
3117 + * hashtable.  The function iterates over the list of conntrack entries and
3118 + * calls the 'kill' function for every entry.  If the return value is true,
3119 + * the connection is deleted (death_by_timeout).
3120 + */
3121  void
3122  ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
3123                         void *data)
3124 @@ -1263,7 +1371,7 @@
3125         while ((h = get_next_corpse(kill, data)) != NULL) {
3126                 /* Time to push up daises... */
3127                 if (del_timer(&h->ctrack->timeout))
3128 -                       death_by_timeout((unsigned long)h->ctrack);
3129 +                       ip_ct_death_by_timeout((unsigned long)h->ctrack);
3130                 /* ... else the timer will get him soon. */
3131  
3132                 ip_conntrack_put(h->ctrack);
3133 @@ -1419,6 +1527,15 @@
3134  
3135         /* For use by ipt_REJECT */
3136         ip_ct_attach = ip_conntrack_attach;
3137 +
3138 +       /* Set up fake conntrack:
3139 +           - to never be deleted, not in any hashes */
3140 +       atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
3141 +       /*  - and look it like as a confirmed connection */
3142 +       set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
3143 +       /*  - and prepare the ctinfo field for NAT. */
3144 +       ip_conntrack_untracked.infos[IP_CT_NEW].master = &ip_conntrack_untracked.ct_general;
3145 +
3146         return ret;
3147  
3148  err_free_hash:
3149 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_egg.c
3150 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_egg.c        1970-01-01 01:00:00.000000000 +0100
3151 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_egg.c    2003-12-10 23:13:56.912424080 +0100
3152 @@ -0,0 +1,237 @@
3153 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3154 + * based on ip_conntrack_irc.c 
3155 + *
3156 + *      This module only supports the share userfile-send command,
3157 + *      used by eggdrops to share it's userfile.
3158 + *
3159 + *      There are no support for NAT at the moment.
3160 + *
3161 + *      This program is free software; you can redistribute it and/or
3162 + *      modify it under the terms of the GNU General Public License
3163 + *      as published by the Free Software Foundation; either version
3164 + *      2 of the License, or (at your option) any later version.
3165 + *
3166 + *     Module load syntax:
3167 + *     
3168 + *     please give the ports of all Eggdrops You have running
3169 + *      on your system, the default port is 3333.
3170 + *
3171 + *      2001-04-19: Security update. IP addresses are now compared
3172 + *                  to prevent unauthorized "related" access.
3173 + *
3174 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
3175 + *                 Port to netfilter 'newnat' API.
3176 + */
3177 +
3178 +#include <linux/module.h>
3179 +#include <linux/netfilter.h>
3180 +#include <linux/ip.h>
3181 +#include <net/checksum.h>
3182 +#include <net/tcp.h>
3183 +
3184 +#include <linux/netfilter_ipv4/lockhelp.h>
3185 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3186 +
3187 +#define MAX_PORTS 8
3188 +static int ports[MAX_PORTS];
3189 +static int ports_c = 0;
3190 +static unsigned int egg_timeout = 300;
3191 +
3192 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3193 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3194 +MODULE_LICENSE("GPL");
3195 +#ifdef MODULE_PARM
3196 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3197 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3198 +#endif
3199 +
3200 +DECLARE_LOCK(ip_egg_lock);
3201 +struct module *ip_conntrack_egg = THIS_MODULE;
3202 +
3203 +#if 0
3204 +#define DEBUGP printk
3205 +#else
3206 +#define DEBUGP(format, args...)
3207 +#endif
3208 +
3209 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3210 +/* tries to get the ip_addr and port out of a eggdrop command
3211 +   return value: -1 on failure, 0 on success 
3212 +   data                pointer to first byte of DCC command data
3213 +   data_end    pointer to last byte of dcc command data
3214 +   ip          returns parsed ip of dcc command
3215 +   port                returns parsed port of dcc command */
3216 +{
3217 +       if (data > data_end)
3218 +               return -1;
3219 +       
3220 +       *ip = simple_strtoul(data, &data, 10);
3221 +
3222 +       /* skip blanks between ip and port */
3223 +       while (*data == ' ' && data < data_end)
3224 +               data++;
3225 +
3226 +       *port = simple_strtoul(data, &data, 10);
3227 +       return 0;
3228 +}
3229 +
3230 +
3231 +static int help(const struct iphdr *iph, size_t len,
3232 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3233 +{
3234 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3235 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3236 +       char *data = (char *) tcph + tcph->doff * 4;
3237 +       char *data_limit;
3238 +       u_int32_t tcplen = len - iph->ihl * 4;
3239 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3240 +       int dir = CTINFO2DIR(ctinfo);
3241 +       int bytes_scanned = 0;
3242 +       struct ip_conntrack_expect exp;
3243 +
3244 +       u_int32_t egg_ip;
3245 +       u_int16_t egg_port;
3246 +
3247 +       DEBUGP("entered\n");
3248 +
3249 +       /* If packet is coming from IRC server */
3250 +       if (dir != IP_CT_DIR_REPLY)
3251 +               return NF_ACCEPT;
3252 +
3253 +       /* Until there's been traffic both ways, don't look in packets. */
3254 +       if (ctinfo != IP_CT_ESTABLISHED
3255 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3256 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
3257 +               return NF_ACCEPT;
3258 +       }
3259 +
3260 +       /* Not whole TCP header? */
3261 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3262 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3263 +               return NF_ACCEPT;
3264 +       }
3265 +
3266 +       /* Checksum invalid?  Ignore. */
3267 +       /* FIXME: Source route IP option packets --RR */
3268 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3269 +                        csum_partial((char *) tcph, tcplen, 0))) {
3270 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3271 +                       tcph, tcplen, NIPQUAD(iph->saddr),
3272 +                       NIPQUAD(iph->daddr));
3273 +               return NF_ACCEPT;
3274 +       }
3275 +
3276 +       data_limit = (char *) data + datalen;
3277 +       while (datalen > 5 && bytes_scanned < 128) {
3278 +               if (memcmp(data, "s us ", 5)) {
3279 +                       data++;
3280 +                       datalen--;
3281 +                       bytes_scanned++;
3282 +                       continue;
3283 +               }
3284 +
3285 +               data += 5;
3286 +
3287 +               DEBUGP("Userfile-share found in connection "
3288 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3289 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3290 +
3291 +               if (parse_command((char *) data, data_limit, &egg_ip,
3292 +                                 &egg_port)) {
3293 +                       DEBUGP("no data in userfile-share pkt\n");
3294 +                       return NF_ACCEPT;
3295 +               }
3296 +
3297 +               memset(&exp, 0, sizeof(exp));
3298 +
3299 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3300 +                       if (net_ratelimit())
3301 +                               printk("Forged Eggdrop command from "
3302 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3303 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3304 +                                      HIPQUAD(egg_ip), egg_port);
3305 +                       return NF_ACCEPT;
3306 +               }
3307 +
3308 +               exp.tuple.src.ip = iph->daddr;
3309 +               exp.tuple.src.u.tcp.port = 0;
3310 +               exp.tuple.dst.ip = htonl(egg_ip);
3311 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
3312 +               exp.tuple.dst.protonum = IPPROTO_TCP;
3313 +
3314 +               exp.mask.dst.u.tcp.port = 0xffff;
3315 +               exp.mask.dst.protonum = 0xffff;
3316 +
3317 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3318 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3319 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3320 +
3321 +               ip_conntrack_expect_related(ct, &exp);
3322 +               break;
3323 +       }
3324 +       return NF_ACCEPT;
3325 +}
3326 +
3327 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3328 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3329 +
3330 +static void deregister_helpers(void) {
3331 +       int i;
3332 +       
3333 +       for (i = 0; i < ports_c; i++) {
3334 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
3335 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
3336 +       }
3337 +}
3338 +
3339 +static int __init init(void)
3340 +{
3341 +       int i, ret;
3342 +       char *tmpname;
3343 +
3344 +       /* If no port given, default to standard eggdrop port */
3345 +       if (ports[0] == 0)
3346 +               ports[0] = 3333;
3347 +
3348 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3349 +               memset(&egg_helpers[i], 0,
3350 +                      sizeof(struct ip_conntrack_helper));
3351 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3352 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3353 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3354 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
3355 +               egg_helpers[i].max_expected = 1;
3356 +               egg_helpers[i].timeout = egg_timeout;
3357 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3358 +               egg_helpers[i].me = THIS_MODULE;
3359 +               egg_helpers[i].help = help;
3360 +
3361 +               tmpname = &egg_names[i][0];
3362 +               if (ports[i] == 3333)
3363 +                       sprintf(tmpname, "eggdrop");
3364 +               else
3365 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
3366 +               egg_helpers[i].name = tmpname;
3367 +
3368 +               DEBUGP("port #%d: %d\n", i, ports[i]);
3369 +
3370 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
3371 +
3372 +               if (ret) {
3373 +                       printk("ip_conntrack_egg: ERROR registering helper "
3374 +                               "for port %d\n", ports[i]);
3375 +                       deregister_helpers();
3376 +                       return 1;
3377 +               }
3378 +               ports_c++;
3379 +       }
3380 +       return 0;
3381 +}
3382 +
3383 +static void __exit fini(void)
3384 +{
3385 +       deregister_helpers();
3386 +}
3387 +
3388 +module_init(init);
3389 +module_exit(fini);
3390 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_h323.c
3391 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_h323.c       1970-01-01 01:00:00.000000000 +0100
3392 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_h323.c   2003-12-10 23:13:58.177231800 +0100
3393 @@ -0,0 +1,308 @@
3394 +/* 
3395 + * H.323 'brute force' extension for H.323 connection tracking. 
3396 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3397 + *
3398 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3399 + * (http://www.coritel.it/projects/sofia/nat/)
3400 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3401 + * the unregistered helpers to the conntrack entries.
3402 + */
3403 +
3404 +
3405 +#include <linux/module.h>
3406 +#include <linux/netfilter.h>
3407 +#include <linux/ip.h>
3408 +#include <net/checksum.h>
3409 +#include <net/tcp.h>
3410 +
3411 +#include <linux/netfilter_ipv4/lockhelp.h>
3412 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3413 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3414 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3415 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3416 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3417 +
3418 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3419 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3420 +MODULE_LICENSE("GPL");
3421 +
3422 +DECLARE_LOCK(ip_h323_lock);
3423 +struct module *ip_conntrack_h323 = THIS_MODULE;
3424 +
3425 +#if 0
3426 +#define DEBUGP printk
3427 +#else
3428 +#define DEBUGP(format, args...)
3429 +#endif
3430 +
3431 +/* FIXME: This should be in userspace.  Later. */
3432 +static int h245_help(const struct iphdr *iph, size_t len,
3433 +                    struct ip_conntrack *ct,
3434 +                    enum ip_conntrack_info ctinfo)
3435 +{
3436 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3437 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3438 +       unsigned char *data_limit;
3439 +       u_int32_t tcplen = len - iph->ihl * 4;
3440 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3441 +       int dir = CTINFO2DIR(ctinfo);
3442 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3443 +       struct ip_conntrack_expect expect, *exp = &expect;
3444 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3445 +       u_int16_t data_port;
3446 +       u_int32_t data_ip;
3447 +       unsigned int i;
3448 +
3449 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3450 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3451 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3452 +
3453 +       /* Can't track connections formed before we registered */
3454 +       if (!info)
3455 +               return NF_ACCEPT;
3456 +               
3457 +       /* Until there's been traffic both ways, don't look in packets. */
3458 +       if (ctinfo != IP_CT_ESTABLISHED
3459 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3460 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3461 +               return NF_ACCEPT;
3462 +       }
3463 +
3464 +       /* Not whole TCP header or too short packet? */
3465 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3466 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3467 +               return NF_ACCEPT;
3468 +       }
3469 +
3470 +       /* Checksum invalid?  Ignore. */
3471 +       /* FIXME: Source route IP option packets --RR */
3472 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3473 +                             csum_partial((char *)tcph, tcplen, 0))) {
3474 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3475 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3476 +                      NIPQUAD(iph->daddr));
3477 +               return NF_ACCEPT;
3478 +       }
3479 +
3480 +       data_limit = (unsigned char *) data + datalen;
3481 +       /* bytes: 0123   45
3482 +                 ipadrr port */
3483 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3484 +               data_ip = *((u_int32_t *)data);
3485 +               if (data_ip == iph->saddr) {
3486 +                       data_port = *((u_int16_t *)(data + 4));
3487 +                       memset(&expect, 0, sizeof(expect));
3488 +                       /* update the H.225 info */
3489 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3490 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3491 +                               NIPQUAD(iph->saddr), ntohs(data_port));
3492 +                       LOCK_BH(&ip_h323_lock);
3493 +                       info->is_h225 = H225_PORT + 1;
3494 +                       exp_info->port = data_port;
3495 +                       exp_info->dir = dir;
3496 +                       exp_info->offset = i;
3497 +
3498 +                       exp->seq = ntohl(tcph->seq) + i;
3499 +                   
3500 +                       exp->tuple = ((struct ip_conntrack_tuple)
3501 +                               { { ct->tuplehash[!dir].tuple.src.ip,
3502 +                                   { 0 } },
3503 +                                 { data_ip,
3504 +                                   { .tcp = { data_port } },
3505 +                                   IPPROTO_UDP }});
3506 +                       exp->mask = ((struct ip_conntrack_tuple)
3507 +                               { { 0xFFFFFFFF, { 0 } },
3508 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3509 +       
3510 +                       exp->expectfn = NULL;
3511 +                       
3512 +                       /* Ignore failure; should only happen with NAT */
3513 +                       ip_conntrack_expect_related(ct, exp);
3514 +
3515 +                       UNLOCK_BH(&ip_h323_lock);
3516 +               }
3517 +       }
3518 +
3519 +       return NF_ACCEPT;
3520 +
3521 +}
3522 +
3523 +/* H.245 helper is not registered! */
3524 +static struct ip_conntrack_helper h245 = 
3525 +       { { NULL, NULL },
3526 +          "H.245",                             /* name */
3527 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
3528 +          NULL,                                        /* module */
3529 +          8,                                   /* max_ expected */
3530 +          240,                                 /* timeout */
3531 +          { { 0, { 0 } },                      /* tuple */
3532 +            { 0, { 0 }, IPPROTO_TCP } },
3533 +          { { 0, { 0xFFFF } },                 /* mask */
3534 +            { 0, { 0 }, 0xFFFF } },
3535 +          h245_help                            /* helper */
3536 +       };
3537 +
3538 +static int h225_expect(struct ip_conntrack *ct)
3539 +{
3540 +       WRITE_LOCK(&ip_conntrack_lock);
3541 +       ct->helper = &h245;
3542 +       DEBUGP("h225_expect: helper for %p added\n", ct);
3543 +       WRITE_UNLOCK(&ip_conntrack_lock);
3544 +       
3545 +       return NF_ACCEPT;       /* unused */
3546 +}
3547 +
3548 +/* FIXME: This should be in userspace.  Later. */
3549 +static int h225_help(const struct iphdr *iph, size_t len,
3550 +                    struct ip_conntrack *ct,
3551 +                    enum ip_conntrack_info ctinfo)
3552 +{
3553 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3554 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3555 +       unsigned char *data_limit;
3556 +       u_int32_t tcplen = len - iph->ihl * 4;
3557 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3558 +       int dir = CTINFO2DIR(ctinfo);
3559 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3560 +       struct ip_conntrack_expect expect, *exp = &expect;
3561 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3562 +       u_int16_t data_port;
3563 +       u_int32_t data_ip;
3564 +       unsigned int i;
3565 +       
3566 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3567 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3568 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3569 +
3570 +       /* Can't track connections formed before we registered */
3571 +       if (!info)
3572 +               return NF_ACCEPT;
3573 +
3574 +       /* Until there's been traffic both ways, don't look in packets. */
3575 +       if (ctinfo != IP_CT_ESTABLISHED
3576 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3577 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3578 +               return NF_ACCEPT;
3579 +       }
3580 +
3581 +       /* Not whole TCP header or too short packet? */
3582 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3583 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3584 +               return NF_ACCEPT;
3585 +       }
3586 +
3587 +       /* Checksum invalid?  Ignore. */
3588 +       /* FIXME: Source route IP option packets --RR */
3589 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3590 +                             csum_partial((char *)tcph, tcplen, 0))) {
3591 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3592 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3593 +                      NIPQUAD(iph->daddr));
3594 +               return NF_ACCEPT;
3595 +       }
3596 +       
3597 +       data_limit = (unsigned char *) data + datalen;
3598 +       /* bytes: 0123   45
3599 +                 ipadrr port */
3600 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3601 +               data_ip = *((u_int32_t *)data);
3602 +               if (data_ip == iph->saddr) {
3603 +                       data_port = *((u_int16_t *)(data + 4));
3604 +                       if (data_port == tcph->source) {
3605 +                               /* Signal address */
3606 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3607 +                                       NIPQUAD(iph->saddr));
3608 +                               /* Update the H.225 info so that NAT can mangle the address/port
3609 +                                  even when we have no expected connection! */
3610 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3611 +                               LOCK_BH(&ip_h323_lock);
3612 +                               info->dir = dir;
3613 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3614 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
3615 +                               UNLOCK_BH(&ip_h323_lock);
3616 +#endif
3617 +                       } else {
3618 +                               memset(&expect, 0, sizeof(expect));
3619 +
3620 +                               /* update the H.225 info */
3621 +                               LOCK_BH(&ip_h323_lock);
3622 +                               info->is_h225 = H225_PORT;
3623 +                               exp_info->port = data_port;
3624 +                               exp_info->dir = dir;
3625 +                               exp_info->offset = i;
3626 +
3627 +                               exp->seq = ntohl(tcph->seq) + i;
3628 +
3629 +                               exp->tuple = ((struct ip_conntrack_tuple)
3630 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
3631 +                                           { 0 } },
3632 +                                         { data_ip,
3633 +                                           { .tcp = { data_port } },
3634 +                                           IPPROTO_TCP }});
3635 +                               exp->mask = ((struct ip_conntrack_tuple)
3636 +                                       { { 0xFFFFFFFF, { 0 } },
3637 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3638 +       
3639 +                               exp->expectfn = h225_expect;
3640 +                               
3641 +                               /* Ignore failure */
3642 +                               ip_conntrack_expect_related(ct, exp);
3643 +
3644 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3645 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3646 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
3647 +
3648 +                               UNLOCK_BH(&ip_h323_lock);
3649 +                       }  
3650 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3651 +               } else if (data_ip == iph->daddr) {
3652 +                       data_port = *((u_int16_t *)(data + 4));
3653 +                       if (data_port == tcph->dest) {
3654 +                               /* Signal address */
3655 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3656 +                                       NIPQUAD(iph->daddr));
3657 +                               /* Update the H.225 info so that NAT can mangle the address/port
3658 +                                  even when we have no expected connection! */
3659 +                               LOCK_BH(&ip_h323_lock);
3660 +                               info->dir = dir;
3661 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3662 +                               info->offset[IP_CT_DIR_REPLY] = i;
3663 +                               UNLOCK_BH(&ip_h323_lock);
3664 +                       }
3665 +#endif
3666 +               }
3667 +       }
3668 +
3669 +       return NF_ACCEPT;
3670 +
3671 +}
3672 +
3673 +static struct ip_conntrack_helper h225 = 
3674 +       { { NULL, NULL },
3675 +         "H.225",                                      /* name */
3676 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
3677 +         THIS_MODULE,                                  /* module */
3678 +         2,                                            /* max_expected */
3679 +         240,                                          /* timeout */
3680 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
3681 +           { 0, { 0 }, IPPROTO_TCP } },
3682 +         { { 0, { 0xFFFF } },                          /* mask */
3683 +           { 0, { 0 }, 0xFFFF } },
3684 +         h225_help                                     /* helper */
3685 +       };
3686 +
3687 +static int __init init(void)
3688 +{
3689 +       return ip_conntrack_helper_register(&h225);
3690 +}
3691 +
3692 +static void __exit fini(void)
3693 +{
3694 +       /* Unregister H.225 helper */   
3695 +       ip_conntrack_helper_unregister(&h225);
3696 +}
3697 +
3698 +EXPORT_SYMBOL(ip_h323_lock);
3699 +
3700 +module_init(init);
3701 +module_exit(fini);
3702 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_mms.c
3703 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_mms.c        1970-01-01 01:00:00.000000000 +0100
3704 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_mms.c    2003-12-10 23:14:02.756535640 +0100
3705 @@ -0,0 +1,308 @@
3706 +/* MMS extension for IP connection tracking
3707 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3708 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
3709 + *
3710 + * ip_conntrack_mms.c v0.3 2002-09-22
3711 + *
3712 + *      This program is free software; you can redistribute it and/or
3713 + *      modify it under the terms of the GNU General Public License
3714 + *      as published by the Free Software Foundation; either version
3715 + *      2 of the License, or (at your option) any later version.
3716 + *
3717 + *      Module load syntax:
3718 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
3719 + *
3720 + *      Please give the ports of all MMS servers You wish to connect to.
3721 + *      If you don't specify ports, the default will be TCP port 1755.
3722 + *
3723 + *      More info on MMS protocol, firewalls and NAT:
3724 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
3725 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
3726 + *
3727 + *      The SDP project people are reverse-engineering MMS:
3728 + *      http://get.to/sdp
3729 + */
3730 +
3731 +#include <linux/config.h>
3732 +#include <linux/module.h>
3733 +#include <linux/netfilter.h>
3734 +#include <linux/ip.h>
3735 +#include <linux/ctype.h>
3736 +#include <net/checksum.h>
3737 +#include <net/tcp.h>
3738 +
3739 +#include <linux/netfilter_ipv4/lockhelp.h>
3740 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3741 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
3742 +
3743 +DECLARE_LOCK(ip_mms_lock);
3744 +struct module *ip_conntrack_mms = THIS_MODULE;
3745 +
3746 +#define MAX_PORTS 8
3747 +static int ports[MAX_PORTS];
3748 +static int ports_c;
3749 +#ifdef MODULE_PARM
3750 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3751 +#endif
3752 +
3753 +#if 0 
3754 +#define DEBUGP printk
3755 +#else
3756 +#define DEBUGP(format, args...)
3757 +#endif
3758 +
3759 +EXPORT_SYMBOL(ip_mms_lock);
3760 +
3761 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3762 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
3763 +MODULE_LICENSE("GPL");
3764 +
3765 +/* #define isdigit(c) (c >= '0' && c <= '9') */
3766 +
3767 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
3768 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
3769 +{
3770 +       int i;
3771 +       for (i = 0; i < unicode_size; ++i) {
3772 +               string[i] = (char)(unicode[i]);
3773 +       }
3774 +       string[unicode_size] = 0x00;
3775 +}
3776 +
3777 +__inline static int atoi(char *s) 
3778 +{
3779 +       int i=0;
3780 +       while (isdigit(*s)) {
3781 +               i = i*10 + *(s++) - '0';
3782 +       }
3783 +       return i;
3784 +}
3785 +
3786 +/* convert ip address string like "192.168.0.10" to unsigned int */
3787 +__inline static u_int32_t asciiiptoi(char *s)
3788 +{
3789 +       unsigned int i, j, k;
3790 +
3791 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
3792 +               i+=atoi(s);
3793 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
3794 +                       ;
3795 +       }
3796 +       i+=atoi(s);
3797 +       return ntohl(i);
3798 +}
3799 +
3800 +int parse_mms(const char *data, 
3801 +             const unsigned int datalen,
3802 +             u_int32_t *mms_ip,
3803 +             u_int16_t *mms_proto,
3804 +             u_int16_t *mms_port,
3805 +             char **mms_string_b,
3806 +             char **mms_string_e,
3807 +             char **mms_padding_e)
3808 +{
3809 +       int unicode_size, i;
3810 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
3811 +       char getlengthstring[28];
3812 +       
3813 +       for(unicode_size=0; 
3814 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
3815 +           unicode_size++)
3816 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
3817 +                       return -1; /* out of bounds - incomplete packet */
3818 +       
3819 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
3820 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
3821 +       
3822 +       /* IP address ? */
3823 +       *mms_ip = asciiiptoi(tempstring+2);
3824 +       
3825 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
3826 +               
3827 +       /* protocol ? */
3828 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
3829 +               *mms_proto = IPPROTO_TCP;
3830 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
3831 +               *mms_proto = IPPROTO_UDP;
3832 +
3833 +       /* port ? */
3834 +       *mms_port = atoi(tempstring+7+i);
3835 +
3836 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
3837 +          unicode string, one to the end of the string, and one to the end 
3838 +          of the packet, since we must keep track of the number of bytes 
3839 +          between end of the unicode string and the end of packet (padding) */
3840 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
3841 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
3842 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
3843 +       return 0;
3844 +}
3845 +
3846 +
3847 +/* FIXME: This should be in userspace.  Later. */
3848 +static int help(const struct iphdr *iph, size_t len,
3849 +               struct ip_conntrack *ct,
3850 +               enum ip_conntrack_info ctinfo)
3851 +{
3852 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
3853 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3854 +       const char *data = (const char *)tcph + tcph->doff * 4;
3855 +       unsigned int tcplen = len - iph->ihl * 4;
3856 +       unsigned int datalen = tcplen - tcph->doff * 4;
3857 +       int dir = CTINFO2DIR(ctinfo);
3858 +       struct ip_conntrack_expect expect, *exp = &expect; 
3859 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
3860 +       
3861 +       u_int32_t mms_ip;
3862 +       u_int16_t mms_proto;
3863 +       char mms_proto_string[8];
3864 +       u_int16_t mms_port;
3865 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
3866 +            
3867 +       /* Until there's been traffic both ways, don't look in packets. */
3868 +       if (ctinfo != IP_CT_ESTABLISHED
3869 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
3870 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
3871 +               return NF_ACCEPT;
3872 +       }
3873 +
3874 +       /* Not whole TCP header? */
3875 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
3876 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
3877 +               return NF_ACCEPT;
3878 +       }
3879 +
3880 +       /* Checksum invalid?  Ignore. */
3881 +       /* FIXME: Source route IP option packets --RR */
3882 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3883 +           csum_partial((char *)tcph, tcplen, 0))) {
3884 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3885 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3886 +                      NIPQUAD(iph->daddr));
3887 +               return NF_ACCEPT;
3888 +       }
3889 +       
3890 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
3891 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
3892 +          the client has already sent a packet to the server with the server's hostname 
3893 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
3894 +          server will break the connection if this doesn't correspond to its own host 
3895 +          header. The client can also connect to an IP address; if it's the server's IP
3896 +          address, it will not break the connection. When doing DNAT on a connection 
3897 +          where the client uses a server's IP address, the nat module should detect
3898 +          this and change this string accordingly to the DNATed address. This should
3899 +          probably be done by checking for an IP address, then storing it as a member
3900 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
3901 +          */
3902 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
3903 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
3904 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
3905 +                      (u8)*(data+36), (u8)*(data+37), 
3906 +                      (u8)*(data+38), (u8)*(data+39),
3907 +                      datalen);
3908 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
3909 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
3910 +                       if(net_ratelimit())
3911 +                               /* FIXME: more verbose debugging ? */
3912 +                               printk(KERN_WARNING
3913 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
3914 +
3915 +               memset(&expect, 0, sizeof(expect));
3916 +
3917 +               sprintf(mms_proto_string, "(%u)", mms_proto);
3918 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
3919 +                      mms_proto == IPPROTO_TCP ? "TCP"
3920 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
3921 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3922 +                      NIPQUAD(mms_ip),
3923 +                      mms_port);
3924 +               
3925 +               /* it's possible that the client will just ask the server to tunnel
3926 +                  the stream over the same TCP session (from port 1755): there's 
3927 +                  shouldn't be a need to add an expectation in that case, but it
3928 +                  makes NAT packet mangling so much easier */
3929 +               LOCK_BH(&ip_mms_lock);
3930 +
3931 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
3932 +               
3933 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
3934 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
3935 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
3936 +               exp_mms_info->port    = mms_port;
3937 +               
3938 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
3939 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
3940 +               
3941 +               exp->tuple = ((struct ip_conntrack_tuple)
3942 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3943 +                             { mms_ip,
3944 +                               { .tcp = { (__u16) ntohs(mms_port) } },
3945 +                               mms_proto } }
3946 +                            );
3947 +               exp->mask  = ((struct ip_conntrack_tuple)
3948 +                            { { 0xFFFFFFFF, { 0 } },
3949 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3950 +               exp->expectfn = NULL;
3951 +               ip_conntrack_expect_related(ct, &expect);
3952 +               UNLOCK_BH(&ip_mms_lock);
3953 +       }
3954 +
3955 +       return NF_ACCEPT;
3956 +}
3957 +
3958 +static struct ip_conntrack_helper mms[MAX_PORTS];
3959 +static char mms_names[MAX_PORTS][10];
3960 +
3961 +/* Not __exit: called from init() */
3962 +static void fini(void)
3963 +{
3964 +       int i;
3965 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3966 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
3967 +                               ports[i]);
3968 +               ip_conntrack_helper_unregister(&mms[i]);
3969 +       }
3970 +}
3971 +
3972 +static int __init init(void)
3973 +{
3974 +       int i, ret;
3975 +       char *tmpname;
3976 +
3977 +       if (ports[0] == 0)
3978 +               ports[0] = MMS_PORT;
3979 +
3980 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3981 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
3982 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
3983 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
3984 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
3985 +               mms[i].mask.dst.protonum = 0xFFFF;
3986 +               mms[i].max_expected = 1;
3987 +               mms[i].timeout = 0;
3988 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3989 +               mms[i].me = THIS_MODULE;
3990 +               mms[i].help = help;
3991 +
3992 +               tmpname = &mms_names[i][0];
3993 +               if (ports[i] == MMS_PORT)
3994 +                       sprintf(tmpname, "mms");
3995 +               else
3996 +                       sprintf(tmpname, "mms-%d", ports[i]);
3997 +               mms[i].name = tmpname;
3998 +
3999 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
4000 +                               ports[i]);
4001 +               ret = ip_conntrack_helper_register(&mms[i]);
4002 +
4003 +               if (ret) {
4004 +                       fini();
4005 +                       return ret;
4006 +               }
4007 +               ports_c++;
4008 +       }
4009 +       return 0;
4010 +}
4011 +
4012 +module_init(init);
4013 +module_exit(fini);
4014 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp.c
4015 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp.c       1970-01-01 01:00:00.000000000 +0100
4016 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp.c   2003-12-10 23:14:24.102290592 +0100
4017 @@ -0,0 +1,639 @@
4018 +/*
4019 + * ip_conntrack_pptp.c - Version 1.9
4020 + *
4021 + * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
4022 + * PPTP is a a protocol for creating virtual private networks.
4023 + * It is a specification defined by Microsoft and some vendors
4024 + * working with Microsoft.  PPTP is built on top of a modified
4025 + * version of the Internet Generic Routing Encapsulation Protocol.
4026 + * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
4027 + * PPTP can be found in RFC 2637
4028 + *
4029 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4030 + *
4031 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4032 + *
4033 + * Limitations:
4034 + *      - We blindly assume that control connections are always
4035 + *        established in PNS->PAC direction.  This is a violation
4036 + *        of RFFC2673
4037 + *
4038 + * TODO: - finish support for multiple calls within one session
4039 + *        (needs expect reservations in newnat)
4040 + *      - testing of incoming PPTP calls 
4041 + *
4042 + * Changes: 
4043 + *     2002-02-05 - Version 1.3
4044 + *       - Call ip_conntrack_unexpect_related() from 
4045 + *         pptp_timeout_related() to destroy expectations in case
4046 + *         CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
4047 + *         (Philip Craig <philipc@snapgear.com>)
4048 + *       - Add Version information at module loadtime
4049 + *     2002-02-10 - Version 1.6
4050 + *       - move to C99 style initializers
4051 + *       - remove second expectation if first arrives
4052 + *
4053 + */
4054 +
4055 +#include <linux/config.h>
4056 +#include <linux/module.h>
4057 +#include <linux/netfilter.h>
4058 +#include <linux/ip.h>
4059 +#include <net/checksum.h>
4060 +#include <net/tcp.h>
4061 +
4062 +#include <linux/netfilter_ipv4/lockhelp.h>
4063 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4064 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4065 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4066 +
4067 +#define IP_CT_PPTP_VERSION "1.9"
4068 +
4069 +MODULE_LICENSE("GPL");
4070 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4071 +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
4072 +
4073 +DECLARE_LOCK(ip_pptp_lock);
4074 +
4075 +#if 0
4076 +#include "ip_conntrack_pptp_priv.h"
4077 +#define DEBUGP(format, args...)        printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4078 +                                       ": " format, ## args)
4079 +#else
4080 +#define DEBUGP(format, args...)
4081 +#endif
4082 +
4083 +#define SECS *HZ
4084 +#define MINS * 60 SECS
4085 +#define HOURS * 60 MINS
4086 +#define DAYS * 24 HOURS
4087 +
4088 +#define PPTP_GRE_TIMEOUT               (10 MINS)
4089 +#define PPTP_GRE_STREAM_TIMEOUT        (5 DAYS)
4090 +
4091 +static int pptp_expectfn(struct ip_conntrack *ct)
4092 +{
4093 +       struct ip_conntrack *master;
4094 +       struct ip_conntrack_expect *exp;
4095 +
4096 +       DEBUGP("increasing timeouts\n");
4097 +       /* increase timeout of GRE data channel conntrack entry */
4098 +       ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
4099 +       ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
4100 +
4101 +       master = master_ct(ct);
4102 +       if (!master) {
4103 +               DEBUGP(" no master!!!\n");
4104 +               return 0;
4105 +       }
4106 +
4107 +       exp = ct->master;
4108 +       if (!exp) {
4109 +               DEBUGP("no expectation!!\n");
4110 +               return 0;
4111 +       }
4112 +
4113 +       DEBUGP("completing tuples with ct info\n");
4114 +       /* we can do this, since we're unconfirmed */
4115 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == 
4116 +               htonl(master->help.ct_pptp_info.pac_call_id)) { 
4117 +               /* assume PNS->PAC */
4118 +               ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = 
4119 +                       htonl(master->help.ct_pptp_info.pns_call_id);
4120 +               ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4121 +                       htonl(master->help.ct_pptp_info.pns_call_id);
4122 +       } else {
4123 +               /* assume PAC->PNS */
4124 +               ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
4125 +                       htonl(master->help.ct_pptp_info.pac_call_id);
4126 +               ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4127 +                       htonl(master->help.ct_pptp_info.pac_call_id);
4128 +       }
4129 +       
4130 +       /* delete other expectation */
4131 +       if (exp->expected_list.next != &exp->expected_list) {
4132 +               struct ip_conntrack_expect *other_exp;
4133 +               struct list_head *cur_item, *next;
4134 +
4135 +               for (cur_item = master->sibling_list.next;
4136 +                    cur_item != &master->sibling_list; cur_item = next) {
4137 +                       next = cur_item->next;
4138 +                       other_exp = list_entry(cur_item,
4139 +                                              struct ip_conntrack_expect,
4140 +                                              expected_list);
4141 +                       /* remove only if occurred at same sequence number */
4142 +                       if (other_exp != exp && other_exp->seq == exp->seq) {
4143 +                               DEBUGP("unexpecting other direction\n");
4144 +                               ip_ct_gre_keymap_destroy(other_exp);
4145 +                               ip_conntrack_unexpect_related(other_exp);
4146 +                       }
4147 +               }
4148 +       }
4149 +
4150 +       return 0;
4151 +}
4152 +
4153 +/* timeout GRE data connections */
4154 +static int pptp_timeout_related(struct ip_conntrack *ct)
4155 +{
4156 +       struct list_head *cur_item, *next;
4157 +       struct ip_conntrack_expect *exp;
4158 +
4159 +       /* FIXME: do we have to lock something ? */
4160 +       for (cur_item = ct->sibling_list.next;
4161 +           cur_item != &ct->sibling_list; cur_item = next) {
4162 +               next = cur_item->next;
4163 +               exp = list_entry(cur_item, struct ip_conntrack_expect,
4164 +                                expected_list);
4165 +
4166 +               ip_ct_gre_keymap_destroy(exp);
4167 +               if (!exp->sibling) {
4168 +                       ip_conntrack_unexpect_related(exp);
4169 +                       continue;
4170 +               }
4171 +
4172 +               DEBUGP("killing conntrack %p\n",
4173 +                       exp->sibling);
4174 +               exp->sibling->proto.gre.timeout = 0;
4175 +               exp->sibling->proto.gre.stream_timeout = 0;
4176 +
4177 +               if (del_timer(&exp->sibling->timeout))
4178 +                       ip_ct_death_by_timeout((unsigned long)exp->sibling);
4179 +       }
4180 +
4181 +       return 0;
4182 +}
4183 +
4184 +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
4185 +static inline int
4186 +exp_gre(struct ip_conntrack *master,
4187 +       u_int32_t seq,
4188 +       u_int16_t callid,
4189 +       u_int16_t peer_callid)
4190 +{
4191 +       struct ip_conntrack_expect exp;
4192 +       struct ip_conntrack_tuple inv_tuple;
4193 +
4194 +       memset(&exp, 0, sizeof(exp));
4195 +       /* tuple in original direction, PNS->PAC */
4196 +       exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4197 +       exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
4198 +       exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4199 +       exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
4200 +       exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
4201 +       exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
4202 +       exp.tuple.dst.protonum = IPPROTO_GRE;
4203 +
4204 +       exp.mask.src.ip = 0xffffffff;
4205 +       exp.mask.src.u.all = 0;
4206 +       exp.mask.dst.u.all = 0;
4207 +       exp.mask.dst.u.gre.key = 0xffffffff;
4208 +       exp.mask.dst.u.gre.version = 0xff;
4209 +       exp.mask.dst.u.gre.protocol = 0xffff;
4210 +       exp.mask.dst.ip = 0xffffffff;
4211 +       exp.mask.dst.protonum = 0xffff;
4212 +                       
4213 +       exp.seq = seq;
4214 +       exp.expectfn = pptp_expectfn;
4215 +
4216 +       exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
4217 +       exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
4218 +
4219 +       DEBUGP("calling expect_related ");
4220 +       DUMP_TUPLE_RAW(&exp.tuple);
4221 +       
4222 +       /* Add GRE keymap entries */
4223 +       if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
4224 +               return 1;
4225 +
4226 +       invert_tuplepr(&inv_tuple, &exp.tuple);
4227 +       if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
4228 +               ip_ct_gre_keymap_destroy(&exp);
4229 +               return 1;
4230 +       }
4231 +       
4232 +       if (ip_conntrack_expect_related(master, &exp) != 0) {
4233 +               ip_ct_gre_keymap_destroy(&exp);
4234 +               DEBUGP("cannot expect_related()\n");
4235 +               return 1;
4236 +       }
4237 +
4238 +       /* tuple in reply direction, PAC->PNS */
4239 +       exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4240 +       exp.tuple.src.u.gre.key = htonl(ntohs(callid));
4241 +       exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4242 +       exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
4243 +
4244 +       DEBUGP("calling expect_related ");
4245 +       DUMP_TUPLE_RAW(&exp.tuple);
4246 +       
4247 +       /* Add GRE keymap entries */
4248 +       ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
4249 +       invert_tuplepr(&inv_tuple, &exp.tuple);
4250 +       ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
4251 +       /* FIXME: cannot handle error correctly, since we need to free
4252 +        * the above keymap :( */
4253 +       
4254 +       if (ip_conntrack_expect_related(master, &exp) != 0) {
4255 +               /* free the second pair of keypmaps */
4256 +               ip_ct_gre_keymap_destroy(&exp);
4257 +               DEBUGP("cannot expect_related():\n");
4258 +               return 1;
4259 +       }
4260 +
4261 +       return 0;
4262 +}
4263 +
4264 +static inline int 
4265 +pptp_inbound_pkt(struct tcphdr *tcph,
4266 +                struct pptp_pkt_hdr *pptph, 
4267 +                size_t datalen,
4268 +                struct ip_conntrack *ct,
4269 +                enum ip_conntrack_info ctinfo)
4270 +{
4271 +       struct PptpControlHeader *ctlh;
4272 +        union pptp_ctrl_union pptpReq;
4273 +       
4274 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4275 +       u_int16_t msg, *cid, *pcid;
4276 +       u_int32_t seq;  
4277 +
4278 +       ctlh = (struct PptpControlHeader *) 
4279 +               ((char *) pptph + sizeof(struct pptp_pkt_hdr));
4280 +       pptpReq.rawreq = (void *) 
4281 +               ((char *) ctlh + sizeof(struct PptpControlHeader));
4282 +
4283 +       msg = ntohs(ctlh->messageType);
4284 +       DEBUGP("inbound control message %s\n", strMName[msg]);
4285 +
4286 +       switch (msg) {
4287 +       case PPTP_START_SESSION_REPLY:
4288 +               /* server confirms new control session */
4289 +               if (info->sstate < PPTP_SESSION_REQUESTED) {
4290 +                       DEBUGP("%s without START_SESS_REQUEST\n",
4291 +                               strMName[msg]);
4292 +                       break;
4293 +               }
4294 +               if (pptpReq.srep->resultCode == PPTP_START_OK)
4295 +                       info->sstate = PPTP_SESSION_CONFIRMED;
4296 +               else 
4297 +                       info->sstate = PPTP_SESSION_ERROR;
4298 +               break;
4299 +
4300 +       case PPTP_STOP_SESSION_REPLY:
4301 +               /* server confirms end of control session */
4302 +               if (info->sstate > PPTP_SESSION_STOPREQ) {
4303 +                       DEBUGP("%s without STOP_SESS_REQUEST\n",
4304 +                               strMName[msg]);
4305 +                       break;
4306 +               }
4307 +               if (pptpReq.strep->resultCode == PPTP_STOP_OK)
4308 +                       info->sstate = PPTP_SESSION_NONE;
4309 +               else
4310 +                       info->sstate = PPTP_SESSION_ERROR;
4311 +               break;
4312 +
4313 +       case PPTP_OUT_CALL_REPLY:
4314 +               /* server accepted call, we now expect GRE frames */
4315 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4316 +                       DEBUGP("%s but no session\n", strMName[msg]);
4317 +                       break;
4318 +               }
4319 +               if (info->cstate != PPTP_CALL_OUT_REQ &&
4320 +                   info->cstate != PPTP_CALL_OUT_CONF) {
4321 +                       DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
4322 +                       break;
4323 +               }
4324 +               if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
4325 +                       info->cstate = PPTP_CALL_NONE;
4326 +                       break;
4327 +               }
4328 +
4329 +               cid = &pptpReq.ocack->callID;
4330 +               pcid = &pptpReq.ocack->peersCallID;
4331 +
4332 +               info->pac_call_id = ntohs(*cid);
4333 +               
4334 +               if (htons(info->pns_call_id) != *pcid) {
4335 +                       DEBUGP("%s for unknown callid %u\n",
4336 +                               strMName[msg], ntohs(*pcid));
4337 +                       break;
4338 +               }
4339 +
4340 +               DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg], 
4341 +                       ntohs(*cid), ntohs(*pcid));
4342 +               
4343 +               info->cstate = PPTP_CALL_OUT_CONF;
4344 +
4345 +               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4346 +               if (exp_gre(ct, seq, *cid, *pcid) != 0)
4347 +                       printk("ip_conntrack_pptp: error during exp_gre\n");
4348 +               break;
4349 +
4350 +       case PPTP_IN_CALL_REQUEST:
4351 +               /* server tells us about incoming call request */
4352 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4353 +                       DEBUGP("%s but no session\n", strMName[msg]);
4354 +                       break;
4355 +               }
4356 +               pcid = &pptpReq.icack->peersCallID;
4357 +               DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4358 +               info->cstate = PPTP_CALL_IN_REQ;
4359 +               info->pac_call_id= ntohs(*pcid);
4360 +               break;
4361 +
4362 +       case PPTP_IN_CALL_CONNECT:
4363 +               /* server tells us about incoming call established */
4364 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4365 +                       DEBUGP("%s but no session\n", strMName[msg]);
4366 +                       break;
4367 +               }
4368 +               if (info->sstate != PPTP_CALL_IN_REP
4369 +                   && info->sstate != PPTP_CALL_IN_CONF) {
4370 +                       DEBUGP("%s but never sent IN_CALL_REPLY\n",
4371 +                               strMName[msg]);
4372 +                       break;
4373 +               }
4374 +
4375 +               pcid = &pptpReq.iccon->peersCallID;
4376 +               cid = &info->pac_call_id;
4377 +
4378 +               if (info->pns_call_id != ntohs(*pcid)) {
4379 +                       DEBUGP("%s for unknown CallID %u\n", 
4380 +                               strMName[msg], ntohs(*cid));
4381 +                       break;
4382 +               }
4383 +
4384 +               DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4385 +               info->cstate = PPTP_CALL_IN_CONF;
4386 +
4387 +               /* we expect a GRE connection from PAC to PNS */
4388 +               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4389 +               if (exp_gre(ct, seq, *cid, *pcid) != 0)
4390 +                       printk("ip_conntrack_pptp: error during exp_gre\n");
4391 +
4392 +               break;
4393 +
4394 +       case PPTP_CALL_DISCONNECT_NOTIFY:
4395 +               /* server confirms disconnect */
4396 +               cid = &pptpReq.disc->callID;
4397 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4398 +               info->cstate = PPTP_CALL_NONE;
4399 +
4400 +               /* untrack this call id, unexpect GRE packets */
4401 +               pptp_timeout_related(ct);
4402 +               break;
4403 +
4404 +       case PPTP_WAN_ERROR_NOTIFY:
4405 +               break;
4406 +
4407 +       case PPTP_ECHO_REQUEST:
4408 +       case PPTP_ECHO_REPLY:
4409 +               /* I don't have to explain these ;) */
4410 +               break;
4411 +       default:
4412 +               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
4413 +                       ? strMName[msg]:strMName[0], msg);
4414 +               break;
4415 +       }
4416 +
4417 +       return NF_ACCEPT;
4418 +
4419 +}
4420 +
4421 +static inline int
4422 +pptp_outbound_pkt(struct tcphdr *tcph,
4423 +                 struct pptp_pkt_hdr *pptph,
4424 +                 size_t datalen,
4425 +                 struct ip_conntrack *ct,
4426 +                 enum ip_conntrack_info ctinfo)
4427 +{
4428 +       struct PptpControlHeader *ctlh;
4429 +        union pptp_ctrl_union pptpReq;
4430 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4431 +       u_int16_t msg, *cid, *pcid;
4432 +
4433 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
4434 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
4435 +
4436 +       msg = ntohs(ctlh->messageType);
4437 +       DEBUGP("outbound control message %s\n", strMName[msg]);
4438 +
4439 +       switch (msg) {
4440 +       case PPTP_START_SESSION_REQUEST:
4441 +               /* client requests for new control session */
4442 +               if (info->sstate != PPTP_SESSION_NONE) {
4443 +                       DEBUGP("%s but we already have one",
4444 +                               strMName[msg]);
4445 +               }
4446 +               info->sstate = PPTP_SESSION_REQUESTED;
4447 +               break;
4448 +       case PPTP_STOP_SESSION_REQUEST:
4449 +               /* client requests end of control session */
4450 +               info->sstate = PPTP_SESSION_STOPREQ;
4451 +               break;
4452 +
4453 +       case PPTP_OUT_CALL_REQUEST:
4454 +               /* client initiating connection to server */
4455 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4456 +                       DEBUGP("%s but no session\n",
4457 +                               strMName[msg]);
4458 +                       break;
4459 +               }
4460 +               info->cstate = PPTP_CALL_OUT_REQ;
4461 +               /* track PNS call id */
4462 +               cid = &pptpReq.ocreq->callID;
4463 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4464 +               info->pns_call_id = ntohs(*cid);
4465 +               break;
4466 +       case PPTP_IN_CALL_REPLY:
4467 +               /* client answers incoming call */
4468 +               if (info->cstate != PPTP_CALL_IN_REQ
4469 +                   && info->cstate != PPTP_CALL_IN_REP) {
4470 +                       DEBUGP("%s without incall_req\n", 
4471 +                               strMName[msg]);
4472 +                       break;
4473 +               }
4474 +               if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
4475 +                       info->cstate = PPTP_CALL_NONE;
4476 +                       break;
4477 +               }
4478 +               pcid = &pptpReq.icack->peersCallID;
4479 +               if (info->pac_call_id != ntohs(*pcid)) {
4480 +                       DEBUGP("%s for unknown call %u\n", 
4481 +                               strMName[msg], ntohs(*pcid));
4482 +                       break;
4483 +               }
4484 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
4485 +               /* part two of the three-way handshake */
4486 +               info->cstate = PPTP_CALL_IN_REP;
4487 +               info->pns_call_id = ntohs(pptpReq.icack->callID);
4488 +               break;
4489 +
4490 +       case PPTP_CALL_CLEAR_REQUEST:
4491 +               /* client requests hangup of call */
4492 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4493 +                       DEBUGP("CLEAR_CALL but no session\n");
4494 +                       break;
4495 +               }
4496 +               /* FUTURE: iterate over all calls and check if
4497 +                * call ID is valid.  We don't do this without newnat,
4498 +                * because we only know about last call */
4499 +               info->cstate = PPTP_CALL_CLEAR_REQ;
4500 +               break;
4501 +       case PPTP_SET_LINK_INFO:
4502 +               break;
4503 +       case PPTP_ECHO_REQUEST:
4504 +       case PPTP_ECHO_REPLY:
4505 +               /* I don't have to explain these ;) */
4506 +               break;
4507 +       default:
4508 +               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? 
4509 +                       strMName[msg]:strMName[0], msg);
4510 +               /* unknown: no need to create GRE masq table entry */
4511 +               break;
4512 +       }
4513 +
4514 +       return NF_ACCEPT;
4515 +}
4516 +
4517 +
4518 +/* track caller id inside control connection, call expect_related */
4519 +static int 
4520 +conntrack_pptp_help(const struct iphdr *iph, size_t len,
4521 +                   struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4522 +
4523 +{
4524 +       struct pptp_pkt_hdr *pptph;
4525 +       
4526 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4527 +       u_int32_t tcplen = len - iph->ihl * 4;
4528 +       u_int32_t datalen = tcplen - tcph->doff * 4;
4529 +       void *datalimit;
4530 +       int dir = CTINFO2DIR(ctinfo);
4531 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4532 +
4533 +       int oldsstate, oldcstate;
4534 +       int ret;
4535 +
4536 +       /* don't do any tracking before tcp handshake complete */
4537 +       if (ctinfo != IP_CT_ESTABLISHED 
4538 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4539 +               DEBUGP("ctinfo = %u, skipping\n", ctinfo);
4540 +               return NF_ACCEPT;
4541 +       }
4542 +       
4543 +       /* not a complete TCP header? */
4544 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4545 +               DEBUGP("tcplen = %u\n", tcplen);
4546 +               return NF_ACCEPT;
4547 +       }
4548 +
4549 +       /* checksum invalid? */
4550 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4551 +                       csum_partial((char *) tcph, tcplen, 0))) {
4552 +               printk(KERN_NOTICE __FILE__ ": bad csum\n");
4553 +               /* W2K PPTP server sends TCP packets with wrong checksum :(( */
4554 +               //return NF_ACCEPT;
4555 +       }
4556 +
4557 +       if (tcph->fin || tcph->rst) {
4558 +               DEBUGP("RST/FIN received, timeouting GRE\n");
4559 +               /* can't do this after real newnat */
4560 +               info->cstate = PPTP_CALL_NONE;
4561 +
4562 +               /* untrack this call id, unexpect GRE packets */
4563 +               pptp_timeout_related(ct);
4564 +       }
4565 +
4566 +
4567 +       pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
4568 +       datalimit = (void *) pptph + datalen;
4569 +
4570 +       /* not a full pptp packet header? */
4571 +       if ((void *) pptph+sizeof(*pptph) >= datalimit) {
4572 +               DEBUGP("no full PPTP header, can't track\n");
4573 +               return NF_ACCEPT;
4574 +       }
4575 +       
4576 +       /* if it's not a control message we can't do anything with it */
4577 +        if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
4578 +           ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
4579 +               DEBUGP("not a control packet\n");
4580 +               return NF_ACCEPT;
4581 +       }
4582 +
4583 +       oldsstate = info->sstate;
4584 +       oldcstate = info->cstate;
4585 +
4586 +       LOCK_BH(&ip_pptp_lock);
4587 +
4588 +       /* FIXME: We just blindly assume that the control connection is always
4589 +        * established from PNS->PAC.  However, RFC makes no guarantee */
4590 +       if (dir == IP_CT_DIR_ORIGINAL)
4591 +               /* client -> server (PNS -> PAC) */
4592 +               ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4593 +       else
4594 +               /* server -> client (PAC -> PNS) */
4595 +               ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4596 +       DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
4597 +               oldsstate, info->sstate, oldcstate, info->cstate);
4598 +       UNLOCK_BH(&ip_pptp_lock);
4599 +
4600 +       return ret;
4601 +}
4602 +
4603 +/* control protocol helper */
4604 +static struct ip_conntrack_helper pptp = { 
4605 +       .list = { NULL, NULL },
4606 +       .name = "pptp", 
4607 +       .flags = IP_CT_HELPER_F_REUSE_EXPECT,
4608 +       .me = THIS_MODULE,
4609 +       .max_expected = 2,
4610 +       .timeout = 0,
4611 +       .tuple = { .src = { .ip = 0, 
4612 +                           .u = { .tcp = { .port =  
4613 +                                   __constant_htons(PPTP_CONTROL_PORT) } } 
4614 +                         }, 
4615 +                  .dst = { .ip = 0, 
4616 +                           .u = { .all = 0 },
4617 +                           .protonum = IPPROTO_TCP
4618 +                         } 
4619 +                },
4620 +       .mask = { .src = { .ip = 0, 
4621 +                          .u = { .tcp = { .port = 0xffff } } 
4622 +                        }, 
4623 +                 .dst = { .ip = 0, 
4624 +                          .u = { .all = 0 },
4625 +                          .protonum = 0xffff 
4626 +                        } 
4627 +               },
4628 +       .help = conntrack_pptp_help
4629 +};
4630 +
4631 +/* ip_conntrack_pptp initialization */
4632 +static int __init init(void)
4633 +{
4634 +       int retcode;
4635 +
4636 +       DEBUGP(__FILE__ ": registering helper\n");
4637 +       if ((retcode = ip_conntrack_helper_register(&pptp))) {
4638 +                printk(KERN_ERR "Unable to register conntrack application "
4639 +                               "helper for pptp: %d\n", retcode);
4640 +               return -EIO;
4641 +       }
4642 +
4643 +       printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
4644 +       return 0;
4645 +}
4646 +
4647 +static void __exit fini(void)
4648 +{
4649 +       ip_conntrack_helper_unregister(&pptp);
4650 +       printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
4651 +}
4652 +
4653 +module_init(init);
4654 +module_exit(fini);
4655 +
4656 +EXPORT_SYMBOL(ip_pptp_lock);
4657 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp_priv.h
4658 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h  1970-01-01 01:00:00.000000000 +0100
4659 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp_priv.h      2003-11-17 09:09:34.000000000 +0100
4660 @@ -0,0 +1,24 @@
4661 +#ifndef _IP_CT_PPTP_PRIV_H
4662 +#define _IP_CT_PPTP_PRIV_H
4663 +
4664 +/* PptpControlMessageType names */
4665 +static const char *strMName[] = {
4666 +       "UNKNOWN_MESSAGE",
4667 +       "START_SESSION_REQUEST",
4668 +       "START_SESSION_REPLY",
4669 +       "STOP_SESSION_REQUEST",
4670 +       "STOP_SESSION_REPLY",
4671 +       "ECHO_REQUEST",
4672 +       "ECHO_REPLY",
4673 +       "OUT_CALL_REQUEST",
4674 +       "OUT_CALL_REPLY",
4675 +       "IN_CALL_REQUEST",
4676 +       "IN_CALL_REPLY",
4677 +       "IN_CALL_CONNECT",
4678 +       "CALL_CLEAR_REQUEST",
4679 +       "CALL_DISCONNECT_NOTIFY",
4680 +       "WAN_ERROR_NOTIFY",
4681 +       "SET_LINK_INFO"
4682 +};
4683 +
4684 +#endif
4685 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_proto_gre.c
4686 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c  1970-01-01 01:00:00.000000000 +0100
4687 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_proto_gre.c      2003-11-17 09:09:34.000000000 +0100
4688 @@ -0,0 +1,343 @@
4689 +/*
4690 + * ip_conntrack_proto_gre.c - Version 1.2 
4691 + *
4692 + * Connection tracking protocol helper module for GRE.
4693 + *
4694 + * GRE is a generic encapsulation protocol, which is generally not very
4695 + * suited for NAT, as it has no protocol-specific part as port numbers.
4696 + *
4697 + * It has an optional key field, which may help us distinguishing two 
4698 + * connections between the same two hosts.
4699 + *
4700 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
4701 + *
4702 + * PPTP is built on top of a modified version of GRE, and has a mandatory
4703 + * field called "CallID", which serves us for the same purpose as the key
4704 + * field in plain GRE.
4705 + *
4706 + * Documentation about PPTP can be found in RFC 2637
4707 + *
4708 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4709 + *
4710 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4711 + *
4712 + */
4713 +
4714 +#include <linux/config.h>
4715 +#include <linux/module.h>
4716 +#include <linux/types.h>
4717 +#include <linux/timer.h>
4718 +#include <linux/netfilter.h>
4719 +#include <linux/ip.h>
4720 +#include <linux/in.h>
4721 +#include <linux/list.h>
4722 +
4723 +#include <linux/netfilter_ipv4/lockhelp.h>
4724 +
4725 +DECLARE_RWLOCK(ip_ct_gre_lock);
4726 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock)
4727 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock)
4728 +
4729 +#include <linux/netfilter_ipv4/listhelp.h>
4730 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4731 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4732 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4733 +
4734 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4735 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4736 +
4737 +MODULE_LICENSE("GPL");
4738 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4739 +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
4740 +
4741 +/* shamelessly stolen from ip_conntrack_proto_udp.c */
4742 +#define GRE_TIMEOUT            (30*HZ)
4743 +#define GRE_STREAM_TIMEOUT     (180*HZ)
4744 +
4745 +#if 0
4746 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4747 +                                      ": " format, ## args)
4748 +#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
4749 +                       NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
4750 +                       NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key), \
4751 +                       (x)->dst.u.gre.version, \
4752 +                       ntohs((x)->dst.u.gre.protocol))
4753 +#else
4754 +#define DEBUGP(x, args...)
4755 +#define DUMP_TUPLE_GRE(x)
4756 +#endif
4757 +                               
4758 +/* GRE KEYMAP HANDLING FUNCTIONS */
4759 +static LIST_HEAD(gre_keymap_list);
4760 +
4761 +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
4762 +                               const struct ip_conntrack_tuple *t)
4763 +{
4764 +       return ((km->tuple.src.ip == t->src.ip) &&
4765 +               (km->tuple.dst.ip == t->dst.ip) &&
4766 +               (km->tuple.dst.protonum == t->dst.protonum) &&
4767 +               (km->tuple.dst.u.all == t->dst.u.all));
4768 +}
4769 +
4770 +/* look up the source key for a given tuple */
4771 +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
4772 +{
4773 +       struct ip_ct_gre_keymap *km;
4774 +       u_int32_t key;
4775 +
4776 +       READ_LOCK(&ip_ct_gre_lock);
4777 +       km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
4778 +                       struct ip_ct_gre_keymap *, t);
4779 +       if (!km) {
4780 +               READ_UNLOCK(&ip_ct_gre_lock);
4781 +               return 0;
4782 +       }
4783 +
4784 +       key = km->tuple.src.u.gre.key;
4785 +       READ_UNLOCK(&ip_ct_gre_lock);
4786 +
4787 +       return key;
4788 +}
4789 +
4790 +/* add a single keymap entry, associate with specified expect */
4791 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
4792 +                        struct ip_conntrack_tuple *t, int reply)
4793 +{
4794 +       struct ip_ct_gre_keymap *km;
4795 +
4796 +       km = kmalloc(sizeof(*km), GFP_ATOMIC);
4797 +       if (!km)
4798 +               return -1;
4799 +
4800 +       /* initializing list head should be sufficient */
4801 +       memset(km, 0, sizeof(*km));
4802 +
4803 +       memcpy(&km->tuple, t, sizeof(*t));
4804 +
4805 +       if (!reply)
4806 +               exp->proto.gre.keymap_orig = km;
4807 +       else
4808 +               exp->proto.gre.keymap_reply = km;
4809 +
4810 +       DEBUGP("adding new entry %p: ", km);
4811 +       DUMP_TUPLE_GRE(&km->tuple);
4812 +
4813 +       WRITE_LOCK(&ip_ct_gre_lock);
4814 +       list_append(&gre_keymap_list, km);
4815 +       WRITE_UNLOCK(&ip_ct_gre_lock);
4816 +
4817 +       return 0;
4818 +}
4819 +
4820 +/* change the tuple of a keymap entry (used by nat helper) */
4821 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
4822 +                            struct ip_conntrack_tuple *t)
4823 +{
4824 +       DEBUGP("changing entry %p to: ", km);
4825 +       DUMP_TUPLE_GRE(t);
4826 +
4827 +       WRITE_LOCK(&ip_ct_gre_lock);
4828 +       memcpy(&km->tuple, t, sizeof(km->tuple));
4829 +       WRITE_UNLOCK(&ip_ct_gre_lock);
4830 +}
4831 +
4832 +/* destroy the keymap entries associated with specified expect */
4833 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
4834 +{
4835 +       DEBUGP("entering for exp %p\n", exp);
4836 +       WRITE_LOCK(&ip_ct_gre_lock);
4837 +       if (exp->proto.gre.keymap_orig) {
4838 +               DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
4839 +               list_del(&exp->proto.gre.keymap_orig->list);
4840 +               kfree(exp->proto.gre.keymap_orig);
4841 +               exp->proto.gre.keymap_orig = NULL;
4842 +       }
4843 +       if (exp->proto.gre.keymap_reply) {
4844 +               DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
4845 +               list_del(&exp->proto.gre.keymap_reply->list);
4846 +               kfree(exp->proto.gre.keymap_reply);
4847 +               exp->proto.gre.keymap_reply = NULL;
4848 +       }
4849 +       WRITE_UNLOCK(&ip_ct_gre_lock);
4850 +}
4851 +
4852 +
4853 +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
4854 +
4855 +/* invert gre part of tuple */
4856 +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
4857 +                           const struct ip_conntrack_tuple *orig)
4858 +{
4859 +       tuple->dst.u.gre.protocol = orig->dst.u.gre.protocol;
4860 +       tuple->dst.u.gre.version = orig->dst.u.gre.version;
4861 +
4862 +       tuple->dst.u.gre.key = orig->src.u.gre.key;
4863 +       tuple->src.u.gre.key = orig->dst.u.gre.key;
4864 +
4865 +       return 1;
4866 +}
4867 +
4868 +/* gre hdr info to tuple */
4869 +static int gre_pkt_to_tuple(const void *datah, size_t datalen,
4870 +                           struct ip_conntrack_tuple *tuple)
4871 +{
4872 +       struct gre_hdr *grehdr = (struct gre_hdr *) datah;
4873 +       struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
4874 +       u_int32_t srckey;
4875 +
4876 +       /* core guarantees 8 protocol bytes, no need for size check */
4877 +
4878 +       tuple->dst.u.gre.version = grehdr->version; 
4879 +       tuple->dst.u.gre.protocol = grehdr->protocol;
4880 +
4881 +       switch (grehdr->version) {
4882 +               case GRE_VERSION_1701:
4883 +                       if (!grehdr->key) {
4884 +                               DEBUGP("Can't track GRE without key\n");
4885 +                               return 0;
4886 +                       }
4887 +                       tuple->dst.u.gre.key = *(gre_key(grehdr));
4888 +                       break;
4889 +
4890 +               case GRE_VERSION_PPTP:
4891 +                       if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
4892 +                               DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
4893 +                               return 0;
4894 +                       }
4895 +                       tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
4896 +                       break;
4897 +
4898 +               default:
4899 +                       printk(KERN_WARNING "unknown GRE version %hu\n",
4900 +                               tuple->dst.u.gre.version);
4901 +                       return 0;
4902 +       }
4903 +
4904 +       srckey = gre_keymap_lookup(tuple);
4905 +
4906 +#if 0
4907 +       DEBUGP("found src key %x for tuple ", ntohl(srckey));
4908 +       DUMP_TUPLE_GRE(tuple);
4909 +#endif
4910 +       tuple->src.u.gre.key = srckey;
4911 +
4912 +       return 1;
4913 +}
4914 +
4915 +/* print gre part of tuple */
4916 +static unsigned int gre_print_tuple(char *buffer,
4917 +                                   const struct ip_conntrack_tuple *tuple)
4918 +{
4919 +       return sprintf(buffer, "version=%d protocol=0x%04x srckey=0x%x dstkey=0x%x ", 
4920 +                       tuple->dst.u.gre.version,
4921 +                       ntohs(tuple->dst.u.gre.protocol),
4922 +                       ntohl(tuple->src.u.gre.key),
4923 +                       ntohl(tuple->dst.u.gre.key));
4924 +}
4925 +
4926 +/* print private data for conntrack */
4927 +static unsigned int gre_print_conntrack(char *buffer,
4928 +                                       const struct ip_conntrack *ct)
4929 +{
4930 +       return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
4931 +                      (ct->proto.gre.timeout / HZ),
4932 +                      (ct->proto.gre.stream_timeout / HZ));
4933 +}
4934 +
4935 +/* Returns verdict for packet, and may modify conntrack */
4936 +static int gre_packet(struct ip_conntrack *ct,
4937 +                     struct iphdr *iph, size_t len,
4938 +                     enum ip_conntrack_info conntrackinfo)
4939 +{
4940 +       /* If we've seen traffic both ways, this is a GRE connection.
4941 +        * Extend timeout. */
4942 +       if (ct->status & IPS_SEEN_REPLY) {
4943 +               ip_ct_refresh(ct, ct->proto.gre.stream_timeout);
4944 +               /* Also, more likely to be important, and not a probe. */
4945 +               set_bit(IPS_ASSURED_BIT, &ct->status);
4946 +       } else
4947 +               ip_ct_refresh(ct, ct->proto.gre.timeout);
4948 +       
4949 +       return NF_ACCEPT;
4950 +}
4951 +
4952 +/* Called when a new connection for this protocol found. */
4953 +static int gre_new(struct ip_conntrack *ct,
4954 +                  struct iphdr *iph, size_t len)
4955 +{ 
4956 +       DEBUGP(": ");
4957 +       DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4958 +
4959 +       /* initialize to sane value.  Ideally a conntrack helper
4960 +        * (e.g. in case of pptp) is increasing them */
4961 +       ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
4962 +       ct->proto.gre.timeout = GRE_TIMEOUT;
4963 +
4964 +       return 1;
4965 +}
4966 +
4967 +/* Called when a conntrack entry has already been removed from the hashes
4968 + * and is about to be deleted from memory */
4969 +static void gre_destroy(struct ip_conntrack *ct)
4970 +{
4971 +       struct ip_conntrack_expect *master = ct->master;
4972 +
4973 +       DEBUGP(" entering\n");
4974 +
4975 +       if (!master) {
4976 +               DEBUGP("no master exp for ct %p\n", ct);
4977 +               return;
4978 +       }
4979 +
4980 +       ip_ct_gre_keymap_destroy(master);
4981 +}
4982 +
4983 +/* protocol helper struct */
4984 +static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
4985 +                                           "gre", 
4986 +                                           gre_pkt_to_tuple,
4987 +                                           gre_invert_tuple,
4988 +                                           gre_print_tuple,
4989 +                                           gre_print_conntrack,
4990 +                                           gre_packet,
4991 +                                           gre_new,
4992 +                                           gre_destroy,
4993 +                                           NULL,
4994 +                                           THIS_MODULE };
4995 +
4996 +/* ip_conntrack_proto_gre initialization */
4997 +static int __init init(void)
4998 +{
4999 +       int retcode;
5000 +
5001 +       if ((retcode = ip_conntrack_protocol_register(&gre))) {
5002 +                printk(KERN_ERR "Unable to register conntrack protocol "
5003 +                               "helper for gre: %d\n", retcode);
5004 +               return -EIO;
5005 +       }
5006 +
5007 +       return 0;
5008 +}
5009 +
5010 +static void __exit fini(void)
5011 +{
5012 +       struct list_head *pos, *n;
5013 +
5014 +       /* delete all keymap entries */
5015 +       WRITE_LOCK(&ip_ct_gre_lock);
5016 +       list_for_each_safe(pos, n, &gre_keymap_list) {
5017 +               DEBUGP("deleting keymap %p at module unload time\n", pos);
5018 +               list_del(pos);
5019 +               kfree(pos);
5020 +       }
5021 +       WRITE_UNLOCK(&ip_ct_gre_lock);
5022 +
5023 +       ip_conntrack_protocol_unregister(&gre); 
5024 +}
5025 +
5026 +EXPORT_SYMBOL(ip_ct_gre_keymap_add);
5027 +EXPORT_SYMBOL(ip_ct_gre_keymap_change);
5028 +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
5029 +
5030 +module_init(init);
5031 +module_exit(fini);
5032 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_quake3.c
5033 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_quake3.c     1970-01-01 01:00:00.000000000 +0100
5034 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_quake3.c 2003-12-10 23:14:06.244005464 +0100
5035 @@ -0,0 +1,156 @@
5036 +/* Quake3 extension for IP connection tracking
5037 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5038 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5039 + *
5040 + * ip_conntrack_quake3.c v0.04 2002-08-31
5041 + *
5042 + *      This program is free software; you can redistribute it and/or
5043 + *      modify it under the terms of the GNU General Public License
5044 + *      as published by the Free Software Foundation; either version
5045 + *      2 of the License, or (at your option) any later version.
5046 + *
5047 + *      Module load syntax:
5048 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5049 + *
5050 + *      please give the ports of all Quake3 master servers You wish to 
5051 + *      connect to. If you don't specify ports, the default will be UDP 
5052 + *      port 27950.
5053 + *
5054 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5055 + */
5056 +
5057 +#include <linux/module.h>
5058 +#include <linux/ip.h>
5059 +#include <linux/udp.h>
5060 +
5061 +#include <linux/netfilter.h>
5062 +#include <linux/netfilter_ipv4/ip_tables.h>
5063 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5064 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5065 +
5066 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5067 +
5068 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5069 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5070 +MODULE_LICENSE("GPL");
5071 +
5072 +#define MAX_PORTS 8
5073 +static int ports[MAX_PORTS];
5074 +static int ports_c = 0;
5075 +#ifdef MODULE_PARM
5076 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5077 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5078 +#endif
5079 +
5080 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5081 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5082 +#if 0 
5083 +#define DEBUGP printk
5084 +#else
5085 +#define DEBUGP(format, args...)
5086 +#endif
5087 +
5088 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5089 +
5090 +static int quake3_help(const struct iphdr *iph, size_t len,
5091 +       struct ip_conntrack *ct,
5092 +       enum ip_conntrack_info ctinfo)
5093 +{
5094 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5095 +       int dir = CTINFO2DIR(ctinfo);
5096 +       struct ip_conntrack_expect exp;
5097 +       int i;
5098 +       
5099 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5100 +       if (ctinfo != IP_CT_ESTABLISHED
5101 +           && ctinfo != IP_CT_IS_REPLY) {
5102 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5103 +               return NF_ACCEPT;
5104 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5105 +       
5106 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5107 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5108 +                   i+6 < ntohs(udph->len);
5109 +                   i+=7) {
5110 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5111 +                              i, ntohs(udph->len),
5112 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
5113 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5114 +
5115 +                       memset(&exp, 0, sizeof(exp));
5116 +
5117 +                       exp.tuple = ((struct ip_conntrack_tuple)
5118 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5119 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
5120 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
5121 +                                        IPPROTO_UDP } }
5122 +                                   );
5123 +                       exp.mask  = ((struct ip_conntrack_tuple)
5124 +                                    { { 0xFFFFFFFF, { 0 } },
5125 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5126 +                       exp.expectfn = NULL;
5127 +
5128 +                       ip_conntrack_expect_related(ct, &exp);
5129 +               }
5130 +
5131 +       }
5132 +       
5133 +       return(NF_ACCEPT);
5134 +}
5135 +
5136 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5137 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
5138 +
5139 +static void fini(void)
5140 +{
5141 +       int i;
5142 +
5143 +       for(i = 0 ; (i < ports_c); i++) {
5144 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5145 +                                       ports[i]);
5146 +               ip_conntrack_helper_unregister(&quake3[i]);
5147 +       } 
5148 +}
5149 +
5150 +static int __init init(void)
5151 +{
5152 +       int i, ret;
5153 +       char *tmpname;
5154 +
5155 +       if(!ports[0])
5156 +               ports[0]=QUAKE3_MASTER_PORT;
5157 +
5158 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5159 +               /* Create helper structure */
5160 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5161 +
5162 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5163 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5164 +               quake3[i].mask.dst.protonum = 0xFFFF;
5165 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
5166 +               quake3[i].help = quake3_help;
5167 +               quake3[i].me = THIS_MODULE;
5168 +
5169 +               tmpname = &quake3_names[i][0];
5170 +               if (ports[i] == QUAKE3_MASTER_PORT)
5171 +                       sprintf(tmpname, "quake3");
5172 +               else
5173 +                       sprintf(tmpname, "quake3-%d", i);
5174 +               quake3[i].name = tmpname;
5175 +               
5176 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5177 +                      ports[i]);
5178 +
5179 +               ret=ip_conntrack_helper_register(&quake3[i]);
5180 +               if(ret) {
5181 +                       fini();
5182 +                       return(ret);
5183 +               }
5184 +               ports_c++;
5185 +       }
5186 +
5187 +       return(0);
5188 +}
5189 +
5190 +module_init(init);
5191 +module_exit(fini);
5192 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
5193 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c    1970-01-01 01:00:00.000000000 +0100
5194 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c        2003-12-10 23:14:10.153411144 +0100
5195 @@ -0,0 +1,508 @@
5196 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
5197 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5198 + *     - original rpc tracking module
5199 + *     - "recent" connection handling for kernel 2.3+ netfilter
5200 + *
5201 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5202 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5203 + *
5204 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5205 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
5206 + *     - extended matching to support filtering on procedures
5207 + *
5208 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
5209 + *
5210 + *     This program is free software; you can redistribute it and/or
5211 + *     modify it under the terms of the GNU General Public License
5212 + *     as published by the Free Software Foundation; either version
5213 + *     2 of the License, or (at your option) any later version.
5214 + **
5215 + *     Module load syntax:
5216 + *     insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
5217 + *
5218 + *     Please give the ports of all RPC servers you wish to connect to.
5219 + *     If you don't specify ports, the default will be port 111.
5220 + **
5221 + *     Note to all:
5222 + *
5223 + *     RPCs should not be exposed to the internet - ask the Pentagon;
5224 + *
5225 + *       "The unidentified crackers pleaded guilty in July to charges
5226 + *        of juvenile delinquency stemming from a string of Pentagon
5227 + *        network intrusions in February.
5228 + *
5229 + *        The youths, going by the names TooShort and Makaveli, used
5230 + *        a common server security hole to break in, according to
5231 + *        Dane Jasper, owner of the California Internet service
5232 + *        provider, Sonic. They used the hole, known as the 'statd'
5233 + *        exploit, to attempt more than 800 break-ins, Jasper said."
5234 + *
5235 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5236 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
5237 + **
5238 + */
5239 +
5240 +#include <linux/module.h>
5241 +#include <linux/netfilter.h>
5242 +#include <linux/ip.h>
5243 +#include <net/checksum.h>
5244 +#include <net/tcp.h>
5245 +
5246 +#include <asm/param.h>
5247 +#include <linux/sched.h>
5248 +#include <linux/timer.h>
5249 +#include <linux/stddef.h>
5250 +#include <linux/list.h>
5251 +
5252 +#include <linux/netfilter_ipv4/lockhelp.h>
5253 +#include <linux/netfilter_ipv4/ip_tables.h>
5254 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5255 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5256 +
5257 +#define MAX_PORTS 8
5258 +static int ports[MAX_PORTS];
5259 +static int ports_n_c = 0;
5260 +
5261 +#ifdef MODULE_PARM
5262 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5263 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5264 +#endif
5265 +
5266 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5267 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
5268 +MODULE_LICENSE("GPL");
5269 +
5270 +#if 0
5271 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
5272 +                                       format, ## args)
5273 +#else
5274 +#define DEBUGP(format, args...)
5275 +#endif
5276 +
5277 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
5278 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
5279 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
5280 +#include <linux/netfilter_ipv4/listhelp.h>
5281 +
5282 +/* For future conections RPC, using client's cache bindings
5283 + * I'll use ip_conntrack_lock to lock these lists         */
5284 +
5285 +LIST_HEAD(request_p_list_tcp);
5286 +
5287 +
5288 +static void delete_request_p(unsigned long request_p_ul) 
5289 +{
5290 +       struct request_p *p = (void *)request_p_ul;
5291 +       
5292 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5293 +       LIST_DELETE(&request_p_list_tcp, p);
5294 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5295 +       kfree(p);
5296 +       return;
5297 +}
5298 +
5299 +
5300 +static void req_cl(struct request_p * r)
5301 +{
5302 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5303 +       del_timer(&r->timeout);
5304 +       LIST_DELETE(&request_p_list_tcp, r);
5305 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5306 +       kfree(r);
5307 +       return;
5308 +}
5309 +
5310 +
5311 +static void clean_request(struct list_head *list)
5312 +{
5313 +       struct list_head *first = list->prev;
5314 +       struct list_head *temp = list->next;
5315 +       struct list_head *aux;
5316 +
5317 +       if (list_empty(list))
5318 +               return;
5319 +
5320 +       while (first != temp) {
5321 +               aux = temp->next;
5322 +               req_cl((struct request_p *)temp);
5323 +               temp = aux;     
5324 +       }
5325 +       req_cl((struct request_p *)temp);
5326 +       return;
5327 +}
5328 +
5329 +
5330 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5331 +                    u_int16_t port)
5332 +{
5333 +       struct request_p *req_p;
5334 +       
5335 +       /* Verifies if entry already exists */
5336 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5337 +       req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5338 +               struct request_p *, xid, ip, port);
5339 +
5340 +       if (req_p) {
5341 +               /* Refresh timeout */
5342 +               if (del_timer(&req_p->timeout)) {
5343 +                       req_p->timeout.expires = jiffies + EXP;
5344 +                       add_timer(&req_p->timeout);     
5345 +               } 
5346 +               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5347 +               return; 
5348 +
5349 +       }
5350 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5351 +       
5352 +       /* Allocate new request_p */
5353 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5354 +       if (!req_p) {
5355 +               DEBUGP("can't allocate request_p\n");
5356 +               return;                 
5357 +       }
5358 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
5359 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5360 +                       NULL }}); 
5361 +      
5362 +       /* Initialize timer */
5363 +       init_timer(&req_p->timeout);
5364 +       req_p->timeout.function = delete_request_p;
5365 +       add_timer(&req_p->timeout); 
5366 +
5367 +       /* Put in list */
5368 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5369 +       list_prepend(&request_p_list_tcp, req_p);
5370 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
5371 +       return; 
5372 +
5373 +}
5374 +
5375 +
5376 +static int check_rpc_packet(const u_int32_t *data,
5377 +                       int dir, struct ip_conntrack *ct,
5378 +                       struct list_head request_p_list)
5379 +{
5380 +       struct request_p *req_p;
5381 +       u_int32_t xid;
5382 +       struct ip_conntrack_expect expect, *exp = &expect;
5383 +
5384 +        /* Translstion's buffer for XDR */
5385 +        u_int16_t port_buf;
5386 +
5387 +
5388 +       /* Get XID */
5389 +       xid = *data;
5390 +
5391 +       /* This does sanity checking on RPC payloads,
5392 +        * and permits only the RPC "get port" (3)
5393 +        * in authorised procedures in client
5394 +        * communications with the portmapper.
5395 +        */
5396 +
5397 +       /* perform direction dependant RPC work */
5398 +       if (dir == IP_CT_DIR_ORIGINAL) {
5399 +
5400 +               data += 5;
5401 +
5402 +               /* Get RPC requestor */
5403 +               if (IXDR_GET_INT32(data) != 3) {
5404 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5405 +                       return NF_ACCEPT;
5406 +               }
5407 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5408 +
5409 +               data++;
5410 +
5411 +               /* Jump Credentials and Verfifier */
5412 +               data += IXDR_GET_INT32(data) + 2;
5413 +               data += IXDR_GET_INT32(data) + 2;
5414 +
5415 +               /* Get RPC procedure */
5416 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5417 +                       (unsigned int)IXDR_GET_INT32(data));
5418 +
5419 +               /* Get RPC protocol and store against client parameters */
5420 +               data = data + 2;
5421 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5422 +                               ct->tuplehash[dir].tuple.src.u.all);
5423 +
5424 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5425 +                       xid, IXDR_GET_INT32(data),
5426 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5427 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
5428 +
5429 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
5430 +                       (unsigned int)IXDR_GET_INT32(data));
5431 +
5432 +       } else {
5433 +
5434 +               /* Check for returning packet's stored counterpart */
5435 +               req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5436 +                                 struct request_p *, xid,
5437 +                                 ct->tuplehash[!dir].tuple.src.ip,
5438 +                                 ct->tuplehash[!dir].tuple.src.u.all);
5439 +
5440 +               /* Drop unexpected packets */
5441 +               if (!req_p) {
5442 +                       DEBUGP("packet is not expected. [skip]\n");
5443 +                       return NF_ACCEPT;
5444 +               }
5445 +
5446 +               /* Verifies if packet is really an RPC reply packet */
5447 +               data = data++;
5448 +               if (IXDR_GET_INT32(data) != 1) {
5449 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
5450 +                       return NF_ACCEPT;
5451 +               }
5452 +
5453 +               /* Is status accept? */
5454 +               data++;
5455 +               if (IXDR_GET_INT32(data)) {
5456 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
5457 +                       return NF_ACCEPT;
5458 +               }
5459 +
5460 +               /* Get Verifier length. Jump verifier */
5461 +               data++;
5462 +               data = data + IXDR_GET_INT32(data) + 2;
5463 +
5464 +               /* Is accpet status "success"? */
5465 +               if (IXDR_GET_INT32(data)) {
5466 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5467 +                       return NF_ACCEPT;
5468 +               }
5469 +
5470 +               /* Get server port number */      
5471 +               data++;
5472 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
5473 +
5474 +               /* If a packet has made it this far then it deserves an
5475 +                * expectation ...  if port == 0, then this service is 
5476 +                * not going to be registered.
5477 +                */
5478 +               if (port_buf) {
5479 +                       DEBUGP("port found: %u\n", port_buf);
5480 +
5481 +                       memset(&expect, 0, sizeof(expect));
5482 +
5483 +                       /* Watch out, Radioactive-Man! */
5484 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5485 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5486 +                       exp->mask.src.ip = 0xffffffff;
5487 +                       exp->mask.dst.ip = 0xffffffff;
5488 +
5489 +                       switch (req_p->proto) {
5490 +                               case IPPROTO_UDP:
5491 +                                       exp->tuple.src.u.udp.port = 0;
5492 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
5493 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
5494 +                                       exp->mask.src.u.udp.port = 0;
5495 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
5496 +                                       exp->mask.dst.protonum = 0xffff;
5497 +                                       break;
5498 +
5499 +                               case IPPROTO_TCP:
5500 +                                       exp->tuple.src.u.tcp.port = 0;
5501 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
5502 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
5503 +                                       exp->mask.src.u.tcp.port = 0;
5504 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
5505 +                                       exp->mask.dst.protonum = 0xffff;
5506 +                                       break;
5507 +                       }
5508 +                       exp->expectfn = NULL;
5509 +
5510 +                       ip_conntrack_expect_related(ct, &expect);
5511 +
5512 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
5513 +                               NIPQUAD(exp->tuple.src.ip),
5514 +                               NIPQUAD(exp->tuple.dst.ip),
5515 +                               port_buf, req_p->proto);
5516 +
5517 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
5518 +                               NIPQUAD(exp->mask.src.ip),
5519 +                               NIPQUAD(exp->mask.dst.ip),
5520 +                               exp->mask.dst.protonum);
5521 +
5522 +               }
5523 +
5524 +               req_cl(req_p);
5525 +
5526 +               DEBUGP("packet evaluated. [expect]\n");
5527 +               return NF_ACCEPT;
5528 +       }
5529 +
5530 +       return NF_ACCEPT;
5531 +
5532 +}
5533 +
5534 +
5535 +/* RPC TCP helper */
5536 +static int help(const struct iphdr *iph, size_t len,
5537 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5538 +{
5539 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5540 +       const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
5541 +       size_t tcplen = len - iph->ihl * 4;
5542 +
5543 +       int dir = CTINFO2DIR(ctinfo);
5544 +       int crp_ret;
5545 +
5546 +
5547 +       DEBUGP("new packet to evaluate ..\n");
5548 +
5549 +       /* This works for packets like handshake packets, ignore */
5550 +       if (len == ((tcph->doff + iph->ihl) * 4)) {
5551 +               DEBUGP("packet has no data (may still be handshaking). [skip]\n");
5552 +               return NF_ACCEPT;
5553 +       }
5554 +
5555 +       /* Until there's been traffic both ways, don't look in packets. */
5556 +       if (ctinfo != IP_CT_ESTABLISHED
5557 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5558 +               DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
5559 +               DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
5560 +               DEBUGP("packet is not yet part of a two way stream. [skip]\n");
5561 +               return NF_ACCEPT;
5562 +       }
5563 +
5564 +       /* Not whole TCP header? */
5565 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5566 +               DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
5567 +               DEBUGP("packet does not contain a complete TCP header. [skip]\n");
5568 +               return NF_ACCEPT;
5569 +       }
5570 +
5571 +       /* FIXME: Source route IP option packets --RR */
5572 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5573 +                        csum_partial((char *) tcph, tcplen, 0))) {
5574 +               DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5575 +                    tcph, tcplen, NIPQUAD(iph->saddr),
5576 +                    NIPQUAD(iph->daddr));
5577 +               DEBUGP("[note: failure to get past this error may indicate source routing]\n");
5578 +               DEBUGP("packet contains a bad checksum. [skip]\n");
5579 +               return NF_ACCEPT;
5580 +       }
5581 +
5582 +       /* perform direction dependant protocol work */
5583 +       if (dir == IP_CT_DIR_ORIGINAL) {
5584 +
5585 +               DEBUGP("packet is from the initiator. [cont]\n");
5586 +
5587 +               /* Tests if packet len is ok */
5588 +               if ((tcplen - (tcph->doff * 4)) != 60) {
5589 +                       DEBUGP("packet length is not correct. [skip]\n");
5590 +                       return NF_ACCEPT;
5591 +               }
5592 +
5593 +       } else {
5594 +
5595 +               DEBUGP("packet is from the receiver. [cont]\n");
5596 +
5597 +               /* Tests if packet len is ok */
5598 +               if ((tcplen - (tcph->doff * 4)) != 32) {
5599 +                       DEBUGP("packet length is not correct. [skip]\n");
5600 +                       return NF_ACCEPT;
5601 +               }
5602 +       }
5603 +
5604 +       /* Get to the data */
5605 +       data++;
5606 +
5607 +       /* Check the RPC data */
5608 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
5609 +
5610 +       return crp_ret;
5611 +
5612 +}
5613 +
5614 +
5615 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
5616 +
5617 +static void fini(void);
5618 +
5619 +
5620 +static int __init init(void)
5621 +{
5622 +       int port, ret;
5623 +       static char name[10];
5624 +
5625 +
5626 +       /* If no port given, default to standard RPC port */
5627 +       if (ports[0] == 0)
5628 +               ports[0] = RPC_PORT;
5629 +
5630 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5631 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5632 +
5633 +                if (ports[port] == RPC_PORT)
5634 +                        sprintf(name, "rpc");
5635 +                else
5636 +                        sprintf(name, "rpc-%d", port);
5637 +
5638 +               rpc_helpers[port].name = name;
5639 +               rpc_helpers[port].me = THIS_MODULE;
5640 +               rpc_helpers[port].max_expected = 1;
5641 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5642 +               rpc_helpers[port].timeout = 0;
5643 +
5644 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5645 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
5646 +
5647 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
5648 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
5649 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
5650 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
5651 +
5652 +               rpc_helpers[port].help = help;
5653 +
5654 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5655 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5656 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
5657 +                       ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
5658 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
5659 +                       ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
5660 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5661 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
5662 +                       ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
5663 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
5664 +                       ntohs(rpc_helpers[port].mask.src.u.tcp.port));
5665 +
5666 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
5667 +
5668 +               if (ret) {
5669 +                       printk("ERROR registering port %d\n",
5670 +                               ports[port]);
5671 +                       fini();
5672 +                       return -EBUSY;
5673 +               }
5674 +               ports_n_c++;
5675 +       }
5676 +       return 0;
5677 +}
5678 +
5679 +
5680 +/* This function is intentionally _NOT_ defined as __exit, because 
5681 + * it is needed by the init function */
5682 +static void fini(void)
5683 +{
5684 +       int port;
5685 +
5686 +       DEBUGP("cleaning request list\n");
5687 +       clean_request(&request_p_list_tcp);
5688 +
5689 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
5690 +               DEBUGP("unregistering port %d\n", ports[port]);
5691 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
5692 +       }
5693 +}
5694 +
5695 +
5696 +module_init(init);
5697 +module_exit(fini);
5698 +
5699 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
5700 +EXPORT_SYMBOL(request_p_list_tcp);
5701 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
5702 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
5703 +
5704 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
5705 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c    1970-01-01 01:00:00.000000000 +0100
5706 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_udp.c        2003-12-10 23:14:10.154410992 +0100
5707 @@ -0,0 +1,503 @@
5708 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
5709 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5710 + *     - original rpc tracking module
5711 + *     - "recent" connection handling for kernel 2.3+ netfilter
5712 + *
5713 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5714 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5715 + *
5716 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5717 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
5718 + *     - extended matching to support filtering on procedures
5719 + *
5720 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
5721 + *
5722 + *     This program is free software; you can redistribute it and/or
5723 + *     modify it under the terms of the GNU General Public License
5724 + *     as published by the Free Software Foundation; either version
5725 + *     2 of the License, or (at your option) any later version.
5726 + **
5727 + *     Module load syntax:
5728 + *     insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
5729 + *
5730 + *     Please give the ports of all RPC servers you wish to connect to.
5731 + *     If you don't specify ports, the default will be port 111.
5732 + **
5733 + *     Note to all:
5734 + *
5735 + *     RPCs should not be exposed to the internet - ask the Pentagon;
5736 + *
5737 + *       "The unidentified crackers pleaded guilty in July to charges
5738 + *        of juvenile delinquency stemming from a string of Pentagon
5739 + *        network intrusions in February.
5740 + *
5741 + *        The youths, going by the names TooShort and Makaveli, used
5742 + *        a common server security hole to break in, according to
5743 + *        Dane Jasper, owner of the California Internet service
5744 + *        provider, Sonic. They used the hole, known as the 'statd'
5745 + *        exploit, to attempt more than 800 break-ins, Jasper said."
5746 + *
5747 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5748 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
5749 + **
5750 + */
5751 +
5752 +#include <linux/module.h>
5753 +#include <linux/netfilter.h>
5754 +#include <linux/ip.h>
5755 +#include <net/checksum.h>
5756 +#include <net/udp.h>
5757 +
5758 +#include <asm/param.h>
5759 +#include <linux/sched.h>
5760 +#include <linux/timer.h>
5761 +#include <linux/stddef.h>
5762 +#include <linux/list.h>
5763 +
5764 +#include <linux/netfilter_ipv4/lockhelp.h>
5765 +#include <linux/netfilter_ipv4/ip_tables.h>
5766 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5767 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5768 +
5769 +#define MAX_PORTS 8
5770 +static int ports[MAX_PORTS];
5771 +static int ports_n_c = 0;
5772 +
5773 +#ifdef MODULE_PARM
5774 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5775 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5776 +#endif
5777 +
5778 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5779 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
5780 +MODULE_LICENSE("GPL");
5781 +
5782 +#if 0
5783 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
5784 +                                       format, ## args)
5785 +#else
5786 +#define DEBUGP(format, args...)
5787 +#endif
5788 +
5789 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
5790 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
5791 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
5792 +#include <linux/netfilter_ipv4/listhelp.h>
5793 +
5794 +/* For future conections RPC, using client's cache bindings
5795 + * I'll use ip_conntrack_lock to lock these lists           */
5796 +
5797 +LIST_HEAD(request_p_list_udp);
5798 +
5799 +
5800 +static void delete_request_p(unsigned long request_p_ul)
5801 +{
5802 +       struct request_p *p = (void *)request_p_ul;
5803 +       
5804 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5805 +       LIST_DELETE(&request_p_list_udp, p);
5806 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
5807 +       kfree(p);
5808 +       return;
5809 +}
5810 +
5811 +
5812 +static void req_cl(struct request_p * r)
5813 +{
5814 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5815 +       del_timer(&r->timeout);
5816 +       LIST_DELETE(&request_p_list_udp, r);
5817 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
5818 +       kfree(r);
5819 +       return;
5820 +}
5821 +
5822 +
5823 +static void clean_request(struct list_head *list)
5824 +{
5825 +       struct list_head *first = list->prev;
5826 +       struct list_head *temp = list->next;
5827 +       struct list_head *aux;
5828 +
5829 +       if (list_empty(list))
5830 +               return;
5831 +
5832 +       while (first != temp) {
5833 +               aux = temp->next;
5834 +               req_cl((struct request_p *)temp);
5835 +               temp = aux;     
5836 +       }
5837 +       req_cl((struct request_p *)temp);
5838 +       return;
5839 +}
5840 +
5841 +
5842 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5843 +                    u_int16_t port)
5844 +{
5845 +       struct request_p *req_p;
5846 +        
5847 +       /* Verifies if entry already exists */
5848 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5849 +       req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5850 +               struct request_p *, xid, ip, port);
5851 +
5852 +       if (req_p) {
5853 +               /* Refresh timeout */
5854 +               if (del_timer(&req_p->timeout)) {
5855 +                       req_p->timeout.expires = jiffies + EXP;
5856 +                       add_timer(&req_p->timeout);     
5857 +               } 
5858 +               WRITE_UNLOCK(&ipct_rpc_udp_lock);
5859 +               return; 
5860 +
5861 +       }
5862 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
5863 +       
5864 +       /* Allocate new request_p */
5865 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5866 +       if (!req_p) {
5867 +               DEBUGP("can't allocate request_p\n");
5868 +               return;                 
5869 +       }
5870 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
5871 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5872 +                       NULL }}); 
5873 +      
5874 +       /* Initialize timer */
5875 +       init_timer(&req_p->timeout);
5876 +       req_p->timeout.function = delete_request_p;
5877 +       add_timer(&req_p->timeout); 
5878 +
5879 +       /* Put in list */
5880 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5881 +       list_prepend(&request_p_list_udp, req_p);
5882 +       WRITE_UNLOCK(&ipct_rpc_udp_lock); 
5883 +       return; 
5884 +
5885 +}
5886 +
5887 +
5888 +static int check_rpc_packet(const u_int32_t *data,
5889 +                       int dir, struct ip_conntrack *ct,
5890 +                       struct list_head request_p_list)
5891 +{
5892 +       struct request_p *req_p;
5893 +       u_int32_t xid;
5894 +       struct ip_conntrack_expect expect, *exp = &expect;
5895 +
5896 +       /* Translstion's buffer for XDR */
5897 +       u_int16_t port_buf;
5898 +
5899 +
5900 +       /* Get XID */
5901 +       xid = *data;
5902 +
5903 +       /* This does sanity checking on RPC payloads,
5904 +        * and permits only the RPC "get port" (3)
5905 +        * in authorised procedures in client
5906 +        * communications with the portmapper.
5907 +        */
5908 +
5909 +       /* perform direction dependant RPC work */
5910 +       if (dir == IP_CT_DIR_ORIGINAL) {
5911 +
5912 +               data += 5;
5913 +
5914 +               /* Get RPC requestor */
5915 +               if (IXDR_GET_INT32(data) != 3) {
5916 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5917 +                       return NF_ACCEPT;
5918 +               }
5919 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5920 +
5921 +               data++;
5922 +
5923 +               /* Jump Credentials and Verfifier */
5924 +               data = data + IXDR_GET_INT32(data) + 2;
5925 +               data = data + IXDR_GET_INT32(data) + 2;
5926 +
5927 +               /* Get RPC procedure */
5928 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5929 +                       (unsigned int)IXDR_GET_INT32(data));
5930 +
5931 +               /* Get RPC protocol and store against client parameters */
5932 +               data = data + 2;
5933 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5934 +                               ct->tuplehash[dir].tuple.src.u.all);
5935 +
5936 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5937 +                       xid, IXDR_GET_INT32(data),
5938 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5939 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
5940 +
5941 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
5942 +                       (unsigned int)IXDR_GET_INT32(data));
5943 +
5944 +       } else {
5945 +
5946 +               /* Check for returning packet's stored counterpart */
5947 +               req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5948 +                                 struct request_p *, xid,
5949 +                                 ct->tuplehash[!dir].tuple.src.ip,
5950 +                                 ct->tuplehash[!dir].tuple.src.u.all);
5951 +
5952 +               /* Drop unexpected packets */
5953 +               if (!req_p) {
5954 +                       DEBUGP("packet is not expected. [skip]\n");
5955 +                       return NF_ACCEPT;
5956 +               }
5957 +
5958 +               /* Verifies if packet is really an RPC reply packet */
5959 +               data = data++;
5960 +               if (IXDR_GET_INT32(data) != 1) {
5961 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
5962 +                       return NF_ACCEPT;
5963 +               }
5964 +
5965 +               /* Is status accept? */
5966 +               data++;
5967 +               if (IXDR_GET_INT32(data)) {
5968 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
5969 +                       return NF_ACCEPT;
5970 +               }
5971 +
5972 +               /* Get Verifier length. Jump verifier */
5973 +               data++;
5974 +               data = data + IXDR_GET_INT32(data) + 2;
5975 +
5976 +               /* Is accpet status "success"? */
5977 +               if (IXDR_GET_INT32(data)) {
5978 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5979 +                       return NF_ACCEPT;
5980 +               }
5981 +
5982 +               /* Get server port number */      
5983 +               data++;
5984 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
5985 +
5986 +               /* If a packet has made it this far then it deserves an
5987 +                * expectation ...  if port == 0, then this service is 
5988 +                * not going to be registered.
5989 +                */
5990 +               if (port_buf) {
5991 +                       DEBUGP("port found: %u\n", port_buf);
5992 +
5993 +                       memset(&expect, 0, sizeof(expect));
5994 +
5995 +                       /* Watch out, Radioactive-Man! */
5996 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5997 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5998 +                       exp->mask.src.ip = 0xffffffff;
5999 +                       exp->mask.dst.ip = 0xffffffff;
6000 +
6001 +                       switch (req_p->proto) {
6002 +                               case IPPROTO_UDP:
6003 +                                       exp->tuple.src.u.udp.port = 0;
6004 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
6005 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
6006 +                                       exp->mask.src.u.udp.port = 0;
6007 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
6008 +                                       exp->mask.dst.protonum = 0xffff;
6009 +                                       break;
6010 +
6011 +                               case IPPROTO_TCP:
6012 +                                       exp->tuple.src.u.tcp.port = 0;
6013 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
6014 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
6015 +                                       exp->mask.src.u.tcp.port = 0;
6016 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
6017 +                                       exp->mask.dst.protonum = 0xffff;
6018 +                                       break;
6019 +                       }
6020 +                       exp->expectfn = NULL;
6021 +
6022 +                       ip_conntrack_expect_related(ct, &expect);
6023 +
6024 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
6025 +                               NIPQUAD(exp->tuple.src.ip),
6026 +                               NIPQUAD(exp->tuple.dst.ip),
6027 +                               port_buf, req_p->proto);
6028 +
6029 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
6030 +                               NIPQUAD(exp->mask.src.ip),
6031 +                               NIPQUAD(exp->mask.dst.ip),
6032 +                               exp->mask.dst.protonum);
6033 +
6034 +               }
6035 +
6036 +               req_cl(req_p);
6037 +
6038 +               DEBUGP("packet evaluated. [expect]\n");
6039 +               return NF_ACCEPT;
6040 +       }
6041 +
6042 +       return NF_ACCEPT;
6043 +
6044 +}
6045 +
6046 +
6047 +/* RPC UDP helper */
6048 +static int help(const struct iphdr *iph, size_t len,
6049 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6050 +{
6051 +       struct udphdr *udph = (void *) iph + iph->ihl * 4;
6052 +       const u_int32_t *data = (const u_int32_t *)udph + 2;
6053 +       size_t udplen = len - iph->ihl * 4;
6054 +       int dir = CTINFO2DIR(ctinfo);
6055 +       int crp_ret;
6056 +
6057 +       /* Checksum */
6058 +       const u_int16_t *chsm = (const u_int16_t *)udph + 3;
6059 +
6060 +
6061 +       DEBUGP("new packet to evaluate ..\n");
6062 +
6063 +       /* Not whole UDP header? */
6064 +       if (udplen < sizeof(struct udphdr)) {
6065 +               DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
6066 +               DEBUGP("packet does not contain a complete UDP header. [skip]\n");
6067 +               return NF_ACCEPT;
6068 +       }
6069 +
6070 +       /* FIXME: Source route IP option packets --RR */
6071 +       if (*chsm) {
6072 +               if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6073 +                   csum_partial((char *)udph, udplen, 0))) {
6074 +                       DEBUGP("[note: failure to get past this error may indicate source routing]\n");
6075 +                       DEBUGP("packet contains a bad checksum. [skip]\n");
6076 +                       return NF_ACCEPT;
6077 +                  } 
6078 +       }
6079 +
6080 +       /* perform direction dependant protocol work */
6081 +       if (dir == IP_CT_DIR_ORIGINAL) {
6082 +
6083 +               DEBUGP("packet is from the initiator. [cont]\n");
6084 +
6085 +               /* Tests if packet len is ok */
6086 +               if ((udplen - sizeof(struct udphdr)) != 56) {
6087 +                       DEBUGP("packet length is not correct. [skip]\n");
6088 +                       return NF_ACCEPT;
6089 +               }
6090 +
6091 +       } else {
6092 +
6093 +               DEBUGP("packet is from the receiver. [cont]\n");
6094 +
6095 +               /* Until there's been traffic both ways, don't look in packets. */
6096 +               if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6097 +                       DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
6098 +                       DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
6099 +                       DEBUGP("packet is not yet part of a two way stream. [skip]\n");
6100 +                       return NF_ACCEPT;
6101 +               }
6102 +
6103 +               /* Tests if packet len is ok */
6104 +                       if ((udplen - sizeof(struct udphdr)) != 28) {
6105 +                       DEBUGP("packet length is not correct. [skip]\n");
6106 +                       return NF_ACCEPT;
6107 +               }
6108 +
6109 +       }
6110 +
6111 +       /* Get to the data */
6112 +       /* udp *data == *correct */
6113 +
6114 +       /* Check the RPC data */
6115 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
6116 +
6117 +       return crp_ret;
6118 +
6119 +}
6120 +
6121 +
6122 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
6123 +
6124 +static void fini(void);
6125 +
6126 +
6127 +static int __init init(void)
6128 +{
6129 +       int port, ret;
6130 +       static char name[10];
6131 +
6132 +
6133 +       /* If no port given, default to standard RPC port */
6134 +       if (ports[0] == 0)
6135 +               ports[0] = RPC_PORT;
6136 +
6137 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6138 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6139 +
6140 +                if (ports[port] == RPC_PORT)
6141 +                        sprintf(name, "rpc");
6142 +                else
6143 +                        sprintf(name, "rpc-%d", port);
6144 +
6145 +               rpc_helpers[port].name = name;
6146 +               rpc_helpers[port].me = THIS_MODULE;
6147 +               rpc_helpers[port].max_expected = 1;
6148 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6149 +               rpc_helpers[port].timeout = 0;
6150 +
6151 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
6152 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
6153 +
6154 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
6155 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
6156 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
6157 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
6158 +
6159 +               rpc_helpers[port].help = help;
6160 +
6161 +               DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
6162 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6163 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
6164 +                       ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
6165 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
6166 +                       ntohs(rpc_helpers[port].tuple.src.u.udp.port));
6167 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6168 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
6169 +                       ntohs(rpc_helpers[port].mask.dst.u.udp.port),
6170 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
6171 +                       ntohs(rpc_helpers[port].mask.src.u.udp.port));
6172 +
6173 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
6174 +
6175 +               if (ret) {
6176 +                       printk("ERROR registering port %d\n",
6177 +                               ports[port]);
6178 +                       fini();
6179 +                       return -EBUSY;
6180 +               }
6181 +               ports_n_c++;
6182 +       }
6183 +       return 0;
6184 +}
6185 +
6186 +
6187 +/* This function is intentionally _NOT_ defined as __exit, because 
6188 + * it is needed by the init function */
6189 +static void fini(void)
6190 +{
6191 +       int port;
6192 +
6193 +       DEBUGP("cleaning request list\n");
6194 +       clean_request(&request_p_list_udp);
6195 +
6196 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
6197 +               DEBUGP("unregistering port %d\n", ports[port]);
6198 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
6199 +       }
6200 +}
6201 +
6202 +
6203 +module_init(init);
6204 +module_exit(fini);
6205 +
6206 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
6207 +EXPORT_SYMBOL(request_p_list_udp);
6208 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
6209 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
6210 +
6211 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rsh.c
6212 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rsh.c        1970-01-01 01:00:00.000000000 +0100
6213 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rsh.c    2003-12-10 23:14:11.557197736 +0100
6214 @@ -0,0 +1,331 @@
6215 +/* RSH extension for IP connection tracking, Version 1.0
6216 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
6217 + * based on HW's ip_conntrack_irc.c    
6218 + *
6219 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
6220 + *
6221 + *      This program is free software; you can redistribute it and/or
6222 + *      modify it under the terms of the GNU General Public License
6223 + *      as published by the Free Software Foundation; either version
6224 + *      2 of the License, or (at your option) any later version.
6225 + **
6226 + *     Module load syntax:
6227 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
6228 + *     
6229 + *     please give the ports of all RSH servers You wish to connect to.
6230 + *     If You don't specify ports, the default will be port 514
6231 + **
6232 + *      Note to all:
6233 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
6234 + *        unfortunately I babysit some sysadmins that won't migrate
6235 + *       their legacy crap, in our second tier.
6236 + */
6237 +
6238 +
6239 +/*
6240 + *  Some docco ripped from the net to teach me all there is to know about
6241 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
6242 + *  this module).
6243 + *
6244 + *  I have no idea what "unix rshd man pages" these guys have .. but that
6245 + *  is some pretty detailed docco!
6246 + **
6247 + *
6248 + *  4. Of the rsh protocol.
6249 + *  -----------------------
6250 + * 
6251 + *   The rshd listens on TCP port #514. The following info is from the unix
6252 + *   rshd man pages :
6253 + * 
6254 + *   "Service Request Protocol
6255 + * 
6256 + *    When the rshd daemon receives a service request, it initiates the
6257 + *    following protocol:
6258 + * 
6259 + *     1. The rshd daemon checks the source port number for the request.
6260 + *        If the port number is not in the range 0 through 1023, the rshd daemon
6261 + *        terminates the connection.
6262 + * 
6263 + *     2. The rshd daemon reads characters from the socket up to a null byte.
6264 + *        The string read is interpreted as an ASCII number (base 10). If this
6265 + *        number is nonzero, the rshd daemon interprets it as the port number
6266 + *        of a secondary stream to be used as standard error. A second connection
6267 + *        is created to the specified port on the client host. The source port
6268 + *        on the local host is in the range 0 through 1023.
6269 + * 
6270 + *     3. The rshd daemon uses the source address of the initial connection
6271 + *        request to determine the name of the client host. If the name cannot
6272 + *        be determined, the rshd daemon uses the dotted decimal representation
6273 + *        of the client host's address.
6274 + * 
6275 + *     4. The rshd daemon retrieves the following information from the initial
6276 + *        socket:
6277 + * 
6278 + *         * A null-terminated string of at most 16 bytes interpreted as
6279 + *           the user name of the user on the client host.
6280 + * 
6281 + *         * A null-terminated string of at most 16 bytes interpreted as
6282 + *           the user name to be used on the local server host.
6283 + * 
6284 + *         * Another null-terminated string interpreted as a command line
6285 + *           to be passed to a shell on the local server host.
6286 + * 
6287 + *     5. The rshd daemon attempts to validate the user using the following steps:
6288 + * 
6289 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
6290 + *            file and tries to switch to the home directory (using the chdir
6291 + *            subroutine). If either the lookup or the directory change fails,
6292 + *            the rshd daemon terminates the connection.
6293 + * 
6294 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
6295 + *            the /etc/hosts.equiv file to see if the name of the client
6296 + *            workstation is listed. If the client workstation is listed as an
6297 + *            equivalent host, the rshd daemon validates the user.
6298 + * 
6299 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
6300 + *            authenticate the user by checking the .rhosts file.
6301 + * 
6302 + *         d. If either the $HOME/.rhosts authentication fails or the
6303 + *            client host is not an equivalent host, the rshd daemon
6304 + *            terminates the connection.
6305 + * 
6306 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
6307 + *        on the initial connection and passes the command line to the user's
6308 + *        local login shell. The shell then inherits the network connections
6309 + *        established by the rshd daemon."
6310 + * 
6311 + */
6312 +
6313 +
6314 +#include <linux/module.h>
6315 +#include <linux/netfilter.h>
6316 +#include <linux/ip.h>
6317 +#include <net/checksum.h>
6318 +#include <net/tcp.h>
6319 +
6320 +#include <linux/netfilter_ipv4/lockhelp.h>
6321 +#include <linux/netfilter_ipv4/ip_tables.h>
6322 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6323 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
6324 +
6325 +#define MAX_PORTS 8
6326 +static int ports[MAX_PORTS];
6327 +static int ports_n_c = 0;
6328 +
6329 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
6330 +MODULE_DESCRIPTION("RSH connection tracking module");
6331 +MODULE_LICENSE("GPL");
6332 +#ifdef MODULE_PARM
6333 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6334 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
6335 +#endif
6336 +
6337 +DECLARE_LOCK(ip_rsh_lock);
6338 +struct module *ip_conntrack_rsh = THIS_MODULE;
6339 +
6340 +#if 0
6341 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
6342 +                                       format, ## args)
6343 +#else
6344 +#define DEBUGP(format, args...)
6345 +#endif
6346 +
6347 +
6348 +
6349 +/* FIXME: This should be in userspace.  Later. */
6350 +static int help(const struct iphdr *iph, size_t len,
6351 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6352 +{
6353 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6354 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6355 +       const char *data = (const char *) tcph + tcph->doff * 4;
6356 +       u_int32_t tcplen = len - iph->ihl * 4;
6357 +       int dir = CTINFO2DIR(ctinfo);
6358 +        struct ip_conntrack_expect expect, *exp = &expect;
6359 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
6360 +       u_int16_t port;
6361 +       int maxoctet;
6362 +
6363 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
6364 +        *  original array size used in rshd/glibc) -- is there a
6365 +        *  vulnerability in rshd.c in the looped port *= 10?
6366 +        */
6367 +
6368 +
6369 +       DEBUGP("entered\n");
6370 +
6371 +       /* bail if packet is not from RSH client */
6372 +       if (dir == IP_CT_DIR_REPLY)
6373 +               return NF_ACCEPT;
6374 +
6375 +       /* Until there's been traffic both ways, don't look in packets. */
6376 +       if (ctinfo != IP_CT_ESTABLISHED
6377 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6378 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
6379 +               return NF_ACCEPT;
6380 +       }
6381 +
6382 +       /* Not whole TCP header? */
6383 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
6384 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
6385 +               return NF_ACCEPT;
6386 +       }
6387 +
6388 +       /* Checksum invalid?  Ignore. */
6389 +       /* FIXME: Source route IP option packets --RR */
6390 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6391 +                        csum_partial((char *) tcph, tcplen, 0))) {
6392 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6393 +                    tcph, tcplen, NIPQUAD(iph->saddr),
6394 +                    NIPQUAD(iph->daddr));
6395 +               return NF_ACCEPT;
6396 +       }
6397 +
6398 +       /* find the rsh stderr port */
6399 +       maxoctet = 4;
6400 +       port = 0;
6401 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
6402 +               if (*data < 0)
6403 +                       return(1);
6404 +               if (*data == 0)
6405 +                       break;
6406 +               if (*data < 48 || *data > 57) {
6407 +                       DEBUGP("these aren't the packets you're looking for ..\n");
6408 +                       return NF_ACCEPT;
6409 +               }
6410 +               port = port * 10 + ( *data - 48 );
6411 +       }
6412 +
6413 +       /* dont relate sessions that try to expose the client */
6414 +       DEBUGP("found port %u\n", port);
6415 +       if (port > 1023) {
6416 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
6417 +               return NF_ACCEPT;
6418 +       }
6419 +
6420 +
6421 +       LOCK_BH(&ip_rsh_lock);
6422 +
6423 +       /*  new(,related) connection is;
6424 +        *          reply + dst (uint)port + src port (0:1023)
6425 +        */
6426 +       memset(&expect, 0, sizeof(expect));
6427 +
6428 +       /*  save some discovered data, in case someone ever wants to write
6429 +        *  a NAT module for this bastard ..
6430 +        */
6431 +       exp_rsh_info->port = port;
6432 +
6433 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
6434 +
6435 +
6436 +       /* Watch out, Radioactive-Man! */
6437 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6438 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
6439 +       exp->tuple.src.u.tcp.port = 0;
6440 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
6441 +       exp->tuple.dst.protonum = IPPROTO_TCP;
6442 +
6443 +       exp->mask.src.ip = 0xffffffff;
6444 +       exp->mask.dst.ip = 0xffffffff;
6445 +
6446 +       exp->mask.src.u.tcp.port = htons(0xfc00);
6447 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
6448 +       exp->mask.dst.protonum = 0xffff;
6449 +
6450 +       exp->expectfn = NULL;
6451 +
6452 +       ip_conntrack_expect_related(ct, &expect);
6453 +
6454 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6455 +               NIPQUAD(exp->tuple.src.ip),
6456 +               ntohs(exp->tuple.src.u.tcp.port),
6457 +               NIPQUAD(exp->tuple.dst.ip),
6458 +               ntohs(exp->tuple.dst.u.tcp.port));
6459 +
6460 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6461 +               NIPQUAD(exp->mask.src.ip),
6462 +               ntohs(exp->mask.src.u.tcp.port),
6463 +               NIPQUAD(exp->mask.dst.ip),
6464 +               ntohs(exp->mask.dst.u.tcp.port));
6465 +       UNLOCK_BH(&ip_rsh_lock);
6466 +
6467 +       return NF_ACCEPT;
6468 +}
6469 +
6470 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
6471 +
6472 +static void fini(void);
6473 +
6474 +static int __init init(void)
6475 +{
6476 +       int port, ret;
6477 +       static char name[10];
6478 +
6479 +
6480 +       /* If no port given, default to standard RSH port */
6481 +       if (ports[0] == 0)
6482 +               ports[0] = RSH_PORT;
6483 +
6484 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6485 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6486 +
6487 +                if (ports[port] == RSH_PORT)
6488 +                        sprintf(name, "rsh");
6489 +                else
6490 +                        sprintf(name, "rsh-%d", port);
6491 +
6492 +               rsh_helpers[port].name = name;
6493 +               rsh_helpers[port].me = THIS_MODULE;
6494 +               rsh_helpers[port].max_expected = 1;
6495 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6496 +               rsh_helpers[port].timeout = 0;
6497 +
6498 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
6499 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
6500 +
6501 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
6502 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
6503 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
6504 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
6505 +
6506 +               rsh_helpers[port].help = help;
6507 +
6508 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
6509 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6510 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
6511 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
6512 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
6513 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
6514 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6515 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
6516 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
6517 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
6518 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
6519 +
6520 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
6521 +
6522 +               if (ret) {
6523 +                       printk("ERROR registering port %d\n",
6524 +                               ports[port]);
6525 +                       fini();
6526 +                       return -EBUSY;
6527 +               }
6528 +               ports_n_c++;
6529 +       }
6530 +       return 0;
6531 +}
6532 +
6533 +/* This function is intentionally _NOT_ defined as __exit, because 
6534 + * it is needed by the init function */
6535 +static void fini(void)
6536 +{
6537 +       int port;
6538 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6539 +               DEBUGP("unregistering port %d\n", ports[port]);
6540 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
6541 +       }
6542 +}
6543 +
6544 +module_init(init);
6545 +module_exit(fini);
6546 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rtsp.c
6547 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rtsp.c       1970-01-01 01:00:00.000000000 +0100
6548 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rtsp.c   2003-12-10 23:14:12.891994816 +0100
6549 @@ -0,0 +1,509 @@
6550 +/*
6551 + * RTSP extension for IP connection tracking
6552 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6553 + * based on ip_conntrack_irc.c
6554 + *
6555 + *      This program is free software; you can redistribute it and/or
6556 + *      modify it under the terms of the GNU General Public License
6557 + *      as published by the Free Software Foundation; either version
6558 + *      2 of the License, or (at your option) any later version.
6559 + *
6560 + * Module load syntax:
6561 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6562 + *                              max_outstanding=n setup_timeout=secs
6563 + *
6564 + * If no ports are specified, the default will be port 554.
6565 + *
6566 + * With max_outstanding you can define the maximum number of not yet
6567 + * answered SETUP requests per RTSP session (default 8).
6568 + * With setup_timeout you can specify how long the system waits for
6569 + * an expected data channel (default 300 seconds).
6570 + */
6571 +
6572 +#include <linux/config.h>
6573 +#include <linux/module.h>
6574 +#include <linux/netfilter.h>
6575 +#include <linux/ip.h>
6576 +#include <net/checksum.h>
6577 +#include <net/tcp.h>
6578 +
6579 +#include <linux/netfilter_ipv4/lockhelp.h>
6580 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6581 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6582 +
6583 +#include <linux/ctype.h>
6584 +#define NF_NEED_STRNCASECMP
6585 +#define NF_NEED_STRTOU16
6586 +#define NF_NEED_STRTOU32
6587 +#define NF_NEED_NEXTLINE
6588 +#include <linux/netfilter_helpers.h>
6589 +#define NF_NEED_MIME_NEXTLINE
6590 +#include <linux/netfilter_mime.h>
6591 +
6592 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
6593 +
6594 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
6595 +#ifdef IP_NF_RTSP_DEBUG
6596 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args)
6597 +#else
6598 +#define DEBUGP(args...)
6599 +#endif
6600 +
6601 +#define MAX_PORTS 8
6602 +static int ports[MAX_PORTS];
6603 +static int num_ports = 0;
6604 +static int max_outstanding = 8;
6605 +static unsigned int setup_timeout = 300;
6606 +
6607 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
6608 +MODULE_DESCRIPTION("RTSP connection tracking module");
6609 +MODULE_LICENSE("GPL");
6610 +#ifdef MODULE_PARM
6611 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6612 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
6613 +MODULE_PARM(max_outstanding, "i");
6614 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
6615 +MODULE_PARM(setup_timeout, "i");
6616 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
6617 +#endif
6618 +
6619 +DECLARE_LOCK(ip_rtsp_lock);
6620 +struct module* ip_conntrack_rtsp = THIS_MODULE;
6621 +
6622 +/*
6623 + * Max mappings we will allow for one RTSP connection (for RTP, the number
6624 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
6625 + * ports so keep this reasonably high.  If this is too low, you will see a
6626 + * lot of "no free client map entries" messages.
6627 + */
6628 +#define MAX_PORT_MAPS 16
6629 +
6630 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
6631 +
6632 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
6633 +
6634 +/*
6635 + * Parse an RTSP packet.
6636 + *
6637 + * Returns zero if parsing failed.
6638 + *
6639 + * Parameters:
6640 + *  IN      ptcp        tcp data pointer
6641 + *  IN      tcplen      tcp data len
6642 + *  IN/OUT  ptcpoff     points to current tcp offset
6643 + *  OUT     phdrsoff    set to offset of rtsp headers
6644 + *  OUT     phdrslen    set to length of rtsp headers
6645 + *  OUT     pcseqoff    set to offset of CSeq header
6646 + *  OUT     pcseqlen    set to length of CSeq header
6647 + */
6648 +static int
6649 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
6650 +                   uint* phdrsoff, uint* phdrslen,
6651 +                   uint* pcseqoff, uint* pcseqlen)
6652 +{
6653 +    uint    entitylen = 0;
6654 +    uint    lineoff;
6655 +    uint    linelen;
6656 +
6657 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6658 +    {
6659 +        return 0;
6660 +    }
6661 +
6662 +    *phdrsoff = *ptcpoff;
6663 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6664 +    {
6665 +        if (linelen == 0)
6666 +        {
6667 +            if (entitylen > 0)
6668 +            {
6669 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
6670 +            }
6671 +            break;
6672 +        }
6673 +        if (lineoff+linelen > tcplen)
6674 +        {
6675 +            INFOP("!! overrun !!\n");
6676 +            break;
6677 +        }
6678 +
6679 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
6680 +        {
6681 +            *pcseqoff = lineoff;
6682 +            *pcseqlen = linelen;
6683 +        }
6684 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
6685 +        {
6686 +            uint off = lineoff+15;
6687 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
6688 +            nf_strtou32(ptcp+off, &entitylen);
6689 +        }
6690 +    }
6691 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
6692 +
6693 +    return 1;
6694 +}
6695 +
6696 +/*
6697 + * Find lo/hi client ports (if any) in transport header
6698 + * In:
6699 + *   ptcp, tcplen = packet
6700 + *   tranoff, tranlen = buffer to search
6701 + *
6702 + * Out:
6703 + *   pport_lo, pport_hi = lo/hi ports (host endian)
6704 + *
6705 + * Returns nonzero if any client ports found
6706 + *
6707 + * Note: it is valid (and expected) for the client to request multiple
6708 + * transports, so we need to parse the entire line.
6709 + */
6710 +static int
6711 +rtsp_parse_transport(char* ptran, uint tranlen,
6712 +                     struct ip_ct_rtsp_expect* prtspexp)
6713 +{
6714 +    int     rc = 0;
6715 +    uint    off = 0;
6716 +
6717 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
6718 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
6719 +    {
6720 +        INFOP("sanity check failed\n");
6721 +        return 0;
6722 +    }
6723 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
6724 +    off += 10;
6725 +    SKIP_WSPACE(ptran, tranlen, off);
6726 +
6727 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
6728 +    while (off < tranlen)
6729 +    {
6730 +        const char* pparamend;
6731 +        uint        nextparamoff;
6732 +
6733 +        pparamend = memchr(ptran+off, ',', tranlen-off);
6734 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
6735 +        nextparamoff = pparamend-ptran;
6736 +
6737 +        while (off < nextparamoff)
6738 +        {
6739 +            const char* pfieldend;
6740 +            uint        nextfieldoff;
6741 +
6742 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6743 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6744 +
6745 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
6746 +            {
6747 +                u_int16_t   port;
6748 +                uint        numlen;
6749 +
6750 +                off += 12;
6751 +                numlen = nf_strtou16(ptran+off, &port);
6752 +                off += numlen;
6753 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
6754 +                {
6755 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
6756 +                }
6757 +                else
6758 +                {
6759 +                    prtspexp->loport = prtspexp->hiport = port;
6760 +                    if (ptran[off] == '-')
6761 +                    {
6762 +                        off++;
6763 +                        numlen = nf_strtou16(ptran+off, &port);
6764 +                        off += numlen;
6765 +                        prtspexp->pbtype = pb_range;
6766 +                        prtspexp->hiport = port;
6767 +
6768 +                        // If we have a range, assume rtp:
6769 +                        // loport must be even, hiport must be loport+1
6770 +                        if ((prtspexp->loport & 0x0001) != 0 ||
6771 +                            prtspexp->hiport != prtspexp->loport+1)
6772 +                        {
6773 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
6774 +                                   prtspexp->loport, prtspexp->hiport);
6775 +                            prtspexp->loport &= 0xfffe;
6776 +                            prtspexp->hiport = prtspexp->loport+1;
6777 +                        }
6778 +                    }
6779 +                    else if (ptran[off] == '/')
6780 +                    {
6781 +                        off++;
6782 +                        numlen = nf_strtou16(ptran+off, &port);
6783 +                        off += numlen;
6784 +                        prtspexp->pbtype = pb_discon;
6785 +                        prtspexp->hiport = port;
6786 +                    }
6787 +                    rc = 1;
6788 +                }
6789 +            }
6790 +
6791 +            /*
6792 +             * Note we don't look for the destination parameter here.
6793 +             * If we are using NAT, the NAT module will handle it.  If not,
6794 +             * and the client is sending packets elsewhere, the expectation
6795 +             * will quietly time out.
6796 +             */
6797 +
6798 +            off = nextfieldoff;
6799 +        }
6800 +
6801 +        off = nextparamoff;
6802 +    }
6803 +
6804 +    return rc;
6805 +}
6806 +
6807 +/*** conntrack functions ***/
6808 +
6809 +/* outbound packet: client->server */
6810 +static int
6811 +help_out(const struct iphdr* iph, size_t pktlen,
6812 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6813 +{
6814 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
6815 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
6816 +    uint    tcplen = pktlen - iph->ihl * 4;
6817 +    char*   pdata = (char*)tcph + tcph->doff * 4;
6818 +    uint    datalen = tcplen - tcph->doff * 4;
6819 +    uint    dataoff = 0;
6820 +
6821 +    struct ip_conntrack_expect exp;
6822 +
6823 +    while (dataoff < datalen)
6824 +    {
6825 +        uint    cmdoff = dataoff;
6826 +        uint    hdrsoff = 0;
6827 +        uint    hdrslen = 0;
6828 +        uint    cseqoff = 0;
6829 +        uint    cseqlen = 0;
6830 +        uint    lineoff = 0;
6831 +        uint    linelen = 0;
6832 +        uint    off;
6833 +        int     rc;
6834 +
6835 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
6836 +                                &hdrsoff, &hdrslen,
6837 +                                &cseqoff, &cseqlen))
6838 +        {
6839 +            break;      /* not a valid message */
6840 +        }
6841 +
6842 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
6843 +        {
6844 +            continue;   /* not a SETUP message */
6845 +        }
6846 +        DEBUGP("found a setup message\n");
6847 +
6848 +        memset(&exp, 0, sizeof(exp));
6849 +
6850 +        off = 0;
6851 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
6852 +                                &lineoff, &linelen))
6853 +        {
6854 +            if (linelen == 0)
6855 +            {
6856 +                break;
6857 +            }
6858 +            if (off > hdrsoff+hdrslen)
6859 +            {
6860 +                INFOP("!! overrun !!");
6861 +                break;
6862 +            }
6863 +
6864 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
6865 +            {
6866 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
6867 +                                     &exp.help.exp_rtsp_info);
6868 +            }
6869 +        }
6870 +
6871 +        if (exp.help.exp_rtsp_info.loport == 0)
6872 +        {
6873 +            DEBUGP("no udp transports found\n");
6874 +            continue;   /* no udp transports found */
6875 +        }
6876 +
6877 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
6878 +              (int)exp.help.exp_rtsp_info.pbtype,
6879 +              exp.help.exp_rtsp_info.loport,
6880 +              exp.help.exp_rtsp_info.hiport);
6881 +
6882 +        LOCK_BH(&ip_rtsp_lock);
6883 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
6884 +        exp.help.exp_rtsp_info.len = hdrslen;
6885 +
6886 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6887 +        exp.mask.src.ip  = 0xffffffff;
6888 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
6889 +        exp.mask.dst.ip  = 0xffffffff;
6890 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
6891 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
6892 +        exp.tuple.dst.protonum = IPPROTO_UDP;
6893 +        exp.mask.dst.protonum  = 0xffff;
6894 +
6895 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6896 +                NIPQUAD(exp.tuple.src.ip),
6897 +                ntohs(exp.tuple.src.u.tcp.port),
6898 +                NIPQUAD(exp.tuple.dst.ip),
6899 +                ntohs(exp.tuple.dst.u.tcp.port));
6900 +
6901 +        /* pass the request off to the nat helper */
6902 +        rc = ip_conntrack_expect_related(ct, &exp);
6903 +        UNLOCK_BH(&ip_rtsp_lock);
6904 +        if (rc == 0)
6905 +        {
6906 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
6907 +        }
6908 +        else
6909 +        {
6910 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
6911 +        }
6912 +    }
6913 +
6914 +    return NF_ACCEPT;
6915 +}
6916 +
6917 +/* inbound packet: server->client */
6918 +static int
6919 +help_in(const struct iphdr* iph, size_t pktlen,
6920 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6921 +{
6922 +    return NF_ACCEPT;
6923 +}
6924 +
6925 +static int
6926 +help(const struct iphdr* iph, size_t pktlen,
6927 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6928 +{
6929 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6930 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6931 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
6932 +
6933 +    /* Until there's been traffic both ways, don't look in packets. */
6934 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
6935 +    {
6936 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
6937 +        return NF_ACCEPT;
6938 +    }
6939 +
6940 +    /* Not whole TCP header? */
6941 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
6942 +    {
6943 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
6944 +        return NF_ACCEPT;
6945 +    }
6946 +
6947 +    /* Checksum invalid?  Ignore. */
6948 +    /* FIXME: Source route IP option packets --RR */
6949 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6950 +                     csum_partial((char*)tcph, tcplen, 0)))
6951 +    {
6952 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6953 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6954 +        return NF_ACCEPT;
6955 +    }
6956 +
6957 +    switch (CTINFO2DIR(ctinfo))
6958 +    {
6959 +    case IP_CT_DIR_ORIGINAL:
6960 +        help_out(iph, pktlen, ct, ctinfo);
6961 +        break;
6962 +    case IP_CT_DIR_REPLY:
6963 +        help_in(iph, pktlen, ct, ctinfo);
6964 +        break;
6965 +    default:
6966 +        /* oops */
6967 +    }
6968 +
6969 +    return NF_ACCEPT;
6970 +}
6971 +
6972 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
6973 +static char rtsp_names[MAX_PORTS][10];
6974 +
6975 +/* This function is intentionally _NOT_ defined as __exit */
6976 +static void
6977 +fini(void)
6978 +{
6979 +    int i;
6980 +    for (i = 0; i < num_ports; i++)
6981 +    {
6982 +        DEBUGP("unregistering port %d\n", ports[i]);
6983 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
6984 +    }
6985 +}
6986 +
6987 +static int __init
6988 +init(void)
6989 +{
6990 +    int i, ret;
6991 +    struct ip_conntrack_helper *hlpr;
6992 +    char *tmpname;
6993 +
6994 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
6995 +
6996 +    if (max_outstanding < 1)
6997 +    {
6998 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
6999 +        return -EBUSY;
7000 +    }
7001 +    if (setup_timeout < 0)
7002 +    {
7003 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
7004 +        return -EBUSY;
7005 +    }
7006 +
7007 +    /* If no port given, default to standard rtsp port */
7008 +    if (ports[0] == 0)
7009 +    {
7010 +        ports[0] = RTSP_PORT;
7011 +    }
7012 +
7013 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
7014 +    {
7015 +        hlpr = &rtsp_helpers[i];
7016 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
7017 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7018 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
7019 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
7020 +        hlpr->mask.dst.protonum = 0xFFFF;
7021 +        hlpr->max_expected = max_outstanding;
7022 +        hlpr->timeout = setup_timeout;
7023 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
7024 +        hlpr->me = ip_conntrack_rtsp;
7025 +        hlpr->help = help;
7026 +
7027 +        tmpname = &rtsp_names[i][0];
7028 +        if (ports[i] == RTSP_PORT)
7029 +        {
7030 +            sprintf(tmpname, "rtsp");
7031 +        }
7032 +        else
7033 +        {
7034 +            sprintf(tmpname, "rtsp-%d", i);
7035 +        }
7036 +        hlpr->name = tmpname;
7037 +
7038 +        DEBUGP("port #%d: %d\n", i, ports[i]);
7039 +
7040 +        ret = ip_conntrack_helper_register(hlpr);
7041 +
7042 +        if (ret)
7043 +        {
7044 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
7045 +            fini();
7046 +            return -EBUSY;
7047 +        }
7048 +        num_ports++;
7049 +    }
7050 +    return 0;
7051 +}
7052 +
7053 +#ifdef CONFIG_IP_NF_NAT_NEEDED
7054 +EXPORT_SYMBOL(ip_rtsp_lock);
7055 +#endif
7056 +
7057 +module_init(init);
7058 +module_exit(fini);
7059 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_standalone.c
7060 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-12-10 20:50:26.980332712 +0100
7061 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_standalone.c     2003-12-10 23:14:22.974462048 +0100
7062 @@ -105,6 +105,9 @@
7063                 len += sprintf(buffer + len, "[ASSURED] ");
7064         len += sprintf(buffer + len, "use=%u ",
7065                        atomic_read(&conntrack->ct_general.use));
7066 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
7067 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
7068 +#endif
7069         len += sprintf(buffer + len, "\n");
7070  
7071         return len;
7072 @@ -186,6 +189,26 @@
7073         return ip_conntrack_confirm(*pskb);
7074  }
7075  
7076 +static unsigned int ip_conntrack_defrag(unsigned int hooknum,
7077 +                                       struct sk_buff **pskb,
7078 +                                       const struct net_device *in,
7079 +                                       const struct net_device *out,
7080 +                                       int (*okfn)(struct sk_buff *))
7081 +{
7082 +       /* Previously seen (loopback)?  Ignore.  Do this before
7083 +           fragment check. */
7084 +       if ((*pskb)->nfct)
7085 +               return NF_ACCEPT;
7086 +
7087 +       /* Gather fragments. */
7088 +       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
7089 +               *pskb = ip_ct_gather_frags(*pskb);
7090 +               if (!*pskb)
7091 +                       return NF_STOLEN;
7092 +       }
7093 +       return NF_ACCEPT;
7094 +}
7095 +
7096  static unsigned int ip_refrag(unsigned int hooknum,
7097                               struct sk_buff **pskb,
7098                               const struct net_device *in,
7099 @@ -226,6 +249,15 @@
7100         return ip_conntrack_in(hooknum, pskb, in, out, okfn);
7101  }
7102  
7103 +/* At the very first: defragment */
7104 +static struct nf_hook_ops ip_conntrack_defrag_ops = {
7105 +       .hook           = ip_conntrack_defrag,
7106 +       .owner          = THIS_MODULE,
7107 +       .pf             = PF_INET,
7108 +       .hooknum        = NF_IP_PRE_ROUTING,
7109 +       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
7110 +};
7111 +
7112  /* Connection tracking may drop packets, but never alters them, so
7113     make it the first hook. */
7114  static struct nf_hook_ops ip_conntrack_in_ops = {
7115 @@ -236,6 +268,14 @@
7116         .priority       = NF_IP_PRI_CONNTRACK,
7117  };
7118  
7119 +static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
7120 +       .hook           = ip_conntrack_defrag,
7121 +       .owner          = THIS_MODULE,
7122 +       .pf             = PF_INET,
7123 +       .hooknum        = NF_IP_LOCAL_OUT,
7124 +       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
7125 +};
7126 +
7127  static struct nf_hook_ops ip_conntrack_local_out_ops = {
7128         .hook           = ip_conntrack_local,
7129         .owner          = THIS_MODULE,
7130 @@ -368,10 +408,20 @@
7131         if (!proc) goto cleanup_init;
7132         proc->owner = THIS_MODULE;
7133  
7134 +       ret = nf_register_hook(&ip_conntrack_defrag_ops);
7135 +       if (ret < 0) {
7136 +               printk("ip_conntrack: can't register pre-routing defrag hook.\n");
7137 +               goto cleanup_proc;
7138 +       }
7139 +       ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
7140 +       if (ret < 0) {
7141 +               printk("ip_conntrack: can't register local_out defrag hook.\n");
7142 +               goto cleanup_defragops;
7143 +       }
7144         ret = nf_register_hook(&ip_conntrack_in_ops);
7145         if (ret < 0) {
7146                 printk("ip_conntrack: can't register pre-routing hook.\n");
7147 -               goto cleanup_proc;
7148 +               goto cleanup_defraglocalops;
7149         }
7150         ret = nf_register_hook(&ip_conntrack_local_out_ops);
7151         if (ret < 0) {
7152 @@ -409,6 +459,10 @@
7153         nf_unregister_hook(&ip_conntrack_local_out_ops);
7154   cleanup_inops:
7155         nf_unregister_hook(&ip_conntrack_in_ops);
7156 + cleanup_defraglocalops:
7157 +       nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
7158 + cleanup_defragops:
7159 +       nf_unregister_hook(&ip_conntrack_defrag_ops);
7160   cleanup_proc:
7161         proc_net_remove("ip_conntrack");
7162   cleanup_init:
7163 @@ -417,13 +471,20 @@
7164         return ret;
7165  }
7166  
7167 -/* FIXME: Allow NULL functions and sub in pointers to generic for
7168 -   them. --RR */
7169 +/**
7170 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
7171 + * @proto: structure describing this layer 4 protocol helper
7172 + *
7173 + * This function is called by layer 4 protocol helpers to register 
7174 + * themselves with the conntrack core.
7175 + */
7176  int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
7177  {
7178         int ret = 0;
7179         struct list_head *i;
7180  
7181 +       /* FIXME: Allow NULL functions and sub in pointers to generic for
7182 +          them. --RR */
7183         WRITE_LOCK(&ip_conntrack_lock);
7184         list_for_each(i, &protocol_list) {
7185                 if (((struct ip_conntrack_protocol *)i)->proto
7186 @@ -440,12 +501,20 @@
7187         return ret;
7188  }
7189  
7190 +/**
7191 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
7192 + * @proto: structure describing this layer 4 protocol helper
7193 + *
7194 + * This function is called byh layer 4 protocol helpers to unregister
7195 + * themselvers from the conntrack core.  Please note that all conntrack
7196 + * entries for this protocol are deleted from the conntrack hash table.
7197 + */
7198  void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
7199  {
7200         WRITE_LOCK(&ip_conntrack_lock);
7201  
7202 -       /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
7203 -        * helper. So this should be enough - HW */
7204 +       /* ip_ct_find_proto() returns proto_generic in case there is no
7205 +        * protocol helper. So this should be enough - HW */
7206         LIST_DELETE(&protocol_list, proto);
7207         WRITE_UNLOCK(&ip_conntrack_lock);
7208         
7209 @@ -486,6 +555,7 @@
7210  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
7211  EXPORT_SYMBOL(ip_ct_selective_cleanup);
7212  EXPORT_SYMBOL(ip_ct_refresh);
7213 +EXPORT_SYMBOL(ip_ct_death_by_timeout);
7214  EXPORT_SYMBOL(ip_ct_find_proto);
7215  EXPORT_SYMBOL(__ip_ct_find_proto);
7216  EXPORT_SYMBOL(ip_ct_find_helper);
7217 @@ -500,5 +570,6 @@
7218  EXPORT_SYMBOL(ip_conntrack_expect_list);
7219  EXPORT_SYMBOL(ip_conntrack_lock);
7220  EXPORT_SYMBOL(ip_conntrack_hash);
7221 +EXPORT_SYMBOL(ip_conntrack_untracked);
7222  EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
7223  EXPORT_SYMBOL_GPL(ip_conntrack_put);
7224 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_talk.c
7225 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_talk.c       1970-01-01 01:00:00.000000000 +0100
7226 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_talk.c   2003-12-10 23:14:15.480601288 +0100
7227 @@ -0,0 +1,360 @@
7228 +/* 
7229 + * talk extension for IP connection tracking. 
7230 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7231 + *
7232 + *      This program is free software; you can redistribute it and/or
7233 + *      modify it under the terms of the GNU General Public License
7234 + *      as published by the Free Software Foundation; either version
7235 + *      2 of the License, or (at your option) any later version.
7236 + **
7237 + *     Module load syntax:
7238 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
7239 + *
7240 + *             talk=[0|1]      disable|enable old talk support
7241 + *            ntalk=[0|1]      disable|enable ntalk support
7242 + *           ntalk2=[0|1]      disable|enable ntalk2 support
7243 + *
7244 + *     The default is talk=1 ntalk=1 ntalk2=1
7245 + *
7246 + *     The helper does not support simultaneous talk requests.
7247 + **
7248 + *
7249 + *             ASCII art on talk protocols
7250 + *     
7251 + *     
7252 + *     caller server               callee server
7253 + *             |     \           /
7254 + *             |       \       /
7255 + *             |         \   /
7256 + *             |           /  
7257 + *             |         /   \
7258 + *           2 |     1 /       \ 3
7259 + *     caller client  ----------- callee client
7260 + *                              4
7261 + *
7262 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
7263 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
7264 + *     3. callee client <-> caller server: LOOK_UP invitation
7265 + *     4. callee client <-> caller client: talk data channel
7266 + *
7267 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
7268 + *      draft-hunter-talk-00.txt
7269 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
7270 + */
7271 +#include <linux/config.h>
7272 +#include <linux/module.h>
7273 +#include <linux/netfilter.h>
7274 +#include <linux/ip.h>
7275 +#include <net/checksum.h>
7276 +#include <net/udp.h>
7277 +
7278 +#include <linux/netfilter_ipv4/lockhelp.h>
7279 +#include <linux/netfilter_ipv4/ip_conntrack.h>
7280 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
7281 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7282 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7283 +
7284 +/* Default all talk protocols are supported */
7285 +static int talk = 1;
7286 +static int ntalk = 1;
7287 +static int ntalk2 = 1;
7288 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7289 +MODULE_DESCRIPTION("talk connection tracking module");
7290 +MODULE_LICENSE("GPL");
7291 +#ifdef MODULE_PARM
7292 +MODULE_PARM(talk, "i");
7293 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7294 +MODULE_PARM(ntalk, "i");
7295 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7296 +MODULE_PARM(ntalk2, "i");
7297 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7298 +#endif
7299 +
7300 +DECLARE_LOCK(ip_talk_lock);
7301 +struct module *ip_conntrack_talk = THIS_MODULE;
7302 +
7303 +#if 0
7304 +#define DEBUGP printk
7305 +#else
7306 +#define DEBUGP(format, args...)
7307 +#endif
7308 +
7309 +static int talk_expect(struct ip_conntrack *ct);
7310 +static int ntalk_expect(struct ip_conntrack *ct);
7311 +
7312 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
7313 +
7314 +static int talk_help_response(const struct iphdr *iph, size_t len,
7315 +                             struct ip_conntrack *ct,
7316 +                             enum ip_conntrack_info ctinfo,
7317 +                             int talk_port,
7318 +                             u_char mode,
7319 +                             u_char type,
7320 +                             u_char answer,
7321 +                             struct talk_addr *addr)
7322 +{
7323 +       int dir = CTINFO2DIR(ctinfo);
7324 +       struct ip_conntrack_expect expect, *exp = &expect;
7325 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
7326 +
7327 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
7328 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7329 +               type, answer);
7330 +
7331 +       if (!(answer == SUCCESS && type == mode))
7332 +               return NF_ACCEPT;
7333 +       
7334 +       memset(&expect, 0, sizeof(expect));
7335 +       
7336 +       if (type == ANNOUNCE) {
7337 +
7338 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
7339 +
7340 +               /* update the talk info */
7341 +               LOCK_BH(&ip_talk_lock);
7342 +               exp_talk_info->port = htons(talk_port);
7343 +
7344 +               /* expect callee client -> caller server message */
7345 +               exp->tuple = ((struct ip_conntrack_tuple)
7346 +                       { { ct->tuplehash[dir].tuple.src.ip,
7347 +                           { 0 } },
7348 +                         { ct->tuplehash[dir].tuple.dst.ip,
7349 +                           { .tcp = { htons(talk_port) } },
7350 +                           IPPROTO_UDP }});
7351 +               exp->mask = ((struct ip_conntrack_tuple)
7352 +                       { { 0xFFFFFFFF, { 0 } },
7353 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
7354 +               
7355 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
7356 +
7357 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
7358 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
7359 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
7360 +
7361 +               /* Ignore failure; should only happen with NAT */
7362 +               ip_conntrack_expect_related(ct, &expect);
7363 +               UNLOCK_BH(&ip_talk_lock);
7364 +       }
7365 +       if (type == LOOK_UP) {
7366 +
7367 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
7368 +
7369 +               /* update the talk info */
7370 +               LOCK_BH(&ip_talk_lock);
7371 +               exp_talk_info->port = addr->ta_port;
7372 +
7373 +               /* expect callee client -> caller client connection */
7374 +               exp->tuple = ((struct ip_conntrack_tuple)
7375 +                       { { ct->tuplehash[!dir].tuple.src.ip,
7376 +                           { 0 } },
7377 +                         { addr->ta_addr,
7378 +                           { addr->ta_port },
7379 +                           IPPROTO_TCP }});
7380 +               exp->mask = ((struct ip_conntrack_tuple)
7381 +                       { { 0xFFFFFFFF, { 0 } },
7382 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
7383 +               
7384 +               exp->expectfn = NULL;
7385 +               
7386 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
7387 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
7388 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
7389 +
7390 +               /* Ignore failure; should only happen with NAT */
7391 +               ip_conntrack_expect_related(ct, &expect);
7392 +               UNLOCK_BH(&ip_talk_lock);
7393 +       }
7394 +                   
7395 +       return NF_ACCEPT;
7396 +}
7397 +
7398 +/* FIXME: This should be in userspace.  Later. */
7399 +static int talk_help(const struct iphdr *iph, size_t len,
7400 +                    struct ip_conntrack *ct,
7401 +                    enum ip_conntrack_info ctinfo,
7402 +                    int talk_port,
7403 +                    u_char mode)
7404 +{
7405 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7406 +       const char *data = (const char *)udph + sizeof(struct udphdr);
7407 +       int dir = CTINFO2DIR(ctinfo);
7408 +       size_t udplen;
7409 +
7410 +       DEBUGP("ip_ct_talk_help: help entered\n");
7411 +
7412 +       /* Until there's been traffic both ways, don't look in packets. */
7413 +       if (ctinfo != IP_CT_ESTABLISHED
7414 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
7415 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
7416 +               return NF_ACCEPT;
7417 +       }
7418 +
7419 +       /* Not whole UDP header? */
7420 +       udplen = len - iph->ihl * 4;
7421 +       if (udplen < sizeof(struct udphdr)) {
7422 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
7423 +               return NF_ACCEPT;
7424 +       }
7425 +
7426 +       /* Checksum invalid?  Ignore. */
7427 +       /* FIXME: Source route IP option packets --RR */
7428 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7429 +                             csum_partial((char *)udph, udplen, 0))) {
7430 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
7431 +                      udph, udplen, NIPQUAD(iph->saddr),
7432 +                      NIPQUAD(iph->daddr));
7433 +               return NF_ACCEPT;
7434 +       }
7435 +       
7436 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7437 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
7438 +
7439 +       if (dir == IP_CT_DIR_ORIGINAL)
7440 +               return NF_ACCEPT;
7441 +               
7442 +       if (talk_port == TALK_PORT
7443 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7444 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7445 +                                         ((struct talk_response *)data)->type, 
7446 +                                         ((struct talk_response *)data)->answer,
7447 +                                         &(((struct talk_response *)data)->addr));
7448 +       else if (talk_port == NTALK_PORT
7449 +                 && ntalk
7450 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
7451 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
7452 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7453 +                                         ((struct ntalk_response *)data)->type, 
7454 +                                         ((struct ntalk_response *)data)->answer,
7455 +                                         &(((struct ntalk_response *)data)->addr));
7456 +       else if (talk_port == NTALK_PORT
7457 +                && ntalk2
7458 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
7459 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
7460 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7461 +                                         ((struct ntalk2_response *)data)->type, 
7462 +                                         ((struct ntalk2_response *)data)->answer,
7463 +                                         &(((struct ntalk2_response *)data)->addr));
7464 +       else {
7465 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
7466 +                      (unsigned)udplen - sizeof(struct udphdr), 
7467 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
7468 +               return NF_ACCEPT;
7469 +       }
7470 +}
7471 +
7472 +static int lookup_help(const struct iphdr *iph, size_t len,
7473 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7474 +{
7475 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
7476 +}
7477 +
7478 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
7479 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7480 +{
7481 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
7482 +}
7483 +
7484 +static struct ip_conntrack_helper lookup_helpers[2] = 
7485 +       { { { NULL, NULL },
7486 +           "talk",                                     /* name */
7487 +           0,                                          /* flags */
7488 +           NULL,                                       /* module */
7489 +           1,                                          /* max_expected */
7490 +           240,                                        /* timeout */
7491 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
7492 +             { 0, { 0 }, IPPROTO_UDP } },
7493 +           { { 0, { 0xFFFF } },                        /* mask */
7494 +             { 0, { 0 }, 0xFFFF } },
7495 +           lookup_help },                              /* helper */
7496 +          { { NULL, NULL },
7497 +            "ntalk",                                   /* name */
7498 +           0,                                          /* flags */
7499 +           NULL,                                       /* module */
7500 +           1,                                          /* max_expected */
7501 +           240,                                        /* timeout */
7502 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
7503 +             { 0, { 0 }, IPPROTO_UDP } },
7504 +           { { 0, { 0xFFFF } },                        /* mask */
7505 +             { 0, { 0 }, 0xFFFF } },
7506 +           lookup_nhelp }                              /* helper */
7507 +        };
7508 +
7509 +static int talk_expect(struct ip_conntrack *ct)
7510 +{
7511 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
7512 +       WRITE_LOCK(&ip_conntrack_lock);
7513 +       ct->helper = &lookup_helpers[0];
7514 +       WRITE_UNLOCK(&ip_conntrack_lock);
7515 +        
7516 +       return NF_ACCEPT;       /* unused */
7517 +}
7518 +
7519 +static int ntalk_expect(struct ip_conntrack *ct)
7520 +{
7521 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
7522 +       WRITE_LOCK(&ip_conntrack_lock);
7523 +       ct->helper = &lookup_helpers[1];
7524 +       WRITE_UNLOCK(&ip_conntrack_lock);
7525 +        
7526 +       return NF_ACCEPT;       /* unused */
7527 +}
7528 +
7529 +static int help(const struct iphdr *iph, size_t len,
7530 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7531 +{
7532 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
7533 +}
7534 +
7535 +static int nhelp(const struct iphdr *iph, size_t len,
7536 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7537 +{
7538 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
7539 +}
7540 +
7541 +static struct ip_conntrack_helper talk_helpers[2] = 
7542 +       { { { NULL, NULL },
7543 +           "talk",                                     /* name */
7544 +           0,                                          /* flags */
7545 +           THIS_MODULE,                                /* module */
7546 +           1,                                          /* max_expected */
7547 +           240,                                        /* timeout */
7548 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
7549 +             { 0, { 0 }, IPPROTO_UDP } },
7550 +           { { 0, { 0xFFFF } },                        /* mask */
7551 +             { 0, { 0 }, 0xFFFF } },
7552 +           help },                                     /* helper */
7553 +          { { NULL, NULL },
7554 +           "ntalk",                                    /* name */
7555 +           0,                                          /* flags */
7556 +           THIS_MODULE,                                /* module */
7557 +           1,                                          /* max_expected */
7558 +           240,                                        /* timeout */
7559 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
7560 +             { 0, { 0 }, IPPROTO_UDP } },
7561 +           { { 0, { 0xFFFF } },                        /* mask */
7562 +             { 0, { 0 }, 0xFFFF } },
7563 +           nhelp }                                     /* helper */
7564 +       };
7565 +
7566 +static int __init init(void)
7567 +{
7568 +       if (talk > 0)
7569 +               ip_conntrack_helper_register(&talk_helpers[0]);
7570 +       if (ntalk > 0 || ntalk2 > 0)
7571 +               ip_conntrack_helper_register(&talk_helpers[1]);
7572 +               
7573 +       return 0;
7574 +}
7575 +
7576 +static void __exit fini(void)
7577 +{
7578 +       if (talk > 0)
7579 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
7580 +       if (ntalk > 0 || ntalk2 > 0)
7581 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
7582 +}
7583 +
7584 +EXPORT_SYMBOL(ip_talk_lock);
7585 +
7586 +module_init(init);
7587 +module_exit(fini);
7588 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_tftp.c
7589 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_tftp.c       2003-11-26 21:43:31.000000000 +0100
7590 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_tftp.c   2003-12-10 23:13:21.271842272 +0100
7591 @@ -97,8 +97,6 @@
7592  
7593         for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7594                 /* Create helper structure */
7595 -               memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
7596 -
7597                 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
7598                 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
7599                 tftp[i].mask.dst.protonum = 0xFFFF;
7600 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_amanda.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_amanda.c
7601 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_amanda.c   2003-11-26 21:43:24.000000000 +0100
7602 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_amanda.c       2003-12-10 23:13:21.271842272 +0100
7603 @@ -195,8 +195,6 @@
7604         struct ip_nat_helper *hlpr;
7605  
7606         hlpr = &ip_nat_amanda_helper;
7607 -       memset(hlpr, 0, sizeof(struct ip_nat_helper));
7608 -
7609         hlpr->tuple.dst.protonum = IPPROTO_UDP;
7610         hlpr->tuple.src.u.udp.port = htons(10080);
7611         hlpr->mask.src.u.udp.port = 0xFFFF;
7612 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_core.c
7613 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_core.c     2003-11-26 21:43:07.000000000 +0100
7614 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_core.c 2003-12-10 23:14:03.995347312 +0100
7615 @@ -90,9 +90,16 @@
7616         WRITE_UNLOCK(&ip_nat_lock);
7617  }
7618  
7619 -/* We do checksum mangling, so if they were wrong before they're still
7620 - * wrong.  Also works for incomplete packets (eg. ICMP dest
7621 - * unreachables.) */
7622 +/**
7623 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
7624 + * @oldvalinv: bit-inverted old value of 32bit word
7625 + * @newval: new value of 32bit word
7626 + * @oldcheck: old checksum value
7627 + *
7628 + * This function implements incremental checksum mangling, so if a checksum
7629 + * was wrong it will still be wrong after mangling.  Also works for incomplete
7630 + * packets (eg. ICMP dest unreachables).  Return value is the new checksum.
7631 + */
7632  u_int16_t
7633  ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
7634  {
7635 @@ -118,7 +125,14 @@
7636         return i;
7637  }
7638  
7639 -/* Is this tuple already taken? (not by us) */
7640 +/**
7641 + * ip_nat_used_tuple - Is this tuple already in use?
7642 + * @tuple: tuple to be used for this check
7643 + * @ignored_conntrack: conntrack excluded from this check
7644 + *
7645 + * This function checks for the reply (inverted) tuple in the conntrack
7646 + * hash.  This is necessarry with NAT, since there is no fixed mapping.
7647 + */
7648  int
7649  ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
7650                   const struct ip_conntrack *ignored_conntrack)
7651 @@ -432,7 +446,7 @@
7652         *tuple = *orig_tuple;
7653         while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
7654                != NULL) {
7655 -               DEBUGP("Found best for "); DUMP_TUPLE(tuple);
7656 +               DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple);
7657                 /* 3) The per-protocol part of the manip is made to
7658                    map into the range to make a unique tuple. */
7659  
7660 @@ -509,6 +523,19 @@
7661  #endif
7662  };
7663  
7664 +/**
7665 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
7666 + * @conntrack: conntrack on which we operate
7667 + * @mr: address/port range which is valid for this NAT mapping
7668 + * @hooknum: hook at which this NAT mapping applies
7669 + *
7670 + * This function is called by NAT targets (SNAT,DNAT,...) and by
7671 + * the NAT application helper modules.  It is called for the NEW packet
7672 + * of a connection in order to specify which NAT mappings shall apply to
7673 + * this connection at a given hook.
7674 + *
7675 + * Note: The reply mappings are created automagically by this function. 
7676 + */
7677  unsigned int
7678  ip_nat_setup_info(struct ip_conntrack *conntrack,
7679                   const struct ip_nat_multi_range *mr,
7680 @@ -573,9 +600,9 @@
7681                        HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
7682                        conntrack);
7683                 DEBUGP("Original: ");
7684 -               DUMP_TUPLE(&orig_tp);
7685 +               DUMP_TUPLE_RAW(&orig_tp);
7686                 DEBUGP("New: ");
7687 -               DUMP_TUPLE(&new_tuple);
7688 +               DUMP_TUPLE_RAW(&new_tuple);
7689  #endif
7690  
7691                 /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
7692 @@ -810,7 +837,7 @@
7693  
7694                 /* Have to grab read lock before sibling_list traversal */
7695                 READ_LOCK(&ip_conntrack_lock);
7696 -               list_for_each(cur_item, &ct->sibling_list) { 
7697 +               list_for_each_prev(cur_item, &ct->sibling_list) { 
7698                         exp = list_entry(cur_item, struct ip_conntrack_expect, 
7699                                          expected_list);
7700                                          
7701 @@ -1010,7 +1037,11 @@
7702         /* FIXME: Man, this is a hack.  <SIGH> */
7703         IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
7704         ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
7705 -
7706 +       
7707 +       /* Initialize fake conntrack so that NAT will skip it */
7708 +       ip_conntrack_untracked.nat.info.initialized |= 
7709 +               (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
7710
7711         return 0;
7712  }
7713  
7714 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_cuseeme.c
7715 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_cuseeme.c  1970-01-01 01:00:00.000000000 +0100
7716 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_cuseeme.c      2003-12-10 23:13:55.777596600 +0100
7717 @@ -0,0 +1,289 @@
7718 +/* CuSeeMe extension for UDP NAT alteration.
7719 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7720 + * based on ip_masq_cuseeme.c in 2.2 kernels
7721 + *
7722 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
7723 + *
7724 + *      This program is free software; you can redistribute it and/or
7725 + *      modify it under the terms of the GNU General Public License
7726 + *      as published by the Free Software Foundation; either version
7727 + *      2 of the License, or (at your option) any later version.
7728 + *
7729 + *      Module load syntax:
7730 + *      insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
7731 + *
7732 + *      Please give the ports of the CuSeeMe traffic you want to track.
7733 + *      If you don't specify ports, the default will be UDP port 7648.
7734 + *
7735 + *      CuSeeMe Protocol Documentation:
7736 + *      http://cu-seeme.net/squeek/tech/contents.html
7737 + *
7738 + */
7739 +
7740 +#include <linux/module.h>
7741 +#include <linux/netfilter_ipv4.h>
7742 +#include <linux/ip.h>
7743 +#include <linux/udp.h>
7744 +
7745 +#include <linux/netfilter.h>
7746 +#include <linux/netfilter_ipv4/ip_tables.h>
7747 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7748 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
7749 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7750 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7751 +
7752 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7753 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
7754 +MODULE_LICENSE("GPL");
7755 +
7756 +#define MAX_PORTS 8
7757 +
7758 +static int ports[MAX_PORTS];
7759 +static int ports_c = 0;
7760 +#ifdef MODULE_PARM
7761 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7762 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
7763 +#endif
7764 +
7765 +#if 0
7766 +#define DEBUGP printk
7767 +#else
7768 +#define DEBUGP(format, args...)
7769 +#endif
7770 +
7771 +/* process packet from client->reflector, possibly manipulate client IP in payload */
7772 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
7773 +                             struct ip_nat_info *info,
7774 +                             enum ip_conntrack_info ctinfo,
7775 +                             struct sk_buff **pskb,
7776 +                             char *data,
7777 +                             unsigned int datalen)
7778 +{
7779 +       char new_port_ip[6];
7780 +       struct cu_header *cu_head=(struct cu_header *)data;
7781 +       
7782 +       DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n", 
7783 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7784 +               
7785 +       /* At least check that the data at offset 10 is the client's port and IP address */
7786 +       if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
7787 +           (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
7788 +               DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n", 
7789 +                      NIPQUAD(cu_head->addr),
7790 +                      ntohs(cu_head->port),
7791 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7792 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
7793 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7794 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7795 +               /* at offset 10, replace 6 bytes containing port + IP address */
7796 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7797 +                                        10, 6, (char *)(new_port_ip), 6);
7798 +       } else 
7799 +               DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7800 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7801 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
7802 +                      NIPQUAD(cu_head->addr),
7803 +                      ntohs(cu_head->port));
7804 +}
7805 +
7806 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
7807 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
7808 +                             struct ip_nat_info *info,
7809 +                             enum ip_conntrack_info ctinfo,
7810 +                             struct sk_buff **pskb,
7811 +                             char *data,
7812 +                             unsigned int datalen)
7813 +{
7814 +       char new_port_ip[6];
7815 +       struct cu_header *cu_head = (struct cu_header *)data;
7816 +       struct oc_header *oc_head = (struct oc_header *)data; 
7817 +       struct client_info *ci; 
7818 +       int i, off;
7819 +
7820 +       
7821 +       DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n", 
7822 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7823 +               
7824 +       /* Check if we're really dealing with the client's port + IP address before rewriting */
7825 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
7826 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
7827 +               DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
7828 +                      NIPQUAD(cu_head->dest_addr),
7829 +                      ntohs(cu_head->dest_port),
7830 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7831 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
7832 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
7833 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7834 +               /* at offset 2, replace 6 bytes containing port + IP address */
7835 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7836 +                                        2, 6, (char *)(new_port_ip), 6);
7837 +       } else 
7838 +               DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7839 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7840 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
7841 +                      NIPQUAD(cu_head->dest_addr),
7842 +                      ntohs(cu_head->dest_port));
7843 +       
7844 +       /* Check if we're really dealing with the server's port + IP address before rewriting. 
7845 +          In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
7846 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
7847 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
7848 +               DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
7849 +                      NIPQUAD(cu_head->addr),
7850 +                      ntohs(cu_head->port),
7851 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
7852 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
7853 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
7854 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7855 +               /* at offset 10, replace 6 bytes containing port + IP address */
7856 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7857 +                                        10, 6, (char *)(new_port_ip), 6);
7858 +       } else 
7859 +               /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
7860 +                  is not that important so we're not logging this unless we're debugging */
7861 +               DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7862 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
7863 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
7864 +                      NIPQUAD(cu_head->addr),
7865 +                      ntohs(cu_head->port));
7866 +       
7867 +       /* Spin through client_info structs until we find our own */
7868 +       if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
7869 +               DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
7870 +               for(i=0, off=sizeof(struct oc_header);
7871 +                   (i < oc_head->client_count && 
7872 +                   off+sizeof(struct client_info) <= datalen); 
7873 +                   i++) {
7874 +                       ci=(struct client_info *)(data+off);
7875 +                       DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n", 
7876 +                              NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
7877 +                              (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7878 +                       if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
7879 +                               /* mangle this IP address */
7880 +                               DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
7881 +                                      NIPQUAD(ci->address), 
7882 +                                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7883 +                                      (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7884 +                               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7885 +                                                        (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4, 
7886 +                                                        (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
7887 +                               break;
7888 +                       } else 
7889 +                               off+=sizeof(struct client_info);
7890 +               }
7891 +       } else
7892 +               DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n", 
7893 +                      ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
7894 +}
7895 +
7896 +static unsigned int 
7897 +cuseeme_nat_help(struct ip_conntrack *ct,
7898 +                 struct ip_conntrack_expect *exp,
7899 +                 struct ip_nat_info *info,
7900 +                 enum ip_conntrack_info ctinfo,
7901 +                 unsigned int hooknum,
7902 +                 struct sk_buff **pskb)
7903 +{
7904 +       struct iphdr *iph = (*pskb)->nh.iph;
7905 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7906 +       int dir = CTINFO2DIR(ctinfo);
7907 +       unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
7908 +       char *data = (char *) &udph[1];
7909 +       
7910 +       DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
7911 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7912 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7913 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7914 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7915 +             );
7916 +       
7917 +       /* Only mangle things once: original direction in POST_ROUTING
7918 +          and reply direction on PRE_ROUTING. */
7919 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7920 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7921 +               DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
7922 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7923 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7924 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7925 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7926 +               return NF_ACCEPT;
7927 +       }
7928 +       
7929 +       if(datalen < sizeof(struct cu_header)) {
7930 +               /* packet too small */
7931 +               if (net_ratelimit())
7932 +                       printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n", 
7933 +                              datalen, sizeof(struct cu_header));
7934 +               return NF_ACCEPT;
7935 +       }
7936 +
7937 +
7938 +       /* In the debugging output, "outgoing" is from client to server, and
7939 +          "incoming" is from server to client */
7940 +       if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) 
7941 +               cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
7942 +       else 
7943 +               cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
7944 +
7945 +       return NF_ACCEPT;
7946 +}
7947 +
7948 +static struct ip_nat_helper cuseeme[MAX_PORTS];
7949 +static char cuseeme_names[MAX_PORTS][14];  /* cuseeme-65535 */
7950 +
7951 +static void fini(void)
7952 +{
7953 +       int i;
7954 +       
7955 +       for (i = 0 ; i < ports_c; i++) {
7956 +               DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
7957 +                      ip_nat_helper_unregister(&cuseeme[i]);
7958 +       }
7959 +}
7960 +
7961 +static int __init init(void)
7962 +{
7963 +       int i, ret = 0;
7964 +       char *tmpname;
7965 +
7966 +       if (!ports[0])
7967 +               ports[0] = CUSEEME_PORT;
7968 +               
7969 +       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7970 +               memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
7971 +
7972 +               cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
7973 +               cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
7974 +               cuseeme[i].mask.dst.protonum = 0xFFFF;
7975 +               cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
7976 +               cuseeme[i].help = cuseeme_nat_help;
7977 +               cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE + 
7978 +                                  IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
7979 +                                                             is stricly needed... */
7980 +               cuseeme[i].me = THIS_MODULE;
7981 +               cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
7982 +                       
7983 +               tmpname = &cuseeme_names[i][0];
7984 +               if (ports[i] == CUSEEME_PORT)
7985 +                       sprintf(tmpname, "cuseeme");
7986 +               else
7987 +                       sprintf(tmpname, "cuseeme-%d", ports[i]);
7988 +               cuseeme[i].name = tmpname;
7989 +                       
7990 +               DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
7991 +                      ports[i], cuseeme[i].name);
7992 +               ret = ip_nat_helper_register(&cuseeme[i]);
7993 +                       
7994 +               if (ret) {
7995 +                       printk("ip_nat_cuseeme: unable to register helper for port %d\n",
7996 +                              ports[i]);
7997 +                       fini();
7998 +                       return ret;
7999 +               }
8000 +               ports_c++;
8001 +       }
8002 +       return ret;
8003 +}
8004 +       
8005 +module_init(init);
8006 +module_exit(fini);
8007 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_h323.c
8008 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_h323.c     1970-01-01 01:00:00.000000000 +0100
8009 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_h323.c 2003-12-10 23:13:58.178231648 +0100
8010 @@ -0,0 +1,419 @@
8011 +/* 
8012 + * H.323 'brute force' extension for NAT alteration. 
8013 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8014 + *
8015 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
8016 + * (http://www.coritel.it/projects/sofia/nat.html)
8017 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
8018 + * the unregistered helpers to the conntrack entries.
8019 + */
8020 +
8021 +
8022 +#include <linux/module.h>
8023 +#include <linux/netfilter.h>
8024 +#include <linux/ip.h>
8025 +#include <net/checksum.h>
8026 +#include <net/tcp.h>
8027 +
8028 +#include <linux/netfilter_ipv4/lockhelp.h>
8029 +#include <linux/netfilter_ipv4/ip_nat.h>
8030 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8031 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8032 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
8033 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8034 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
8035 +
8036 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8037 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
8038 +MODULE_LICENSE("GPL");
8039 +
8040 +DECLARE_LOCK_EXTERN(ip_h323_lock);
8041 +struct module *ip_nat_h323 = THIS_MODULE;
8042 +
8043 +#if 0
8044 +#define DEBUGP printk
8045 +#else
8046 +#define DEBUGP(format, args...)
8047 +#endif
8048 +
8049 +/* FIXME: Time out? --RR */
8050 +
8051 +static unsigned int 
8052 +h225_nat_expected(struct sk_buff **pskb,
8053 +                 unsigned int hooknum,
8054 +                 struct ip_conntrack *ct,
8055 +                 struct ip_nat_info *info);
8056 +
8057 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8058 +                                 struct ip_conntrack_expect *exp,
8059 +                                 struct ip_nat_info *info,
8060 +                                 enum ip_conntrack_info ctinfo,
8061 +                                 unsigned int hooknum,
8062 +                                 struct sk_buff **pskb);
8063 +                 
8064 +static struct ip_nat_helper h245 = 
8065 +       { { NULL, NULL },
8066 +          "H.245",                             /* name */
8067 +         0,                                    /* flags */
8068 +         NULL,                                 /* module */
8069 +         { { 0, { 0 } },                       /* tuple */
8070 +           { 0, { 0 }, IPPROTO_TCP } },
8071 +         { { 0, { 0xFFFF } },                  /* mask */
8072 +           { 0, { 0 }, 0xFFFF } },
8073 +         h225_nat_help,                        /* helper */
8074 +         h225_nat_expected                     /* expectfn */
8075 +       };
8076 +
8077 +static unsigned int
8078 +h225_nat_expected(struct sk_buff **pskb,
8079 +                 unsigned int hooknum,
8080 +                 struct ip_conntrack *ct,
8081 +                 struct ip_nat_info *info)
8082 +{
8083 +       struct ip_nat_multi_range mr;
8084 +       u_int32_t newdstip, newsrcip, newip;
8085 +       u_int16_t port;
8086 +       struct ip_ct_h225_expect *exp_info;
8087 +       struct ip_ct_h225_master *master_info;
8088 +       struct ip_conntrack *master = master_ct(ct);
8089 +       unsigned int is_h225, ret;
8090 +       
8091 +       IP_NF_ASSERT(info);
8092 +       IP_NF_ASSERT(master);
8093 +
8094 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8095 +
8096 +       DEBUGP("h225_nat_expected: We have a connection!\n");
8097 +       master_info = &ct->master->expectant->help.ct_h225_info;
8098 +       exp_info = &ct->master->help.exp_h225_info;
8099 +
8100 +       LOCK_BH(&ip_h323_lock);
8101 +
8102 +       DEBUGP("master: ");
8103 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8104 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
8105 +       DEBUGP("conntrack: ");
8106 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8107 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
8108 +               /* Make connection go to the client. */
8109 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8110 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8111 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
8112 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8113 +       } else {
8114 +               /* Make the connection go to the server */
8115 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8116 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8117 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
8118 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8119 +       }
8120 +       port = exp_info->port;
8121 +       is_h225 = master_info->is_h225 == H225_PORT;
8122 +       UNLOCK_BH(&ip_h323_lock);
8123 +       
8124 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8125 +               newip = newsrcip;
8126 +       else
8127 +               newip = newdstip;
8128 +
8129 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8130 +
8131 +       mr.rangesize = 1;
8132 +       /* We don't want to manip the per-protocol, just the IPs... */
8133 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8134 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8135 +
8136 +       /* ... unless we're doing a MANIP_DST, in which case, make
8137 +          sure we map to the correct port */
8138 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8139 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8140 +               mr.range[0].min = mr.range[0].max
8141 +                       = ((union ip_conntrack_manip_proto)
8142 +                               { .tcp = { port } });
8143 +       }
8144 +
8145 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
8146 +       
8147 +       if (is_h225) {
8148 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
8149 +               /* NAT expectfn called with ip_nat_lock write-locked */
8150 +               info->helper = &h245;
8151 +       }
8152 +       return ret;
8153 +}
8154 +
8155 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
8156 +                                    struct sk_buff **pskb,
8157 +                                    enum ip_conntrack_info ctinfo)
8158 +{
8159 +       struct iphdr *iph = (*pskb)->nh.iph;
8160 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8161 +       char *data = (char *) tcph + tcph->doff * 4;
8162 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8163 +       u_int32_t datalen = tcplen - tcph->doff*4;
8164 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
8165 +       u_int32_t newip;
8166 +       u_int16_t port;
8167 +       int i;
8168 +
8169 +       MUST_BE_LOCKED(&ip_h323_lock);
8170 +
8171 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
8172 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8173 +                       ? "yes" : "no",
8174 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8175 +                       ? "yes" : "no");
8176 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8177 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
8178 +               return 1;
8179 +
8180 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
8181 +               info->offset[IP_CT_DIR_ORIGINAL], 
8182 +               info->offset[IP_CT_DIR_REPLY],
8183 +               tcplen);
8184 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8185 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8186 +
8187 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
8188 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
8189 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
8190 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
8191 +               if (!between(info->seq[i], ntohl(tcph->seq), 
8192 +                            ntohl(tcph->seq) + datalen))
8193 +                       continue;
8194 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
8195 +                            ntohl(tcph->seq) + datalen)) {
8196 +                       /* Partial retransmisison. It's a cracker being funky. */
8197 +                       if (net_ratelimit()) {
8198 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8199 +                                    info->seq[i],
8200 +                                    ntohl(tcph->seq),
8201 +                                    ntohl(tcph->seq) + datalen);
8202 +                       }
8203 +                       return 0;
8204 +               }
8205 +
8206 +               /* Change address inside packet to match way we're mapping
8207 +                  this connection. */
8208 +               if (i == IP_CT_DIR_ORIGINAL) {
8209 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
8210 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
8211 +               } else {
8212 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
8213 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
8214 +               }
8215 +
8216 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
8217 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
8218 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
8219 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8220 +
8221 +               /* Modify the packet */
8222 +               *(u_int32_t *)(data + info->offset[i]) = newip;
8223 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
8224 +       
8225 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
8226 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
8227 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
8228 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8229 +       }
8230 +
8231 +       /* fix checksum information */
8232 +
8233 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8234 +                                    datalen, 0);
8235 +
8236 +       tcph->check = 0;
8237 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8238 +                                  csum_partial((char *)tcph, tcph->doff*4,
8239 +                                          (*pskb)->csum));
8240 +       ip_send_check(iph);
8241 +
8242 +       return 1;
8243 +}
8244 +
8245 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
8246 +                          struct ip_conntrack *ct,
8247 +                          struct sk_buff **pskb,
8248 +                          enum ip_conntrack_info ctinfo,
8249 +                          struct ip_conntrack_expect *expect)
8250 +{
8251 +       u_int32_t newip;
8252 +       u_int16_t port;
8253 +       struct ip_conntrack_tuple newtuple;
8254 +       struct iphdr *iph = (*pskb)->nh.iph;
8255 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8256 +       char *data = (char *) tcph + tcph->doff * 4;
8257 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8258 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
8259 +       int is_h225;
8260 +
8261 +       MUST_BE_LOCKED(&ip_h323_lock);
8262 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
8263 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8264 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8265 +
8266 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
8267 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
8268 +               /* Partial retransmisison. It's a cracker being funky. */
8269 +               if (net_ratelimit()) {
8270 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8271 +                            expect->seq,
8272 +                            ntohl(tcph->seq),
8273 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
8274 +               }
8275 +               return 0;
8276 +       }
8277 +
8278 +       /* Change address inside packet to match way we're mapping
8279 +          this connection. */
8280 +       if (info->dir == IP_CT_DIR_REPLY) {
8281 +               /* Must be where client thinks server is */
8282 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8283 +               /* Expect something from client->server */
8284 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8285 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8286 +       } else {
8287 +               /* Must be where server thinks client is */
8288 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8289 +               /* Expect something from server->client */
8290 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8291 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8292 +       }
8293 +
8294 +       is_h225 = (master_info->is_h225 == H225_PORT);
8295 +
8296 +       if (is_h225) {
8297 +               newtuple.dst.protonum = IPPROTO_TCP;
8298 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
8299 +       } else {
8300 +               newtuple.dst.protonum = IPPROTO_UDP;
8301 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
8302 +       }
8303 +       
8304 +       /* Try to get same port: if not, try to change it. */
8305 +       for (port = ntohs(info->port); port != 0; port++) {
8306 +               if (is_h225)
8307 +                       newtuple.dst.u.tcp.port = htons(port);
8308 +               else
8309 +                       newtuple.dst.u.udp.port = htons(port);
8310 +
8311 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
8312 +                       break;
8313 +       }
8314 +       if (port == 0) {
8315 +               DEBUGP("h323_data_fixup: no free port found!\n");
8316 +               return 0;
8317 +       }
8318 +
8319 +       port = htons(port);
8320 +
8321 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
8322 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
8323 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
8324 +
8325 +       /* Modify the packet */
8326 +       *(u_int32_t *)(data + info->offset) = newip;
8327 +       *(u_int16_t *)(data + info->offset + 4) = port;
8328 +       
8329 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
8330 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
8331 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
8332 +
8333 +       /* fix checksum information  */
8334 +       /* FIXME: usually repeated multiple times in the case of H.245! */
8335 +
8336 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8337 +                                    tcplen - tcph->doff*4, 0);
8338 +
8339 +       tcph->check = 0;
8340 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8341 +                                  csum_partial((char *)tcph, tcph->doff*4,
8342 +                                          (*pskb)->csum));
8343 +       ip_send_check(iph);
8344 +
8345 +       return 1;
8346 +}
8347 +
8348 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8349 +                                 struct ip_conntrack_expect *exp,
8350 +                                 struct ip_nat_info *info,
8351 +                                 enum ip_conntrack_info ctinfo,
8352 +                                 unsigned int hooknum,
8353 +                                 struct sk_buff **pskb)
8354 +{
8355 +       int dir;
8356 +       struct ip_ct_h225_expect *exp_info;
8357 +       
8358 +       /* Only mangle things once: original direction in POST_ROUTING
8359 +          and reply direction on PRE_ROUTING. */
8360 +       dir = CTINFO2DIR(ctinfo);
8361 +       DEBUGP("nat_h323: dir %s at hook %s\n",
8362 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8363 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8364 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8365 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8366 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8367 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8368 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
8369 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8370 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8371 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8372 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8373 +               return NF_ACCEPT;
8374 +       }
8375 +
8376 +       if (!exp) {
8377 +               LOCK_BH(&ip_h323_lock);
8378 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
8379 +                       UNLOCK_BH(&ip_h323_lock);
8380 +                       return NF_DROP;
8381 +               }
8382 +               UNLOCK_BH(&ip_h323_lock);
8383 +               return NF_ACCEPT;
8384 +       }
8385 +               
8386 +       exp_info = &exp->help.exp_h225_info;
8387 +
8388 +       LOCK_BH(&ip_h323_lock);
8389 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
8390 +               UNLOCK_BH(&ip_h323_lock);
8391 +               return NF_DROP;
8392 +       }
8393 +       UNLOCK_BH(&ip_h323_lock);
8394 +
8395 +       return NF_ACCEPT;
8396 +}
8397 +
8398 +static struct ip_nat_helper h225 = 
8399 +       { { NULL, NULL },
8400 +         "H.225",                                      /* name */
8401 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
8402 +         THIS_MODULE,                                  /* module */
8403 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
8404 +           { 0, { 0 }, IPPROTO_TCP } },
8405 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
8406 +           { 0, { 0 }, 0xFFFF } },
8407 +         h225_nat_help,                                /* helper */
8408 +         h225_nat_expected                             /* expectfn */
8409 +       };
8410 +
8411 +static int __init init(void)
8412 +{
8413 +       int ret;
8414 +       
8415 +       ret = ip_nat_helper_register(&h225);
8416 +
8417 +       if (ret != 0)
8418 +               printk("ip_nat_h323: cannot initialize the module!\n");
8419 +
8420 +       return ret;
8421 +}
8422 +
8423 +static void __exit fini(void)
8424 +{
8425 +       ip_nat_helper_unregister(&h225);
8426 +}
8427 +
8428 +module_init(init);
8429 +module_exit(fini);
8430 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_helper.c
8431 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_helper.c   2003-11-26 21:43:08.000000000 +0100
8432 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_helper.c       2003-12-10 23:14:03.996347160 +0100
8433 @@ -147,9 +147,19 @@
8434         return 1;
8435  }
8436  
8437 -/* Generic function for mangling variable-length address changes inside
8438 - * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
8439 - * command in FTP).
8440 +/**
8441 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
8442 + * @skb: pointer to skb of packet on which we operate
8443 + * @ct: conntrack of the connection to which this packet belongs
8444 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8445 + * @match_offset: offset in bytes where to-be-manipulated part starts
8446 + * @match_len: lenght of the to-be-manipulated part
8447 + * @rep_buffer: pointer to buffer containing replacement
8448 + * @rep_len: length of replacement
8449 + *
8450 + * Generic function for mangling fixed and variable-length changes inside
8451 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command 
8452 + * in FTP).
8453   *
8454   * Takes care about all the nasty sequence number changes, checksumming,
8455   * skb enlargement, ...
8456 @@ -195,16 +205,27 @@
8457         return 1;
8458  }
8459                         
8460 -/* Generic function for mangling variable-length address changes inside
8461 - * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8462 - * command in the Amanda protocol)
8463 +/**
8464 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
8465 + * @skb: pointer to skb of packet on which we operate
8466 + * @ct: conntrack of the connection to which this packet belongs
8467 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8468 + * @match_offset: offset in bytes where to-be-manipulated part starts
8469 + * @match_len: lenght of the to-be-manipulated part
8470 + * @rep_buffer: pointer to buffer containing replacement
8471 + * @rep_len: length of replacement
8472 + *
8473 + * Generic function for mangling fixed and variable-length changes inside
8474 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8475 + * commad in the Amanda protocol)
8476   *
8477   * Takes care about all the nasty sequence number changes, checksumming,
8478   * skb enlargement, ...
8479   *
8480 - * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
8481 - *       should be fairly easy to do.
8482 - */
8483 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
8484 + *
8485 + * */
8486 +
8487  int 
8488  ip_nat_mangle_udp_packet(struct sk_buff **pskb,
8489                          struct ip_conntrack *ct,
8490 @@ -402,6 +423,13 @@
8491         return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
8492  }
8493  
8494 +/**
8495 + * ip_nat_helper_register - Register NAT application helper
8496 + * @me: structure describing the helper
8497 + *
8498 + * This function is called by NAT application helpers to register
8499 + * themselves with the NAT core.
8500 + */
8501  int ip_nat_helper_register(struct ip_nat_helper *me)
8502  {
8503         int ret = 0;
8504 @@ -428,6 +456,13 @@
8505         return ret;
8506  }
8507  
8508 +/**
8509 + * ip_nat_helper_unregister - Unregister NAT application helper
8510 + * @me: structure describing the helper
8511 + *
8512 + * This function is called by NAT application helpers to unregister
8513 + * themselves from the NAT core.
8514 + */
8515  void ip_nat_helper_unregister(struct ip_nat_helper *me)
8516  {
8517         WRITE_LOCK(&ip_nat_lock);
8518 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_mms.c
8519 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_mms.c      1970-01-01 01:00:00.000000000 +0100
8520 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_mms.c  2003-12-10 23:14:02.757535488 +0100
8521 @@ -0,0 +1,350 @@
8522 +/* MMS extension for TCP NAT alteration.
8523 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
8524 + * based on ip_nat_ftp.c and ip_nat_irc.c
8525 + *
8526 + * ip_nat_mms.c v0.3 2002-09-22
8527 + *
8528 + *      This program is free software; you can redistribute it and/or
8529 + *      modify it under the terms of the GNU General Public License
8530 + *      as published by the Free Software Foundation; either version
8531 + *      2 of the License, or (at your option) any later version.
8532 + *
8533 + *      Module load syntax:
8534 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
8535 + *
8536 + *      Please give the ports of all MMS servers You wish to connect to.
8537 + *      If you don't specify ports, the default will be TCP port 1755.
8538 + *
8539 + *      More info on MMS protocol, firewalls and NAT:
8540 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
8541 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
8542 + *
8543 + *      The SDP project people are reverse-engineering MMS:
8544 + *      http://get.to/sdp
8545 + */
8546 +
8547 +/* FIXME: issue with UDP & fragmentation with this URL: 
8548 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
8549 +   may be related to out-of-order first packets:
8550 +   basically the expectation is set up correctly, then the server sends
8551 +   a first UDP packet which is fragmented plus arrives out-of-order.
8552 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
8553 +   an ICMP unreachable back to the server */
8554 +
8555 +#include <linux/module.h>
8556 +#include <linux/netfilter_ipv4.h>
8557 +#include <linux/ip.h>
8558 +#include <linux/tcp.h>
8559 +#include <net/tcp.h>
8560 +#include <linux/netfilter_ipv4/ip_nat.h>
8561 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8562 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8563 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
8564 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8565 +
8566 +#if 0 
8567 +#define DEBUGP printk
8568 +#define DUMP_BYTES(address, counter)                                \
8569 +({                                                                  \
8570 +       int temp_counter;                                           \
8571 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
8572 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
8573 +       };                                                          \
8574 +       DEBUGP("\n");                                               \
8575 +})
8576 +#else
8577 +#define DEBUGP(format, args...)
8578 +#define DUMP_BYTES(address, counter)
8579 +#endif
8580 +
8581 +#define MAX_PORTS 8
8582 +static int ports[MAX_PORTS];
8583 +static int ports_c = 0;
8584 +
8585 +#ifdef MODULE_PARM
8586 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8587 +#endif
8588 +
8589 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
8590 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
8591 +MODULE_LICENSE("GPL");
8592 +
8593 +DECLARE_LOCK_EXTERN(ip_mms_lock);
8594 +
8595 +/* FIXME: Time out? --RR */
8596 +
8597 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
8598 +                          struct ip_conntrack *ct,
8599 +                          struct sk_buff **pskb,
8600 +                          enum ip_conntrack_info ctinfo,
8601 +                          struct ip_conntrack_expect *expect)
8602 +{
8603 +       u_int32_t newip;
8604 +       struct ip_conntrack_tuple t;
8605 +       struct iphdr *iph = (*pskb)->nh.iph;
8606 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8607 +       char *data = (char *)tcph + tcph->doff * 4;
8608 +       int i, j, k, port;
8609 +       u_int16_t mms_proto;
8610 +
8611 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
8612 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
8613 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
8614 +
8615 +       int zero_padding;
8616 +
8617 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
8618 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
8619 +       char proto_string[6];
8620 +       
8621 +       MUST_BE_LOCKED(&ip_mms_lock);
8622 +
8623 +       /* what was the protocol again ? */
8624 +       mms_proto = expect->tuple.dst.protonum;
8625 +       sprintf(proto_string, "%u", mms_proto);
8626 +       
8627 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
8628 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
8629 +              mms_proto == IPPROTO_UDP ? "UDP"
8630 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
8631 +       
8632 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8633 +
8634 +       /* Alter conntrack's expectations. */
8635 +       t = expect->tuple;
8636 +       t.dst.ip = newip;
8637 +       for (port = ct_mms_info->port; port != 0; port++) {
8638 +               t.dst.u.tcp.port = htons(port);
8639 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
8640 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
8641 +                       break;
8642 +               }
8643 +       }
8644 +       
8645 +       if(port == 0)
8646 +               return 0;
8647 +
8648 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
8649 +               NIPQUAD(newip),
8650 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
8651 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
8652 +               port);
8653 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
8654 +       
8655 +       memset(unicode_buffer, 0, sizeof(char)*75);
8656 +
8657 +       for (i=0; i<strlen(buffer); ++i)
8658 +               *(unicode_buffer+i*2)=*(buffer+i);
8659 +       
8660 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
8661 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
8662 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
8663 +       
8664 +       /* add end of packet to it */
8665 +       for (j=0; j<ct_mms_info->padding; ++j) {
8666 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
8667 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
8668 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
8669 +       }
8670 +
8671 +       /* pad with zeroes at the end ? see explanation of weird math below */
8672 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
8673 +       for (k=0; k<zero_padding; ++k)
8674 +               *(unicode_buffer+i*2+j+k)= (char)0;
8675 +       
8676 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
8677 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8678 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8679 +       
8680 +       /* explanation, before I forget what I did:
8681 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
8682 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
8683 +          but note that things may have to be padded with zeroes to align by 8 
8684 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
8685 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
8686 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
8687 +       *mms_messageLength = *mms_chunkLenLV*8;
8688 +       
8689 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8690 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8691 +       
8692 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
8693 +                                expect->seq - ntohl(tcph->seq),
8694 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
8695 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
8696 +       DUMP_BYTES(unicode_buffer, 60);
8697 +       
8698 +       return 1;
8699 +}
8700 +
8701 +static unsigned int
8702 +mms_nat_expected(struct sk_buff **pskb,
8703 +                 unsigned int hooknum,
8704 +                 struct ip_conntrack *ct,
8705 +                 struct ip_nat_info *info)
8706 +{
8707 +       struct ip_nat_multi_range mr;
8708 +       u_int32_t newdstip, newsrcip, newip;
8709 +
8710 +       struct ip_conntrack *master = master_ct(ct);
8711 +
8712 +       IP_NF_ASSERT(info);
8713 +       IP_NF_ASSERT(master);
8714 +
8715 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8716 +
8717 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
8718 +
8719 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8720 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8721 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
8722 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8723 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8724 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8725 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
8726 +
8727 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8728 +               newip = newsrcip;
8729 +       else
8730 +               newip = newdstip;
8731 +
8732 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8733 +
8734 +       mr.rangesize = 1;
8735 +       /* We don't want to manip the per-protocol, just the IPs. */
8736 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8737 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8738 +
8739 +       return ip_nat_setup_info(ct, &mr, hooknum);
8740 +}
8741 +
8742 +
8743 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
8744 +                        struct ip_conntrack_expect *exp,
8745 +                        struct ip_nat_info *info,
8746 +                        enum ip_conntrack_info ctinfo,
8747 +                        unsigned int hooknum,
8748 +                        struct sk_buff **pskb)
8749 +{
8750 +       struct iphdr *iph = (*pskb)->nh.iph;
8751 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8752 +       unsigned int datalen;
8753 +       int dir;
8754 +       struct ip_ct_mms_expect *ct_mms_info;
8755 +
8756 +       if (!exp)
8757 +               DEBUGP("ip_nat_mms: no exp!!");
8758 +
8759 +       ct_mms_info = &exp->help.exp_mms_info;
8760 +       
8761 +       /* Only mangle things once: original direction in POST_ROUTING
8762 +          and reply direction on PRE_ROUTING. */
8763 +       dir = CTINFO2DIR(ctinfo);
8764 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8765 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8766 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
8767 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8768 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8769 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8770 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8771 +               return NF_ACCEPT;
8772 +       }
8773 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
8774 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8775 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8776 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8777 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8778 +       
8779 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
8780 +       
8781 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
8782 +              exp->seq + ct_mms_info->len,
8783 +              ntohl(tcph->seq),
8784 +              ntohl(tcph->seq) + datalen);
8785 +       
8786 +       LOCK_BH(&ip_mms_lock);
8787 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
8788 +       if (between(exp->seq + ct_mms_info->len,
8789 +           ntohl(tcph->seq),
8790 +           ntohl(tcph->seq) + datalen)) {
8791 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
8792 +                       UNLOCK_BH(&ip_mms_lock);
8793 +                       return NF_DROP;
8794 +               }
8795 +       } else {
8796 +               /* Half a match?  This means a partial retransmisison.
8797 +                  It's a cracker being funky. */
8798 +               if (net_ratelimit()) {
8799 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
8800 +                              exp->seq, ct_mms_info->len,
8801 +                              ntohl(tcph->seq),
8802 +                              ntohl(tcph->seq) + datalen);
8803 +               }
8804 +               UNLOCK_BH(&ip_mms_lock);
8805 +               return NF_DROP;
8806 +       }
8807 +       UNLOCK_BH(&ip_mms_lock);
8808 +       
8809 +       return NF_ACCEPT;
8810 +}
8811 +
8812 +static struct ip_nat_helper mms[MAX_PORTS];
8813 +static char mms_names[MAX_PORTS][10];
8814 +
8815 +/* Not __exit: called from init() */
8816 +static void fini(void)
8817 +{
8818 +       int i;
8819 +
8820 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8821 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
8822 +               ip_nat_helper_unregister(&mms[i]);
8823 +       }
8824 +}
8825 +
8826 +static int __init init(void)
8827 +{
8828 +       int i, ret = 0;
8829 +       char *tmpname;
8830 +
8831 +       if (ports[0] == 0)
8832 +               ports[0] = MMS_PORT;
8833 +
8834 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8835 +
8836 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
8837 +
8838 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
8839 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
8840 +               mms[i].mask.dst.protonum = 0xFFFF;
8841 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
8842 +               mms[i].help = mms_nat_help;
8843 +               mms[i].me = THIS_MODULE;
8844 +               mms[i].flags = 0;
8845 +               mms[i].expect = mms_nat_expected;
8846 +
8847 +               tmpname = &mms_names[i][0];
8848 +               if (ports[i] == MMS_PORT)
8849 +                       sprintf(tmpname, "mms");
8850 +               else
8851 +                       sprintf(tmpname, "mms-%d", i);
8852 +               mms[i].name = tmpname;
8853 +
8854 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
8855 +                               ports[i]);
8856 +               ret = ip_nat_helper_register(&mms[i]);
8857 +
8858 +               if (ret) {
8859 +                       printk("ip_nat_mms: error registering "
8860 +                              "helper for port %d\n", ports[i]);
8861 +                       fini();
8862 +                       return ret;
8863 +               }
8864 +               ports_c++;
8865 +       }
8866 +
8867 +       return ret;
8868 +}
8869 +
8870 +module_init(init);
8871 +module_exit(fini);
8872 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_pptp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_pptp.c
8873 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_pptp.c     1970-01-01 01:00:00.000000000 +0100
8874 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_pptp.c 2003-11-17 09:09:34.000000000 +0100
8875 @@ -0,0 +1,475 @@
8876 +/*
8877 + * ip_nat_pptp.c       - Version 1.5
8878 + *
8879 + * NAT support for PPTP (Point to Point Tunneling Protocol).
8880 + * PPTP is a a protocol for creating virtual private networks.
8881 + * It is a specification defined by Microsoft and some vendors
8882 + * working with Microsoft.  PPTP is built on top of a modified
8883 + * version of the Internet Generic Routing Encapsulation Protocol.
8884 + * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
8885 + * PPTP can be found in RFC 2637
8886 + *
8887 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
8888 + *
8889 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
8890 + *
8891 + * TODO: - Support for multiple calls within one session
8892 + *        (needs netfilter newnat code)
8893 + *      - NAT to a unique tuple, not to TCP source port
8894 + *        (needs netfilter tuple reservation)
8895 + *
8896 + * Changes:
8897 + *     2002-02-10 - Version 1.3
8898 + *       - Use ip_nat_mangle_tcp_packet() because of cloned skb's
8899 + *        in local connections (Philip Craig <philipc@snapgear.com>)
8900 + *       - add checks for magicCookie and pptp version
8901 + *       - make argument list of pptp_{out,in}bound_packet() shorter
8902 + *       - move to C99 style initializers
8903 + *       - print version number at module loadtime
8904 + *     2003-09-22 - Version 1.5
8905 + *       - use SNATed tcp sourceport as callid, since we get called before
8906 + *         TCP header is mangled (Philip Craig <philipc@snapgear.com>)
8907 + * 
8908 + */
8909 +
8910 +#include <linux/config.h>
8911 +#include <linux/module.h>
8912 +#include <linux/ip.h>
8913 +#include <linux/tcp.h>
8914 +#include <net/tcp.h>
8915 +#include <linux/netfilter_ipv4/ip_nat.h>
8916 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8917 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8918 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
8919 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8920 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
8921 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
8922 +
8923 +#define IP_NAT_PPTP_VERSION "1.5"
8924 +
8925 +MODULE_LICENSE("GPL");
8926 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
8927 +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
8928 +
8929 +
8930 +#if 0
8931 +#include "ip_conntrack_pptp_priv.h"
8932 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
8933 +                                      ": " format, ## args)
8934 +#else
8935 +#define DEBUGP(format, args...)
8936 +#endif
8937 +
8938 +static unsigned int
8939 +pptp_nat_expected(struct sk_buff **pskb,
8940 +                 unsigned int hooknum,
8941 +                 struct ip_conntrack *ct,
8942 +                 struct ip_nat_info *info)
8943 +{
8944 +       struct ip_conntrack *master = master_ct(ct);
8945 +       struct ip_nat_multi_range mr;
8946 +       struct ip_ct_pptp_master *ct_pptp_info;
8947 +       struct ip_nat_pptp *nat_pptp_info;
8948 +       u_int32_t newip, newcid;
8949 +       int ret;
8950 +
8951 +       IP_NF_ASSERT(info);
8952 +       IP_NF_ASSERT(master);
8953 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8954 +
8955 +       DEBUGP("we have a connection!\n");
8956 +
8957 +       LOCK_BH(&ip_pptp_lock);
8958 +       ct_pptp_info = &master->help.ct_pptp_info;
8959 +       nat_pptp_info = &master->nat.help.nat_pptp_info;
8960 +
8961 +       /* need to alter GRE tuple because conntrack expectfn() used 'wrong'
8962 +        * (unmanipulated) values */
8963 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8964 +               DEBUGP("completing tuples with NAT info \n");
8965 +               /* we can do this, since we're unconfirmed */
8966 +               if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
8967 +                       htonl(ct_pptp_info->pac_call_id)) {     
8968 +                       /* assume PNS->PAC */
8969 +                       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8970 +                               htonl(nat_pptp_info->pns_call_id);
8971 +                       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8972 +                               htonl(nat_pptp_info->pns_call_id);
8973 +                       newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8974 +                       newcid = htonl(nat_pptp_info->pac_call_id);
8975 +               } else {
8976 +                       /* assume PAC->PNS */
8977 +                       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8978 +                               htonl(nat_pptp_info->pac_call_id);
8979 +                       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8980 +                               htonl(nat_pptp_info->pac_call_id);
8981 +                       newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8982 +                       newcid = htonl(nat_pptp_info->pns_call_id);
8983 +               }
8984 +       } else {
8985 +               if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
8986 +                       htonl(ct_pptp_info->pac_call_id)) {     
8987 +                       /* assume PNS->PAC */
8988 +                       newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8989 +                       newcid = htonl(ct_pptp_info->pns_call_id);
8990 +               }
8991 +               else {
8992 +                       /* assume PAC->PNS */
8993 +                       newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8994 +                       newcid = htonl(ct_pptp_info->pac_call_id);
8995 +               }
8996 +       }
8997 +
8998 +       mr.rangesize = 1;
8999 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
9000 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
9001 +       mr.range[0].min = mr.range[0].max = 
9002 +               ((union ip_conntrack_manip_proto ) { newcid }); 
9003 +       DEBUGP("change ip to %u.%u.%u.%u\n", 
9004 +               NIPQUAD(newip));
9005 +       DEBUGP("change key to 0x%x\n", ntohl(newcid));
9006 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
9007 +
9008 +       UNLOCK_BH(&ip_pptp_lock);
9009 +
9010 +       return ret;
9011 +
9012 +}
9013 +
9014 +/* outbound packets == from PNS to PAC */
9015 +static inline unsigned int
9016 +pptp_outbound_pkt(struct sk_buff **pskb,
9017 +                 struct ip_conntrack *ct,
9018 +                 enum ip_conntrack_info ctinfo,
9019 +                 struct ip_conntrack_expect *exp)
9020 +
9021 +{
9022 +       struct iphdr *iph = (*pskb)->nh.iph;
9023 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9024 +       struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
9025 +                                       ((void *)tcph + tcph->doff*4);
9026 +
9027 +       struct PptpControlHeader *ctlh;
9028 +       union pptp_ctrl_union pptpReq;
9029 +       struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9030 +       struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9031 +
9032 +       u_int16_t msg, *cid = NULL, new_callid;
9033 +
9034 +       /* FIXME: size checks !!! */
9035 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9036 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9037 +
9038 +       new_callid = htons(ct_pptp_info->pns_call_id);
9039 +       
9040 +       switch (msg = ntohs(ctlh->messageType)) {
9041 +               case PPTP_OUT_CALL_REQUEST:
9042 +                       cid = &pptpReq.ocreq->callID;
9043 +                       /* FIXME: ideally we would want to reserve a call ID
9044 +                        * here.  current netfilter NAT core is not able to do
9045 +                        * this :( For now we use TCP source port. This breaks
9046 +                        * multiple calls within one control session */
9047 +
9048 +                       /* save original call ID in nat_info */
9049 +                       nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
9050 +
9051 +                       /* don't use tcph->source since we are at a DSTmanip
9052 +                        * hook (e.g. PREROUTING) and pkt is not mangled yet */
9053 +                       new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
9054 +
9055 +                       /* save new call ID in ct info */
9056 +                       ct_pptp_info->pns_call_id = ntohs(new_callid);
9057 +                       break;
9058 +               case PPTP_IN_CALL_REPLY:
9059 +                       cid = &pptpReq.icreq->callID;
9060 +                       break;
9061 +               case PPTP_CALL_CLEAR_REQUEST:
9062 +                       cid = &pptpReq.clrreq->callID;
9063 +                       break;
9064 +               default:
9065 +                       DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
9066 +                             (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9067 +                       /* fall through */
9068 +
9069 +               case PPTP_SET_LINK_INFO:
9070 +                       /* only need to NAT in case PAC is behind NAT box */
9071 +               case PPTP_START_SESSION_REQUEST:
9072 +               case PPTP_START_SESSION_REPLY:
9073 +               case PPTP_STOP_SESSION_REQUEST:
9074 +               case PPTP_STOP_SESSION_REPLY:
9075 +               case PPTP_ECHO_REQUEST:
9076 +               case PPTP_ECHO_REPLY:
9077 +                       /* no need to alter packet */
9078 +                       return NF_ACCEPT;
9079 +       }
9080 +
9081 +       IP_NF_ASSERT(cid);
9082 +
9083 +       DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9084 +               ntohs(*cid), ntohs(new_callid));
9085 +
9086 +       /* mangle packet */
9087 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
9088 +                                sizeof(new_callid), (char *)&new_callid,
9089 +                                sizeof(new_callid));
9090 +
9091 +       return NF_ACCEPT;
9092 +}
9093 +
9094 +/* inbound packets == from PAC to PNS */
9095 +static inline unsigned int
9096 +pptp_inbound_pkt(struct sk_buff **pskb,
9097 +                struct ip_conntrack *ct,
9098 +                enum ip_conntrack_info ctinfo,
9099 +                struct ip_conntrack_expect *oldexp)
9100 +{
9101 +       struct iphdr *iph = (*pskb)->nh.iph;
9102 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9103 +       struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
9104 +                                       ((void *)tcph + tcph->doff*4);
9105 +
9106 +       struct PptpControlHeader *ctlh;
9107 +       union pptp_ctrl_union pptpReq;
9108 +       struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9109 +       struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9110 +
9111 +       u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
9112 +       u_int32_t old_dst_ip;
9113 +
9114 +       struct ip_conntrack_tuple t, inv_t;
9115 +       struct ip_conntrack_tuple *orig_t, *reply_t;
9116 +
9117 +       /* FIXME: size checks !!! */
9118 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9119 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9120 +
9121 +       new_pcid = htons(nat_pptp_info->pns_call_id);
9122 +
9123 +       switch (msg = ntohs(ctlh->messageType)) {
9124 +       case PPTP_OUT_CALL_REPLY:
9125 +               pcid = &pptpReq.ocack->peersCallID;     
9126 +               cid = &pptpReq.ocack->callID;
9127 +               if (!oldexp) {
9128 +                       DEBUGP("outcall but no expectation\n");
9129 +                       break;
9130 +               }
9131 +               old_dst_ip = oldexp->tuple.dst.ip;
9132 +               t = oldexp->tuple;
9133 +               invert_tuplepr(&inv_t, &t);
9134 +
9135 +               /* save original PAC call ID in nat_info */
9136 +               nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
9137 +
9138 +               /* alter expectation */
9139 +               orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
9140 +               reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
9141 +               if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
9142 +                       /* expectation for PNS->PAC direction */
9143 +                       t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9144 +                       t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9145 +                       inv_t.src.ip = reply_t->src.ip;
9146 +                       inv_t.dst.ip = reply_t->dst.ip;
9147 +                       inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9148 +                       inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9149 +               } else {
9150 +                       /* expectation for PAC->PNS direction */
9151 +                       t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9152 +                       t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9153 +                       inv_t.src.ip = orig_t->src.ip;
9154 +                       inv_t.dst.ip = orig_t->dst.ip;
9155 +                       inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9156 +                       inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9157 +               }
9158 +
9159 +               if (!ip_conntrack_change_expect(oldexp, &t)) {
9160 +                       DEBUGP("successfully changed expect\n");
9161 +               } else {
9162 +                       DEBUGP("can't change expect\n");
9163 +               }
9164 +               ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
9165 +               ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
9166 +               break;
9167 +       case PPTP_IN_CALL_CONNECT:
9168 +               pcid = &pptpReq.iccon->peersCallID;
9169 +               if (!oldexp)
9170 +                       break;
9171 +               old_dst_ip = oldexp->tuple.dst.ip;
9172 +               t = oldexp->tuple;
9173 +
9174 +               /* alter expectation, no need for callID */
9175 +               if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
9176 +                       /* expectation for PNS->PAC direction */
9177 +                       t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9178 +               } else {
9179 +                       /* expectation for PAC->PNS direction */
9180 +                       t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9181 +               }
9182 +
9183 +               if (!ip_conntrack_change_expect(oldexp, &t)) {
9184 +                       DEBUGP("successfully changed expect\n");
9185 +               } else {
9186 +                       DEBUGP("can't change expect\n");
9187 +               }
9188 +               break;
9189 +       case PPTP_IN_CALL_REQUEST:
9190 +               /* only need to nat in case PAC is behind NAT box */
9191 +               break;
9192 +       case PPTP_WAN_ERROR_NOTIFY:
9193 +               pcid = &pptpReq.wanerr->peersCallID;
9194 +               break;
9195 +       case PPTP_CALL_DISCONNECT_NOTIFY:
9196 +               pcid = &pptpReq.disc->callID;
9197 +               break;
9198 +
9199 +       default:
9200 +               DEBUGP("unknown inbound packet %s\n",
9201 +                       (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9202 +               /* fall through */
9203 +
9204 +       case PPTP_START_SESSION_REQUEST:
9205 +       case PPTP_START_SESSION_REPLY:
9206 +       case PPTP_STOP_SESSION_REQUEST:
9207 +       case PPTP_STOP_SESSION_REPLY:
9208 +       case PPTP_ECHO_REQUEST:
9209 +       case PPTP_ECHO_REPLY:
9210 +               /* no need to alter packet */
9211 +               return NF_ACCEPT;
9212 +       }
9213 +
9214 +       /* mangle packet */
9215 +       IP_NF_ASSERT(pcid);
9216 +       DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
9217 +               ntohs(*pcid), ntohs(new_pcid));
9218 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
9219 +                                sizeof(new_pcid), (char *)&new_pcid, 
9220 +                                sizeof(new_pcid));
9221 +
9222 +       if (new_cid) {
9223 +               IP_NF_ASSERT(cid);
9224 +               DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9225 +                       ntohs(*cid), ntohs(new_cid));
9226 +               ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
9227 +                                        (void *)cid - (void *)pptph, 
9228 +                                        sizeof(new_cid), (char *)&new_cid, 
9229 +                                        sizeof(new_cid));
9230 +       }
9231 +
9232 +       /* great, at least we don't need to resize packets */
9233 +       return NF_ACCEPT;
9234 +}
9235 +
9236 +
9237 +static unsigned int tcp_help(struct ip_conntrack *ct,
9238 +                            struct ip_conntrack_expect *exp,
9239 +                            struct ip_nat_info *info,
9240 +                            enum ip_conntrack_info ctinfo,
9241 +                            unsigned int hooknum, struct sk_buff **pskb)
9242 +{
9243 +       struct iphdr *iph = (*pskb)->nh.iph;
9244 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9245 +       unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
9246 +       struct pptp_pkt_hdr *pptph;
9247 +
9248 +       int dir;
9249 +
9250 +       DEBUGP("entering\n");
9251 +
9252 +       /* Only mangle things once: DST for original direction
9253 +          and SRC for reply direction. */
9254 +       dir = CTINFO2DIR(ctinfo);
9255 +       if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
9256 +            && dir == IP_CT_DIR_ORIGINAL)
9257 +             || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
9258 +                 && dir == IP_CT_DIR_REPLY))) {
9259 +               DEBUGP("Not touching dir %s at hook %s\n",
9260 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9261 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9262 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9263 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
9264 +                      : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
9265 +               return NF_ACCEPT;
9266 +       }
9267 +
9268 +       /* if packet is too small, just skip it */
9269 +       if (datalen < sizeof(struct pptp_pkt_hdr)+
9270 +                     sizeof(struct PptpControlHeader)) {
9271 +               DEBUGP("pptp packet too short\n");
9272 +               return NF_ACCEPT;       
9273 +       }
9274 +
9275 +       pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
9276 +
9277 +       /* if it's not a control message, we can't handle it */
9278 +       if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
9279 +           ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
9280 +               DEBUGP("not a pptp control packet\n");
9281 +               return NF_ACCEPT;
9282 +       }
9283 +
9284 +       LOCK_BH(&ip_pptp_lock);
9285 +
9286 +       if (dir == IP_CT_DIR_ORIGINAL) {
9287 +               /* reuqests sent by client to server (PNS->PAC) */
9288 +               pptp_outbound_pkt(pskb, ct, ctinfo, exp);
9289 +       } else {
9290 +               /* response from the server to the client (PAC->PNS) */
9291 +               pptp_inbound_pkt(pskb, ct, ctinfo, exp);
9292 +       }
9293 +
9294 +       UNLOCK_BH(&ip_pptp_lock);
9295 +
9296 +       return NF_ACCEPT;
9297 +}
9298 +
9299 +/* nat helper struct for control connection */
9300 +static struct ip_nat_helper pptp_tcp_helper = { 
9301 +       .list = { NULL, NULL },
9302 +       .name = "pptp", 
9303 +       .flags = IP_NAT_HELPER_F_ALWAYS, 
9304 +       .me = THIS_MODULE,
9305 +       .tuple = { .src = { .ip = 0, 
9306 +                           .u = { .tcp = { .port = 
9307 +                                       __constant_htons(PPTP_CONTROL_PORT) } 
9308 +                                } 
9309 +                         },
9310 +                  .dst = { .ip = 0, 
9311 +                           .u = { .all = 0 }, 
9312 +                           .protonum = IPPROTO_TCP 
9313 +                         } 
9314 +                },
9315 +
9316 +       .mask = { .src = { .ip = 0, 
9317 +                          .u = { .tcp = { .port = 0xFFFF } } 
9318 +                        },
9319 +                 .dst = { .ip = 0, 
9320 +                          .u = { .all = 0 }, 
9321 +                          .protonum = 0xFFFF 
9322 +                        } 
9323 +               },
9324 +       .help = tcp_help, 
9325 +       .expect = pptp_nat_expected 
9326 +};
9327 +
9328 +                         
9329 +static int __init init(void)
9330 +{
9331 +       DEBUGP("%s: registering NAT helper\n", __FILE__);
9332 +       if (ip_nat_helper_register(&pptp_tcp_helper)) {
9333 +               printk(KERN_ERR "Unable to register NAT application helper "
9334 +                               "for pptp\n");
9335 +               return -EIO;
9336 +       }
9337 +
9338 +       printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
9339 +       return 0;
9340 +}
9341 +
9342 +static void __exit fini(void)
9343 +{
9344 +       DEBUGP("cleanup_module\n" );
9345 +       ip_nat_helper_unregister(&pptp_tcp_helper);
9346 +       printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
9347 +}
9348 +
9349 +module_init(init);
9350 +module_exit(fini);
9351 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_proto_gre.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_proto_gre.c
9352 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_proto_gre.c        1970-01-01 01:00:00.000000000 +0100
9353 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_proto_gre.c    2003-11-17 09:09:34.000000000 +0100
9354 @@ -0,0 +1,225 @@
9355 +/*
9356 + * ip_nat_proto_gre.c - Version 1.2
9357 + *
9358 + * NAT protocol helper module for GRE.
9359 + *
9360 + * GRE is a generic encapsulation protocol, which is generally not very
9361 + * suited for NAT, as it has no protocol-specific part as port numbers.
9362 + *
9363 + * It has an optional key field, which may help us distinguishing two 
9364 + * connections between the same two hosts.
9365 + *
9366 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
9367 + *
9368 + * PPTP is built on top of a modified version of GRE, and has a mandatory
9369 + * field called "CallID", which serves us for the same purpose as the key
9370 + * field in plain GRE.
9371 + *
9372 + * Documentation about PPTP can be found in RFC 2637
9373 + *
9374 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
9375 + *
9376 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
9377 + *
9378 + */
9379 +
9380 +#include <linux/config.h>
9381 +#include <linux/module.h>
9382 +#include <linux/ip.h>
9383 +#include <linux/netfilter_ipv4/ip_nat.h>
9384 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9385 +#include <linux/netfilter_ipv4/ip_nat_protocol.h>
9386 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
9387 +
9388 +MODULE_LICENSE("GPL");
9389 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
9390 +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
9391 +
9392 +#if 0
9393 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
9394 +                                      ": " format, ## args)
9395 +#else
9396 +#define DEBUGP(x, args...)
9397 +#endif
9398 +
9399 +/* is key in given range between min and max */
9400 +static int
9401 +gre_in_range(const struct ip_conntrack_tuple *tuple,
9402 +            enum ip_nat_manip_type maniptype,
9403 +            const union ip_conntrack_manip_proto *min,
9404 +            const union ip_conntrack_manip_proto *max)
9405 +{
9406 +       u_int32_t key;
9407 +
9408 +       if (maniptype == IP_NAT_MANIP_SRC)
9409 +               key = tuple->src.u.gre.key;
9410 +       else
9411 +               key = tuple->dst.u.gre.key;
9412 +
9413 +       return ntohl(key) >= ntohl(min->gre.key)
9414 +               && ntohl(key) <= ntohl(max->gre.key);
9415 +}
9416 +
9417 +/* generate unique tuple ... */
9418 +static int 
9419 +gre_unique_tuple(struct ip_conntrack_tuple *tuple,
9420 +                const struct ip_nat_range *range,
9421 +                enum ip_nat_manip_type maniptype,
9422 +                const struct ip_conntrack *conntrack)
9423 +{
9424 +       u_int32_t min, i, range_size;
9425 +       u_int32_t key = 0, *keyptr;
9426 +
9427 +       if (maniptype == IP_NAT_MANIP_SRC)
9428 +               keyptr = &tuple->src.u.gre.key;
9429 +       else
9430 +               keyptr = &tuple->dst.u.gre.key;
9431 +
9432 +       if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
9433 +
9434 +               switch (tuple->dst.u.gre.version) {
9435 +               case 0:
9436 +                       DEBUGP("NATing GRE version 0 (ct=%p)\n",
9437 +                               conntrack);
9438 +                       min = 1;
9439 +                       range_size = 0xffffffff;
9440 +                       break;
9441 +               case GRE_VERSION_PPTP:
9442 +                       DEBUGP("%p: NATing GRE PPTP\n", 
9443 +                               conntrack);
9444 +                       min = 1;
9445 +                       range_size = 0xffff;
9446 +                       break;
9447 +               default:
9448 +                       printk(KERN_WARNING "nat_gre: unknown GRE version\n");
9449 +                       return 0;
9450 +                       break;
9451 +               }
9452 +
9453 +       } else {
9454 +               min = ntohl(range->min.gre.key);
9455 +               range_size = ntohl(range->max.gre.key) - min + 1;
9456 +       }
9457 +
9458 +       DEBUGP("min = %u, range_size = %u\n", min, range_size); 
9459 +
9460 +       for (i = 0; i < range_size; i++, key++) {
9461 +               *keyptr = htonl(min + key % range_size);
9462 +               if (!ip_nat_used_tuple(tuple, conntrack))
9463 +                       return 1;
9464 +       }
9465 +
9466 +       DEBUGP("%p: no NAT mapping\n", conntrack);
9467 +
9468 +       return 0;
9469 +}
9470 +
9471 +/* manipulate a GRE packet according to maniptype */
9472 +static void 
9473 +gre_manip_pkt(struct iphdr *iph, size_t len, 
9474 +             const struct ip_conntrack_manip *manip,
9475 +             enum ip_nat_manip_type maniptype)
9476 +{
9477 +       struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
9478 +       struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;
9479 +
9480 +       /* we only have destination manip of a packet, since 'source key' 
9481 +        * is not present in the packet itself */
9482 +       if (maniptype == IP_NAT_MANIP_DST) {
9483 +               /* key manipulation is always dest */
9484 +               switch (greh->version) {
9485 +               case 0:
9486 +                       if (!greh->key) {
9487 +                               DEBUGP("can't nat GRE w/o key\n");
9488 +                               break;
9489 +                       }
9490 +                       if (greh->csum) {
9491 +                               /* FIXME: Never tested this code... */
9492 +                               *(gre_csum(greh)) = 
9493 +                                       ip_nat_cheat_check(~*(gre_key(greh)),
9494 +                                                       manip->u.gre.key,
9495 +                                                       *(gre_csum(greh)));
9496 +                       }
9497 +                       *(gre_key(greh)) = manip->u.gre.key;
9498 +                       break;
9499 +               case GRE_VERSION_PPTP:
9500 +                       DEBUGP("call_id -> 0x%04x\n", 
9501 +                               ntohl(manip->u.gre.key));
9502 +                       pgreh->call_id = htons(ntohl(manip->u.gre.key));
9503 +                       break;
9504 +               default:
9505 +                       DEBUGP("can't nat unknown GRE version\n");
9506 +                       break;
9507 +               }
9508 +       }
9509 +}
9510 +
9511 +/* print out a nat tuple */
9512 +static unsigned int 
9513 +gre_print(char *buffer, 
9514 +         const struct ip_conntrack_tuple *match,
9515 +         const struct ip_conntrack_tuple *mask)
9516 +{
9517 +       unsigned int len = 0;
9518 +
9519 +       if (mask->dst.u.gre.version)
9520 +               len += sprintf(buffer + len, "version=%d ",
9521 +                               ntohs(match->dst.u.gre.version));
9522 +
9523 +       if (mask->dst.u.gre.protocol)
9524 +               len += sprintf(buffer + len, "protocol=0x%x ",
9525 +                               ntohs(match->dst.u.gre.protocol));
9526 +
9527 +       if (mask->src.u.gre.key)
9528 +               len += sprintf(buffer + len, "srckey=0x%x ", 
9529 +                               ntohl(match->src.u.gre.key));
9530 +
9531 +       if (mask->dst.u.gre.key)
9532 +               len += sprintf(buffer + len, "dstkey=0x%x ",
9533 +                               ntohl(match->src.u.gre.key));
9534 +
9535 +       return len;
9536 +}
9537 +
9538 +/* print a range of keys */
9539 +static unsigned int 
9540 +gre_print_range(char *buffer, const struct ip_nat_range *range)
9541 +{
9542 +       if (range->min.gre.key != 0 
9543 +           || range->max.gre.key != 0xFFFF) {
9544 +               if (range->min.gre.key == range->max.gre.key)
9545 +                       return sprintf(buffer, "key 0x%x ",
9546 +                                       ntohl(range->min.gre.key));
9547 +               else
9548 +                       return sprintf(buffer, "keys 0x%u-0x%u ",
9549 +                                       ntohl(range->min.gre.key),
9550 +                                       ntohl(range->max.gre.key));
9551 +       } else
9552 +               return 0;
9553 +}
9554 +
9555 +/* nat helper struct */
9556 +static struct ip_nat_protocol gre = 
9557 +       { { NULL, NULL }, "GRE", IPPROTO_GRE,
9558 +         gre_manip_pkt,
9559 +         gre_in_range,
9560 +         gre_unique_tuple,
9561 +         gre_print,
9562 +         gre_print_range 
9563 +       };
9564 +                                 
9565 +static int __init init(void)
9566 +{
9567 +        if (ip_nat_protocol_register(&gre))
9568 +                return -EIO;
9569 +
9570 +        return 0;
9571 +}
9572 +
9573 +static void __exit fini(void)
9574 +{
9575 +        ip_nat_protocol_unregister(&gre);
9576 +}
9577 +
9578 +module_init(init);
9579 +module_exit(fini);
9580 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_quake3.c
9581 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_quake3.c   1970-01-01 01:00:00.000000000 +0100
9582 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_quake3.c       2003-12-10 23:14:06.244005464 +0100
9583 @@ -0,0 +1,249 @@
9584 +/* Quake3 extension for UDP NAT alteration.
9585 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
9586 + * based on ip_nat_ftp.c and ip_nat_tftp.c
9587 + *
9588 + * ip_nat_quake3.c v0.0.3 2002-08-31
9589 + *
9590 + *      This program is free software; you can redistribute it and/or
9591 + *      modify it under the terms of the GNU General Public License
9592 + *      as published by the Free Software Foundation; either version
9593 + *      2 of the License, or (at your option) any later version.
9594 + *
9595 + *      Module load syntax:
9596 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
9597 + *
9598 + *      please give the ports of all Quake3 master servers You wish to
9599 + *      connect to. If you don't specify ports, the default will be UDP
9600 + *      port 27950.
9601 + *
9602 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
9603 + *
9604 + *      Notes: 
9605 + *      - If you're one of those people who would try anything to lower
9606 + *        latency while playing Quake (and who isn't :-) ), you may want to
9607 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
9608 + *        outgoing UDP traffic.
9609 + *        This will make ip_conntrack_quake3 add the necessary expectations,
9610 + *        but there will be no overhead for client->server UDP streams. If
9611 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
9612 + *        hook for every packet in the client->server UDP stream.
9613 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
9614 + *        The IP addresses in the master connection payload (=IP addresses
9615 + *        of Quake servers) have no relation with the master server so
9616 + *        DNAT'ing the master connection to a server should not change the
9617 + *        expected connections.
9618 + *      - Not tested due to lack of equipment:
9619 + *        - multiple Quake3 clients behind one MASQUERADE gateway
9620 + *        - what if Quake3 client is running on router too
9621 + */
9622 +
9623 +#include <linux/module.h>
9624 +#include <linux/netfilter_ipv4.h>
9625 +#include <linux/ip.h>
9626 +#include <linux/udp.h>
9627 +
9628 +#include <linux/netfilter.h>
9629 +#include <linux/netfilter_ipv4/ip_tables.h>
9630 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9631 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
9632 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9633 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9634 +
9635 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
9636 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
9637 +MODULE_LICENSE("GPL");
9638 +
9639 +#define MAX_PORTS 8
9640 +
9641 +static int ports[MAX_PORTS];
9642 +static int ports_c = 0;
9643 +#ifdef MODULE_PARM
9644 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
9645 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
9646 +#endif
9647 +
9648 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
9649 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
9650 +#if 0 
9651 +#define DEBUGP printk
9652 +#else
9653 +#define DEBUGP(format, args...)
9654 +#endif
9655 +
9656 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
9657 +
9658 +static unsigned int 
9659 +quake3_nat_help(struct ip_conntrack *ct,
9660 +                struct ip_conntrack_expect *exp,
9661 +                struct ip_nat_info *info,
9662 +                enum ip_conntrack_info ctinfo,
9663 +                unsigned int hooknum,
9664 +                struct sk_buff **pskb)
9665 +{
9666 +       struct iphdr *iph = (*pskb)->nh.iph;
9667 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
9668 +       struct ip_conntrack_tuple repl;
9669 +       int dir = CTINFO2DIR(ctinfo);
9670 +       int i;
9671 +       
9672 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
9673 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9674 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9675 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9676 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
9677 +             );
9678 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9679 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
9680 +       
9681 +       /* Only mangle things once: original direction in POST_ROUTING
9682 +          and reply direction on PRE_ROUTING. */
9683 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
9684 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
9685 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
9686 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9687 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9688 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9689 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
9690 +               return NF_ACCEPT;
9691 +       }
9692 +
9693 +       if (!exp) {
9694 +               DEBUGP("no conntrack expectation to modify\n");
9695 +               return NF_ACCEPT;
9696 +       }
9697 +
9698 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
9699 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
9700 +                   i+6 < ntohs(udph->len);
9701 +                   i+=7) {
9702 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
9703 +                              i, ntohs(udph->len),
9704 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
9705 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
9706 +                       
9707 +                       memset(&repl, 0, sizeof(repl));
9708 +
9709 +                       repl.dst.protonum = IPPROTO_UDP;
9710 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
9711 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
9712 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
9713 +                       
9714 +                       ip_conntrack_change_expect(exp, &repl);
9715 +               }
9716 +       }
9717 +       return NF_ACCEPT;
9718 +}
9719 +
9720 +static unsigned int 
9721 +quake3_nat_expected(struct sk_buff **pskb,
9722 +                    unsigned int hooknum,
9723 +                    struct ip_conntrack *ct, 
9724 +                    struct ip_nat_info *info) 
9725 +{
9726 +       const struct ip_conntrack *master = ct->master->expectant;
9727 +       struct ip_nat_multi_range mr;
9728 +       u_int32_t newsrcip, newdstip, newip;
9729 +#if 0 
9730 +       const struct ip_conntrack_tuple *repl =
9731 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
9732 +       struct iphdr *iph = (*pskb)->nh.iph;
9733 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
9734 +#endif
9735 +
9736 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
9737 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9738 +
9739 +       IP_NF_ASSERT(info);
9740 +       IP_NF_ASSERT(master);
9741 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
9742 +       
9743 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
9744 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9745 +       
9746 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
9747 +               newip = newsrcip;
9748 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9749 +                      "newsrc: %u.%u.%u.%u\n",
9750 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9751 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9752 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9753 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9754 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9755 +                      NIPQUAD(newip));
9756 +               
9757 +       } else {
9758 +               newip = newdstip;
9759 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9760 +                      "newdst: %u.%u.%u.%u\n",
9761 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9762 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9763 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9764 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9765 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9766 +                      NIPQUAD(newip));
9767 +       }
9768 +       
9769 +       mr.rangesize = 1;
9770 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
9771 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
9772 +
9773 +       return ip_nat_setup_info(ct,&mr,hooknum);
9774 +}
9775 +
9776 +static struct ip_nat_helper quake3[MAX_PORTS];
9777 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
9778 +
9779 +static void fini(void)
9780 +{
9781 +       int i;
9782 +       
9783 +       for (i = 0 ; i < ports_c; i++) {
9784 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
9785 +                      ip_nat_helper_unregister(&quake3[i]);
9786 +       }
9787 +}
9788 +
9789 +static int __init init(void)
9790 +       {
9791 +               int i, ret = 0;
9792 +               char *tmpname;
9793 +
9794 +               if (!ports[0])
9795 +                       ports[0] = QUAKE3_MASTER_PORT;
9796 +               
9797 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
9798 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
9799 +
9800 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
9801 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
9802 +                       quake3[i].mask.dst.protonum = 0xFFFF;
9803 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
9804 +                       quake3[i].help = quake3_nat_help;
9805 +                       quake3[i].flags = 0;
9806 +                       quake3[i].me = THIS_MODULE;
9807 +                       quake3[i].expect = quake3_nat_expected;
9808 +                       
9809 +                       tmpname = &quake3_names[i][0];
9810 +                       if (ports[i] == QUAKE3_MASTER_PORT)
9811 +                               sprintf(tmpname, "quake3");
9812 +                       else
9813 +                               sprintf(tmpname, "quake3-%d", i);
9814 +                       quake3[i].name = tmpname;
9815 +                       
9816 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
9817 +                              ports[i], quake3[i].name);
9818 +                       ret = ip_nat_helper_register(&quake3[i]);
9819 +                       
9820 +                       if (ret) {
9821 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
9822 +                                      ports[i]);
9823 +                               fini();
9824 +                               return ret;
9825 +                       }
9826 +                       ports_c++;
9827 +               }
9828 +               return ret;
9829 +       }
9830 +       
9831 +module_init(init);
9832 +module_exit(fini);
9833 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rtsp.c
9834 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rtsp.c     1970-01-01 01:00:00.000000000 +0100
9835 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rtsp.c 2003-12-10 23:14:12.892994664 +0100
9836 @@ -0,0 +1,625 @@
9837 +/*
9838 + * RTSP extension for TCP NAT alteration
9839 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
9840 + * based on ip_nat_irc.c
9841 + *
9842 + *      This program is free software; you can redistribute it and/or
9843 + *      modify it under the terms of the GNU General Public License
9844 + *      as published by the Free Software Foundation; either version
9845 + *      2 of the License, or (at your option) any later version.
9846 + *
9847 + * Module load syntax:
9848 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
9849 + *                           stunaddr=<address>
9850 + *                           destaction=[auto|strip|none]
9851 + *
9852 + * If no ports are specified, the default will be port 554 only.
9853 + *
9854 + * stunaddr specifies the address used to detect that a client is using STUN.
9855 + * If this address is seen in the destination parameter, it is assumed that
9856 + * the client has already punched a UDP hole in the firewall, so we don't
9857 + * mangle the client_port.  If none is specified, it is autodetected.  It
9858 + * only needs to be set if you have multiple levels of NAT.  It should be
9859 + * set to the external address that the STUN clients detect.  Note that in
9860 + * this case, it will not be possible for clients to use UDP with servers
9861 + * between the NATs.
9862 + *
9863 + * If no destaction is specified, auto is used.
9864 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
9865 + *   destaction=strip: always strip destination parameter (not recommended).
9866 + *   destaction=none:  do not touch destination parameter (not recommended).
9867 + */
9868 +
9869 +#include <linux/module.h>
9870 +#include <linux/netfilter_ipv4.h>
9871 +#include <linux/ip.h>
9872 +#include <linux/tcp.h>
9873 +#include <linux/kernel.h>
9874 +#include <net/tcp.h>
9875 +#include <linux/netfilter_ipv4/ip_nat.h>
9876 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9877 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9878 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
9879 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9880 +
9881 +#include <linux/inet.h>
9882 +#include <linux/ctype.h>
9883 +#define NF_NEED_STRNCASECMP
9884 +#define NF_NEED_STRTOU16
9885 +#include <linux/netfilter_helpers.h>
9886 +#define NF_NEED_MIME_NEXTLINE
9887 +#include <linux/netfilter_mime.h>
9888 +
9889 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
9890 +#ifdef IP_NF_RTSP_DEBUG
9891 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args);
9892 +#else
9893 +#define DEBUGP(args...)
9894 +#endif
9895 +
9896 +#define MAX_PORTS       8
9897 +#define DSTACT_AUTO     0
9898 +#define DSTACT_STRIP    1
9899 +#define DSTACT_NONE     2
9900 +
9901 +static int      ports[MAX_PORTS];
9902 +static char*    stunaddr = NULL;
9903 +static char*    destaction = NULL;
9904 +
9905 +static int       num_ports = 0;
9906 +static u_int32_t extip = 0;
9907 +static int       dstact = 0;
9908 +
9909 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
9910 +MODULE_DESCRIPTION("RTSP network address translation module");
9911 +MODULE_LICENSE("GPL");
9912 +#ifdef MODULE_PARM
9913 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9914 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
9915 +MODULE_PARM(stunaddr, "s");
9916 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
9917 +MODULE_PARM(destaction, "s");
9918 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
9919 +#endif
9920 +
9921 +/* protects rtsp part of conntracks */
9922 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
9923 +
9924 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
9925 +
9926 +/*** helper functions ***/
9927 +
9928 +static void
9929 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
9930 +{
9931 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
9932 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
9933 +
9934 +    *pptcpdata = (char*)tcph + tcph->doff*4;
9935 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
9936 +}
9937 +
9938 +/*** nat functions ***/
9939 +
9940 +/*
9941 + * Mangle the "Transport:" header:
9942 + *   - Replace all occurences of "client_port=<spec>"
9943 + *   - Handle destination parameter
9944 + *
9945 + * In:
9946 + *   ct, ctinfo = conntrack context
9947 + *   pskb       = packet
9948 + *   tranoff    = Transport header offset from TCP data
9949 + *   tranlen    = Transport header length (incl. CRLF)
9950 + *   rport_lo   = replacement low  port (host endian)
9951 + *   rport_hi   = replacement high port (host endian)
9952 + *
9953 + * Returns packet size difference.
9954 + *
9955 + * Assumes that a complete transport header is present, ending with CR or LF
9956 + */
9957 +static int
9958 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
9959 +                 struct ip_conntrack_expect* exp,
9960 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
9961 +{
9962 +    char*       ptcp;
9963 +    uint        tcplen;
9964 +    char*       ptran;
9965 +    char        rbuf1[16];      /* Replacement buffer (one port) */
9966 +    uint        rbuf1len;       /* Replacement len (one port) */
9967 +    char        rbufa[16];      /* Replacement buffer (all ports) */
9968 +    uint        rbufalen;       /* Replacement len (all ports) */
9969 +    u_int32_t   newip;
9970 +    u_int16_t   loport, hiport;
9971 +    uint        off = 0;
9972 +    uint        diff;           /* Number of bytes we removed */
9973 +
9974 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
9975 +    struct ip_conntrack_tuple t;
9976 +
9977 +    char    szextaddr[15+1];
9978 +    uint    extaddrlen;
9979 +    int     is_stun;
9980 +
9981 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
9982 +    ptran = ptcp+tranoff;
9983 +
9984 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
9985 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
9986 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
9987 +    {
9988 +        INFOP("sanity check failed\n");
9989 +        return 0;
9990 +    }
9991 +    off += 10;
9992 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
9993 +
9994 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9995 +    t = exp->tuple;
9996 +    t.dst.ip = newip;
9997 +
9998 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
9999 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
10000 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
10001 +
10002 +    rbuf1len = rbufalen = 0;
10003 +    switch (prtspexp->pbtype)
10004 +    {
10005 +    case pb_single:
10006 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10007 +        {
10008 +            t.dst.u.udp.port = htons(loport);
10009 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10010 +            {
10011 +                DEBUGP("using port %hu\n", loport);
10012 +                break;
10013 +            }
10014 +        }
10015 +        if (loport != 0)
10016 +        {
10017 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
10018 +            rbufalen = sprintf(rbufa, "%hu", loport);
10019 +        }
10020 +        break;
10021 +    case pb_range:
10022 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
10023 +        {
10024 +            t.dst.u.udp.port = htons(loport);
10025 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10026 +            {
10027 +                hiport = loport + ~exp->mask.dst.u.udp.port;
10028 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
10029 +                break;
10030 +            }
10031 +        }
10032 +        if (loport != 0)
10033 +        {
10034 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
10035 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
10036 +        }
10037 +        break;
10038 +    case pb_discon:
10039 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10040 +        {
10041 +            t.dst.u.udp.port = htons(loport);
10042 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10043 +            {
10044 +                DEBUGP("using port %hu (1 of 2)\n", loport);
10045 +                break;
10046 +            }
10047 +        }
10048 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
10049 +        {
10050 +            t.dst.u.udp.port = htons(hiport);
10051 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10052 +            {
10053 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
10054 +                break;
10055 +            }
10056 +        }
10057 +        if (loport != 0 && hiport != 0)
10058 +        {
10059 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
10060 +            if (hiport == loport+1)
10061 +            {
10062 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
10063 +            }
10064 +            else
10065 +            {
10066 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
10067 +            }
10068 +        }
10069 +        break;
10070 +    default:
10071 +        /* oops */
10072 +    }
10073 +
10074 +    if (rbuf1len == 0)
10075 +    {
10076 +        return 0;   /* cannot get replacement port(s) */
10077 +    }
10078 +
10079 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
10080 +    while (off < tranlen)
10081 +    {
10082 +        uint        saveoff;
10083 +        const char* pparamend;
10084 +        uint        nextparamoff;
10085 +
10086 +        pparamend = memchr(ptran+off, ',', tranlen-off);
10087 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
10088 +        nextparamoff = pparamend-ptcp;
10089 +
10090 +        /*
10091 +         * We pass over each param twice.  On the first pass, we look for a
10092 +         * destination= field.  It is handled by the security policy.  If it
10093 +         * is present, allowed, and equal to our external address, we assume
10094 +         * that STUN is being used and we leave the client_port= field alone.
10095 +         */
10096 +        is_stun = 0;
10097 +        saveoff = off;
10098 +        while (off < nextparamoff)
10099 +        {
10100 +            const char* pfieldend;
10101 +            uint        nextfieldoff;
10102 +
10103 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10104 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10105 +
10106 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
10107 +            {
10108 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
10109 +                {
10110 +                    is_stun = 1;
10111 +                }
10112 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
10113 +                {
10114 +                    diff = nextfieldoff-off;
10115 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10116 +                                                         off, diff, NULL, 0))
10117 +                    {
10118 +                        /* mangle failed, all we can do is bail */
10119 +                        return 0;
10120 +                    }
10121 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10122 +                    ptran = ptcp+tranoff;
10123 +                    tranlen -= diff;
10124 +                    nextparamoff -= diff;
10125 +                    nextfieldoff -= diff;
10126 +                }
10127 +            }
10128 +
10129 +            off = nextfieldoff;
10130 +        }
10131 +        if (is_stun)
10132 +        {
10133 +            continue;
10134 +        }
10135 +        off = saveoff;
10136 +        while (off < nextparamoff)
10137 +        {
10138 +            const char* pfieldend;
10139 +            uint        nextfieldoff;
10140 +
10141 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10142 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10143 +
10144 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
10145 +            {
10146 +                u_int16_t   port;
10147 +                uint        numlen;
10148 +                uint        origoff;
10149 +                uint        origlen;
10150 +                char*       rbuf    = rbuf1;
10151 +                uint        rbuflen = rbuf1len;
10152 +
10153 +                off += 12;
10154 +                origoff = (ptran-ptcp)+off;
10155 +                origlen = 0;
10156 +                numlen = nf_strtou16(ptran+off, &port);
10157 +                off += numlen;
10158 +                origlen += numlen;
10159 +                if (port != prtspexp->loport)
10160 +                {
10161 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
10162 +                }
10163 +                else
10164 +                {
10165 +                    if (ptran[off] == '-' || ptran[off] == '/')
10166 +                    {
10167 +                        off++;
10168 +                        origlen++;
10169 +                        numlen = nf_strtou16(ptran+off, &port);
10170 +                        off += numlen;
10171 +                        origlen += numlen;
10172 +                        rbuf = rbufa;
10173 +                        rbuflen = rbufalen;
10174 +                    }
10175 +
10176 +                    /*
10177 +                     * note we cannot just memcpy() if the sizes are the same.
10178 +                     * the mangle function does skb resizing, checks for a
10179 +                     * cloned skb, and updates the checksums.
10180 +                     *
10181 +                     * parameter 4 below is offset from start of tcp data.
10182 +                     */
10183 +                    diff = origlen-rbuflen;
10184 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10185 +                                              origoff, origlen, rbuf, rbuflen))
10186 +                    {
10187 +                        /* mangle failed, all we can do is bail */
10188 +                        return 0;
10189 +                    }
10190 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10191 +                    ptran = ptcp+tranoff;
10192 +                    tranlen -= diff;
10193 +                    nextparamoff -= diff;
10194 +                    nextfieldoff -= diff;
10195 +                }
10196 +            }
10197 +
10198 +            off = nextfieldoff;
10199 +        }
10200 +
10201 +        off = nextparamoff;
10202 +    }
10203 +
10204 +    return 1;
10205 +}
10206 +
10207 +static unsigned int
10208 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
10209 +{
10210 +    struct ip_nat_multi_range mr;
10211 +    u_int32_t newdstip, newsrcip, newip;
10212 +
10213 +    struct ip_conntrack *master = master_ct(ct);
10214 +
10215 +    IP_NF_ASSERT(info);
10216 +    IP_NF_ASSERT(master);
10217 +
10218 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
10219 +
10220 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10221 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10222 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
10223 +
10224 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
10225 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
10226 +
10227 +    mr.rangesize = 1;
10228 +    /* We don't want to manip the per-protocol, just the IPs. */
10229 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10230 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
10231 +
10232 +    return ip_nat_setup_info(ct, &mr, hooknum);
10233 +}
10234 +
10235 +static uint
10236 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10237 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10238 +{
10239 +    char*   ptcp;
10240 +    uint    tcplen;
10241 +    uint    hdrsoff;
10242 +    uint    hdrslen;
10243 +    uint    lineoff;
10244 +    uint    linelen;
10245 +    uint    off;
10246 +
10247 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
10248 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
10249 +
10250 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
10251 +
10252 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10253 +
10254 +    hdrsoff = exp->seq - ntohl(tcph->seq);
10255 +    hdrslen = prtspexp->len;
10256 +    off = hdrsoff;
10257 +
10258 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
10259 +    {
10260 +        if (linelen == 0)
10261 +        {
10262 +            break;
10263 +        }
10264 +        if (off > hdrsoff+hdrslen)
10265 +        {
10266 +            INFOP("!! overrun !!");
10267 +            break;
10268 +        }
10269 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10270 +
10271 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
10272 +        {
10273 +            uint oldtcplen = tcplen;
10274 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
10275 +            {
10276 +                break;
10277 +            }
10278 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10279 +            hdrslen -= (oldtcplen-tcplen);
10280 +            off -= (oldtcplen-tcplen);
10281 +            lineoff -= (oldtcplen-tcplen);
10282 +            linelen -= (oldtcplen-tcplen);
10283 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10284 +        }
10285 +    }
10286 +
10287 +    return NF_ACCEPT;
10288 +}
10289 +
10290 +static uint
10291 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10292 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10293 +{
10294 +    /* XXX: unmangle */
10295 +    return NF_ACCEPT;
10296 +}
10297 +
10298 +static uint
10299 +help(struct ip_conntrack* ct,
10300 +     struct ip_conntrack_expect* exp,
10301 +     struct ip_nat_info* info,
10302 +     enum ip_conntrack_info ctinfo,
10303 +     unsigned int hooknum,
10304 +     struct sk_buff** pskb)
10305 +{
10306 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
10307 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
10308 +    uint datalen;
10309 +    int dir;
10310 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
10311 +    int rc = NF_ACCEPT;
10312 +
10313 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
10314 +    {
10315 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
10316 +        return NF_ACCEPT;
10317 +    }
10318 +
10319 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
10320 +
10321 +    /*
10322 +     * Only mangle things once: original direction in POST_ROUTING
10323 +     * and reply direction on PRE_ROUTING.
10324 +     */
10325 +    dir = CTINFO2DIR(ctinfo);
10326 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10327 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
10328 +    {
10329 +        DEBUGP("Not touching dir %s at hook %s\n",
10330 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10331 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10332 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10333 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10334 +        return NF_ACCEPT;
10335 +    }
10336 +    DEBUGP("got beyond not touching\n");
10337 +
10338 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
10339 +
10340 +    LOCK_BH(&ip_rtsp_lock);
10341 +    /* Ensure the packet contains all of the marked data */
10342 +    if (!between(exp->seq + ct_rtsp_info->len,
10343 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
10344 +    {
10345 +        /* Partial retransmission?  Probably a hacker. */
10346 +        if (net_ratelimit())
10347 +        {
10348 +            INFOP("partial packet %u/%u in %u/%u\n",
10349 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
10350 +        }
10351 +        UNLOCK_BH(&ip_rtsp_lock);
10352 +        return NF_DROP;
10353 +    }
10354 +
10355 +    switch (dir)
10356 +    {
10357 +    case IP_CT_DIR_ORIGINAL:
10358 +        rc = help_out(ct, ctinfo, exp, pskb);
10359 +        break;
10360 +    case IP_CT_DIR_REPLY:
10361 +        rc = help_in(ct, ctinfo, exp, pskb);
10362 +        break;
10363 +    default:
10364 +        /* oops */
10365 +    }
10366 +    UNLOCK_BH(&ip_rtsp_lock);
10367 +
10368 +    return rc;
10369 +}
10370 +
10371 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
10372 +static char rtsp_names[MAX_PORTS][10];
10373 +
10374 +/* This function is intentionally _NOT_ defined as  __exit */
10375 +static void
10376 +fini(void)
10377 +{
10378 +    int i;
10379 +
10380 +    for (i = 0; i < num_ports; i++)
10381 +    {
10382 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
10383 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
10384 +    }
10385 +}
10386 +
10387 +static int __init
10388 +init(void)
10389 +{
10390 +    int ret = 0;
10391 +    int i;
10392 +    struct ip_nat_helper* hlpr;
10393 +    char* tmpname;
10394 +
10395 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
10396 +
10397 +    if (ports[0] == 0)
10398 +    {
10399 +        ports[0] = RTSP_PORT;
10400 +    }
10401 +
10402 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
10403 +    {
10404 +        hlpr = &ip_nat_rtsp_helpers[i];
10405 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
10406 +
10407 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
10408 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
10409 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
10410 +        hlpr->mask.dst.protonum = 0xFFFF;
10411 +        hlpr->help = help;
10412 +        hlpr->flags = 0;
10413 +        hlpr->me = THIS_MODULE;
10414 +        hlpr->expect = expected;
10415 +
10416 +        tmpname = &rtsp_names[i][0];
10417 +        if (ports[i] == RTSP_PORT)
10418 +        {
10419 +                sprintf(tmpname, "rtsp");
10420 +        }
10421 +        else
10422 +        {
10423 +                sprintf(tmpname, "rtsp-%d", i);
10424 +        }
10425 +        hlpr->name = tmpname;
10426 +
10427 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
10428 +        ret = ip_nat_helper_register(hlpr);
10429 +
10430 +        if (ret)
10431 +        {
10432 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
10433 +            fini();
10434 +            return 1;
10435 +        }
10436 +        num_ports++;
10437 +    }
10438 +    if (stunaddr != NULL)
10439 +    {
10440 +        extip = in_aton(stunaddr);
10441 +    }
10442 +    if (destaction != NULL)
10443 +    {
10444 +        if (strcmp(destaction, "auto") == 0)
10445 +        {
10446 +            dstact = DSTACT_AUTO;
10447 +        }
10448 +        if (strcmp(destaction, "strip") == 0)
10449 +        {
10450 +            dstact = DSTACT_STRIP;
10451 +        }
10452 +        if (strcmp(destaction, "none") == 0)
10453 +        {
10454 +            dstact = DSTACT_NONE;
10455 +        }
10456 +    }
10457 +    return ret;
10458 +}
10459 +
10460 +module_init(init);
10461 +module_exit(fini);
10462 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rule.c
10463 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rule.c     2003-11-26 21:43:38.000000000 +0100
10464 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rule.c 2003-12-10 23:13:24.662326840 +0100
10465 @@ -67,7 +67,7 @@
10466                 0,
10467                 sizeof(struct ipt_entry),
10468                 sizeof(struct ipt_standard),
10469 -               0, { 0, 0 }, { } },
10470 +               0, NULL, 0, { 0, 0 }, { } },
10471               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10472                 -NF_ACCEPT - 1 } },
10473             /* POST_ROUTING */
10474 @@ -75,7 +75,7 @@
10475                 0,
10476                 sizeof(struct ipt_entry),
10477                 sizeof(struct ipt_standard),
10478 -               0, { 0, 0 }, { } },
10479 +               0, NULL, 0, { 0, 0 }, { } },
10480               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10481                 -NF_ACCEPT - 1 } },
10482             /* LOCAL_OUT */
10483 @@ -83,7 +83,7 @@
10484                 0,
10485                 sizeof(struct ipt_entry),
10486                 sizeof(struct ipt_standard),
10487 -               0, { 0, 0 }, { } },
10488 +               0, NULL, 0, { 0, 0 }, { } },
10489               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10490                 -NF_ACCEPT - 1 } }
10491      },
10492 @@ -92,7 +92,7 @@
10493         0,
10494         sizeof(struct ipt_entry),
10495         sizeof(struct ipt_error),
10496 -       0, { 0, 0 }, { } },
10497 +       0, NULL, 0, { 0, 0 }, { } },
10498        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
10499           { } },
10500         "ERROR"
10501 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_standalone.c
10502 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_standalone.c       2003-11-26 21:45:10.000000000 +0100
10503 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_standalone.c   2003-12-10 23:14:03.996347160 +0100
10504 @@ -260,7 +260,13 @@
10505  };
10506  #endif
10507  
10508 -/* Protocol registration. */
10509 +/**
10510 + * ip_nat_protocol_register - Register a layer 4 protocol helper
10511 + * @proto: structure describing this helper
10512 + * 
10513 + * This function is called by NAT layer 4 protocol helpers to register
10514 + * themselvers with the NAT core.
10515 + */
10516  int ip_nat_protocol_register(struct ip_nat_protocol *proto)
10517  {
10518         int ret = 0;
10519 @@ -281,9 +287,16 @@
10520         return ret;
10521  }
10522  
10523 -/* Noone stores the protocol anywhere; simply delete it. */
10524 +/**
10525 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
10526 + * @proto: sturcture describing the helper
10527 + *
10528 + * This function is called by NAT layer 4 protocol helpers to
10529 + * unregister themselves from the NAT core.
10530 + */
10531  void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
10532  {
10533 +       /* Noone stores the protocol anywhere; simply delete it. */
10534         WRITE_LOCK(&ip_nat_lock);
10535         LIST_DELETE(&protos, proto);
10536         WRITE_UNLOCK(&ip_nat_lock);
10537 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_talk.c
10538 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_talk.c     1970-01-01 01:00:00.000000000 +0100
10539 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_talk.c 2003-12-10 23:14:15.481601136 +0100
10540 @@ -0,0 +1,473 @@
10541 +/* 
10542 + * talk extension for UDP NAT alteration. 
10543 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10544 + *
10545 + *      This program is free software; you can redistribute it and/or
10546 + *      modify it under the terms of the GNU General Public License
10547 + *      as published by the Free Software Foundation; either version
10548 + *      2 of the License, or (at your option) any later version.
10549 + **
10550 + *     Module load syntax:
10551 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
10552 + *
10553 + *             talk=[0|1]      disable|enable old talk support
10554 + *            ntalk=[0|1]      disable|enable ntalk support
10555 + *           ntalk2=[0|1]      disable|enable ntalk2 support
10556 + *
10557 + *     The default is talk=1 ntalk=1 ntalk2=1
10558 + *
10559 + *  
10560 + */
10561 +#include <linux/module.h>
10562 +#include <linux/netfilter_ipv4.h>
10563 +#include <linux/ip.h>
10564 +#include <linux/udp.h>
10565 +#include <linux/kernel.h>
10566 +#include <net/tcp.h>
10567 +#include <net/udp.h>
10568 +
10569 +#include <linux/netfilter_ipv4/ip_nat.h>
10570 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
10571 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
10572 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
10573 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
10574 +
10575 +/* Default all talk protocols are supported */
10576 +static int talk   = 1;
10577 +static int ntalk  = 1;
10578 +static int ntalk2 = 1;
10579 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
10580 +MODULE_DESCRIPTION("talk network address translation module");
10581 +#ifdef MODULE_PARM
10582 +MODULE_PARM(talk, "i");
10583 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
10584 +MODULE_PARM(ntalk, "i");
10585 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
10586 +MODULE_PARM(ntalk2, "i");
10587 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
10588 +#endif
10589 +
10590 +#if 0
10591 +#define DEBUGP printk
10592 +#define IP_NAT_TALK_DEBUG
10593 +#else
10594 +#define DEBUGP(format, args...)
10595 +#endif
10596 +
10597 +/* FIXME: Time out? --RR */
10598 +
10599 +static int
10600 +mangle_packet(struct sk_buff **pskb,
10601 +             struct ip_conntrack *ct,
10602 +             u_int32_t newip,
10603 +             u_int16_t port,
10604 +             struct talk_addr *addr,
10605 +             struct talk_addr *ctl_addr)
10606 +{
10607 +       struct iphdr *iph = (*pskb)->nh.iph;
10608 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
10609 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
10610 +
10611 +       /* Fortunately talk sends a structure with the address and
10612 +          port in it. The size of the packet won't change. */
10613 +
10614 +       if (ctl_addr == NULL) {
10615 +               /* response */
10616 +               if (addr->ta_addr == INADDR_ANY)
10617 +                       return 1;
10618 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
10619 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10620 +                      NIPQUAD(newip), ntohs(port));
10621 +               addr->ta_addr = newip;
10622 +               addr->ta_port = port;
10623 +       } else {
10624 +               /* message */
10625 +               if (addr->ta_addr != INADDR_ANY) {
10626 +                       /* Change address inside packet to match way we're mapping
10627 +                          this connection. */
10628 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
10629 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10630 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
10631 +                              ntohs(addr->ta_port));
10632 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10633 +               }
10634 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
10635 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10636 +                      NIPQUAD(newip), ntohs(port));
10637 +               ctl_addr->ta_addr = newip;
10638 +               ctl_addr->ta_port = port;
10639 +       }
10640 +
10641 +       /* Fix checksums */
10642 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
10643 +       udph->check = 0;
10644 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
10645 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
10646 +               
10647 +       ip_send_check(iph);
10648 +       return 1;
10649 +}
10650 +
10651 +static int talk_help_msg(struct ip_conntrack *ct,
10652 +                        struct sk_buff **pskb,
10653 +                        u_char type,
10654 +                        struct talk_addr *addr,
10655 +                        struct talk_addr *ctl_addr)
10656 +{
10657 +       u_int32_t newip;
10658 +       u_int16_t port;
10659 +       
10660 +       unsigned int verdict = NF_ACCEPT;
10661 +
10662 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
10663 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10664 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10665 +               type);
10666 +
10667 +       /* Change address inside packet to match way we're mapping
10668 +          this connection. */
10669 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10670 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
10671 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
10672 +               NIPQUAD(newip), ntohs(port));
10673 +
10674 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
10675 +               verdict = NF_DROP;
10676 +
10677 +       return verdict;
10678 +}
10679 +
10680 +static int talk_help_response(struct ip_conntrack *ct,
10681 +                             struct ip_conntrack_expect *exp,
10682 +                             struct sk_buff **pskb,
10683 +                             u_char type,
10684 +                             u_char answer,
10685 +                             struct talk_addr *addr)
10686 +{
10687 +       u_int32_t newip;
10688 +       u_int16_t port;
10689 +       struct ip_conntrack_tuple t;
10690 +       struct ip_ct_talk_expect *ct_talk_info;
10691 +
10692 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
10693 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10694 +               type, answer);
10695 +       
10696 +       LOCK_BH(&ip_talk_lock);
10697 +       ct_talk_info = &exp->help.exp_talk_info;
10698 +
10699 +       if (!(answer == SUCCESS 
10700 +             && (type == LOOK_UP || type == ANNOUNCE)
10701 +             && exp != NULL)) {
10702 +               UNLOCK_BH(&ip_talk_lock);
10703 +               return NF_ACCEPT;
10704 +       }
10705 +               
10706 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
10707 +               ntohs(ct_talk_info->port), 
10708 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
10709 +
10710 +       /* Change address inside packet to match way we're mapping
10711 +          this connection. */
10712 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
10713 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
10714 +       /* We can read expect here without conntrack lock, since it's
10715 +          only set in ip_conntrack_talk , with ip_talk_lock held
10716 +          writable */ 
10717 +       t = exp->tuple;
10718 +       t.dst.ip = newip;
10719 +
10720 +       /* Try to get same port: if not, try to change it. */
10721 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
10722 +               if (type == LOOK_UP)
10723 +                       t.dst.u.tcp.port = htons(port);
10724 +               else
10725 +                       t.dst.u.udp.port = htons(port);
10726 +
10727 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
10728 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
10729 +                       break;
10730 +               }
10731 +       }
10732 +       UNLOCK_BH(&ip_talk_lock);
10733 +
10734 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
10735 +               return NF_DROP;
10736 +       
10737 +       return NF_ACCEPT;
10738 +}
10739 +
10740 +static unsigned int talk_help(struct ip_conntrack *ct,
10741 +                             struct ip_conntrack_expect *exp,
10742 +                             struct ip_nat_info *info,
10743 +                             enum ip_conntrack_info ctinfo,
10744 +                             unsigned int hooknum,
10745 +                             struct sk_buff **pskb,
10746 +                             int talk_port)
10747 +{
10748 +       struct iphdr *iph = (*pskb)->nh.iph;
10749 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
10750 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
10751 +       char *data = (char *)udph + sizeof(struct udphdr);
10752 +       int dir;
10753 +
10754 +       /* Only mangle things once: original direction in POST_ROUTING
10755 +          and reply direction on PRE_ROUTING. */
10756 +       dir = CTINFO2DIR(ctinfo);
10757 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10758 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
10759 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
10760 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10761 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10762 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10763 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10764 +               return NF_ACCEPT;
10765 +       }
10766 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
10767 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10768 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10769 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10770 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10771 +              NIPQUAD(iph->saddr), ntohs(udph->source),
10772 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
10773 +              talk_port);
10774 +
10775 +       /* Because conntrack does not drop packets, checking must be repeated here... */
10776 +       if (talk_port == TALK_PORT) {
10777 +               if (dir == IP_CT_DIR_ORIGINAL
10778 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
10779 +                       return talk_help_msg(ct, pskb,
10780 +                                            ((struct talk_msg *)data)->type, 
10781 +                                            &(((struct talk_msg *)data)->addr),
10782 +                                            &(((struct talk_msg *)data)->ctl_addr));
10783 +               else if (dir == IP_CT_DIR_REPLY
10784 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
10785 +                       return talk_help_response(ct, exp, pskb,
10786 +                                                 ((struct talk_response *)data)->type, 
10787 +                                                 ((struct talk_response *)data)->answer,
10788 +                                                 &(((struct talk_response *)data)->addr));
10789 +               else {  
10790 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
10791 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
10792 +                              (unsigned)udplen - sizeof(struct udphdr), 
10793 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
10794 +                       return NF_DROP;
10795 +               }
10796 +       } else {
10797 +               if (dir == IP_CT_DIR_ORIGINAL) {
10798 +                       if (ntalk
10799 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
10800 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
10801 +                               return talk_help_msg(ct, pskb,
10802 +                                                    ((struct ntalk_msg *)data)->type, 
10803 +                                                    &(((struct ntalk_msg *)data)->addr),
10804 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
10805 +                       else if (ntalk2
10806 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
10807 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
10808 +                                && udplen == sizeof(struct udphdr) 
10809 +                                             + sizeof(struct ntalk2_msg) 
10810 +                                             + ((struct ntalk2_msg *)data)->extended)
10811 +                               return talk_help_msg(ct, pskb,
10812 +                                                    ((struct ntalk2_msg *)data)->type, 
10813 +                                                    &(((struct ntalk2_msg *)data)->addr),
10814 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
10815 +                       else {
10816 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
10817 +                                      (unsigned)udplen - sizeof(struct udphdr), 
10818 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
10819 +                               return NF_DROP;
10820 +                       }
10821 +               } else {
10822 +                       if (ntalk
10823 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
10824 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
10825 +                               return talk_help_response(ct, exp, pskb,
10826 +                                                         ((struct ntalk_response *)data)->type, 
10827 +                                                         ((struct ntalk_response *)data)->answer,
10828 +                                                         &(((struct ntalk_response *)data)->addr));
10829 +                       else if (ntalk2
10830 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
10831 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
10832 +                               return talk_help_response(ct, exp, pskb,
10833 +                                                         ((struct ntalk2_response *)data)->type, 
10834 +                                                         ((struct ntalk2_response *)data)->answer,
10835 +                                                         &(((struct ntalk2_response *)data)->addr));
10836 +                       else {
10837 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
10838 +                                      (unsigned)udplen - sizeof(struct udphdr), 
10839 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
10840 +                               return NF_DROP;
10841 +                       }
10842 +               }
10843 +       }
10844 +}
10845 +
10846 +static unsigned int help(struct ip_conntrack *ct,
10847 +                        struct ip_conntrack_expect *exp,
10848 +                        struct ip_nat_info *info,
10849 +                        enum ip_conntrack_info ctinfo,
10850 +                        unsigned int hooknum,
10851 +                        struct sk_buff **pskb)
10852 +{
10853 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
10854 +}
10855 +
10856 +static unsigned int nhelp(struct ip_conntrack *ct,
10857 +                         struct ip_conntrack_expect *exp,
10858 +                         struct ip_nat_info *info,
10859 +                         enum ip_conntrack_info ctinfo,
10860 +                         unsigned int hooknum,
10861 +                         struct sk_buff **pskb)
10862 +{
10863 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
10864 +}
10865 +
10866 +static unsigned int
10867 +talk_nat_expected(struct sk_buff **pskb,
10868 +                 unsigned int hooknum,
10869 +                 struct ip_conntrack *ct,
10870 +                 struct ip_nat_info *info);
10871 +
10872 +static struct ip_nat_helper talk_helpers[2] = 
10873 +       { { { NULL, NULL },
10874 +            "talk",                                    /* name */
10875 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
10876 +            THIS_MODULE,                               /* module */
10877 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
10878 +              { 0, { 0 }, IPPROTO_UDP } },
10879 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
10880 +              { 0, { 0 }, 0xFFFF } },
10881 +            help,                                      /* helper */
10882 +            talk_nat_expected },                       /* expectfn */
10883 +         { { NULL, NULL },
10884 +            "ntalk",                                   /* name */
10885 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
10886 +            THIS_MODULE,                                       /* module */
10887 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
10888 +              { 0, { 0 }, IPPROTO_UDP } },
10889 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
10890 +              { 0, { 0 }, 0xFFFF } },
10891 +            nhelp,                                     /* helper */
10892 +            talk_nat_expected }                                /* expectfn */
10893 +       };
10894 +          
10895 +static unsigned int
10896 +talk_nat_expected(struct sk_buff **pskb,
10897 +                 unsigned int hooknum,
10898 +                 struct ip_conntrack *ct,
10899 +                 struct ip_nat_info *info)
10900 +{
10901 +       struct ip_nat_multi_range mr;
10902 +       u_int32_t newdstip, newsrcip, newip;
10903 +       u_int16_t port;
10904 +       unsigned int ret;
10905 +       
10906 +       struct ip_conntrack *master = master_ct(ct);
10907 +
10908 +       IP_NF_ASSERT(info);
10909 +       IP_NF_ASSERT(master);
10910 +
10911 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
10912 +
10913 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
10914 +
10915 +       LOCK_BH(&ip_talk_lock);
10916 +       port = ct->master->help.exp_talk_info.port;
10917 +       UNLOCK_BH(&ip_talk_lock);
10918 +
10919 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
10920 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10921 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10922 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10923 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10924 +              ct, master);
10925 +
10926 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10927 +               /* Callee client -> caller server */
10928 +#ifdef IP_NAT_TALK_DEBUG
10929 +               struct iphdr *iph = (*pskb)->nh.iph;
10930 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
10931 +
10932 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10933 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
10934 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
10935 +#endif
10936 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10937 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
10938 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10939 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
10940 +       } else {
10941 +               /* Callee client -> caller client */
10942 +#ifdef IP_NAT_TALK_DEBUG
10943 +               struct iphdr *iph = (*pskb)->nh.iph;
10944 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
10945 +
10946 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10947 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
10948 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
10949 +#endif
10950 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
10951 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10952 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10953 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
10954 +       }
10955 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
10956 +               newip = newsrcip;
10957 +       else
10958 +               newip = newdstip;
10959 +
10960 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
10961 +
10962 +       mr.rangesize = 1;
10963 +       /* We don't want to manip the per-protocol, just the IPs... */
10964 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10965 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
10966 +       
10967 +       /* ... unless we're doing a MANIP_DST, in which case, make
10968 +          sure we map to the correct port */
10969 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
10970 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
10971 +               mr.range[0].min = mr.range[0].max
10972 +                       = ((union ip_conntrack_manip_proto)
10973 +                               { .udp = { port } });
10974 +       }
10975 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
10976 +
10977 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10978 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
10979 +               /* NAT expectfn called with ip_nat_lock write-locked */
10980 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
10981 +       }
10982 +       return ret;
10983 +}
10984 +
10985 +static int __init init(void)
10986 +{
10987 +       int ret = 0;
10988 +
10989 +       if (talk > 0) {
10990 +               ret = ip_nat_helper_register(&talk_helpers[0]);
10991 +
10992 +               if (ret != 0)
10993 +                       return ret;
10994 +       }
10995 +       if (ntalk > 0 || ntalk2 > 0) {
10996 +               ret = ip_nat_helper_register(&talk_helpers[1]);
10997 +
10998 +               if (ret != 0 && talk > 0)
10999 +                       ip_nat_helper_unregister(&talk_helpers[0]);
11000 +       }
11001 +       return ret;
11002 +}
11003 +
11004 +static void __exit fini(void)
11005 +{
11006 +       if (talk > 0)
11007 +               ip_nat_helper_unregister(&talk_helpers[0]);
11008 +       if (ntalk > 0 || ntalk2 > 0)
11009 +               ip_nat_helper_unregister(&talk_helpers[1]);
11010 +}
11011 +
11012 +module_init(init);
11013 +module_exit(fini);
11014 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_tftp.c linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_tftp.c
11015 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_tftp.c     2003-11-26 21:43:31.000000000 +0100
11016 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_tftp.c 2003-12-10 23:13:21.271842272 +0100
11017 @@ -164,8 +164,6 @@
11018                 ports[0] = TFTP_PORT;
11019  
11020         for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
11021 -               memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
11022 -
11023                 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
11024                 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
11025                 tftp[i].mask.dst.protonum = 0xFFFF;
11026 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_pool.c linux-2.6.0-test11/net/ipv4/netfilter/ip_pool.c
11027 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
11028 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_pool.c     2003-12-10 23:13:39.982997744 +0100
11029 @@ -0,0 +1,332 @@
11030 +/* Kernel module for IP pool management */
11031 +
11032 +#include <linux/module.h>
11033 +#include <linux/ip.h>
11034 +#include <linux/skbuff.h>
11035 +#include <linux/netfilter_ipv4/ip_tables.h>
11036 +#include <linux/netfilter_ipv4/ip_pool.h>
11037 +#include <linux/errno.h>
11038 +#include <asm/uaccess.h>
11039 +#include <asm/bitops.h>
11040 +#include <linux/interrupt.h>
11041 +#include <linux/spinlock.h>
11042 +
11043 +#if 0
11044 +#define DP printk
11045 +#else
11046 +#define DP(format, args...)
11047 +#endif
11048 +
11049 +MODULE_LICENSE("GPL");
11050 +
11051 +#define NR_POOL 16
11052 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
11053 +
11054 +struct ip_pool {
11055 +       u_int32_t first_ip;     /* host byte order, included in range */
11056 +       u_int32_t last_ip;      /* host byte order, included in range */
11057 +       void *members;          /* the bitmap proper */
11058 +       int nr_use;             /* total nr. of tests through this */
11059 +       int nr_match;           /* total nr. of matches through this */
11060 +       rwlock_t lock;
11061 +};
11062 +
11063 +static struct ip_pool *POOL;
11064 +
11065 +static inline struct ip_pool *lookup(ip_pool_t index)
11066 +{
11067 +       if (index < 0 || index >= nr_pool) {
11068 +               DP("ip_pool:lookup: bad index %d\n", index);
11069 +               return 0;
11070 +       }
11071 +       return POOL+index;
11072 +}
11073 +
11074 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
11075 +{
11076 +        struct ip_pool *pool = lookup(index);
11077 +       int res = 0;
11078 +
11079 +       if (!pool || !pool->members)
11080 +               return 0;
11081 +       read_lock_bh(&pool->lock);
11082 +       if (pool->members) {
11083 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
11084 +                       addr -= pool->first_ip;
11085 +                       if (test_bit(addr, pool->members)) {
11086 +                               res = 1;
11087 +#ifdef CONFIG_IP_POOL_STATISTICS
11088 +                               pool->nr_match++;
11089 +#endif
11090 +                       }
11091 +               }
11092 +#ifdef CONFIG_IP_POOL_STATISTICS
11093 +               pool->nr_use++;
11094 +#endif
11095 +       }
11096 +       read_unlock_bh(&pool->lock);
11097 +       return res;
11098 +}
11099 +
11100 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
11101 +{
11102 +       struct ip_pool *pool;
11103 +       int res = -1;
11104 +
11105 +       pool = lookup(index);
11106 +       if (    !pool || !pool->members
11107 +            || addr < pool->first_ip || addr > pool->last_ip)
11108 +               return -1;
11109 +       read_lock_bh(&pool->lock);
11110 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
11111 +               addr -= pool->first_ip;
11112 +               res = isdel
11113 +                       ? (0 != test_and_clear_bit(addr, pool->members))
11114 +                       : (0 != test_and_set_bit(addr, pool->members));
11115 +       }
11116 +       read_unlock_bh(&pool->lock);
11117 +       return res;
11118 +}
11119 +
11120 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
11121 +{
11122 +       int res = pool_change(index,addr,isdel);
11123 +
11124 +       if (!isdel) res = !res;
11125 +       return res;
11126 +}
11127 +
11128 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
11129 +{
11130 +       return 4*((((b-a+8)/8)+3)/4);
11131 +}
11132 +
11133 +static inline int poolbytes(ip_pool_t index)
11134 +{
11135 +       struct ip_pool *pool = lookup(index);
11136 +
11137 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
11138 +}
11139 +
11140 +static int setpool(
11141 +       struct sock *sk,
11142 +       int optval,
11143 +       void *user,
11144 +       unsigned int len
11145 +) {
11146 +       struct ip_pool_request req;
11147 +
11148 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
11149 +       if (!capable(CAP_NET_ADMIN))
11150 +               return -EPERM;
11151 +       if (optval != SO_IP_POOL)
11152 +               return -EBADF;
11153 +       if (len != sizeof(req))
11154 +               return -EINVAL;
11155 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
11156 +               return -EFAULT;
11157 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
11158 +       return -EINVAL;
11159 +}
11160 +
11161 +static int getpool(
11162 +       struct sock *sk,
11163 +       int optval,
11164 +       void *user,
11165 +       int *len
11166 +) {
11167 +       struct ip_pool_request req;
11168 +       struct ip_pool *pool;
11169 +       ip_pool_t i;
11170 +       int newbytes;
11171 +       void *newmembers;
11172 +       int res;
11173 +
11174 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
11175 +       if (!capable(CAP_NET_ADMIN))
11176 +               return -EINVAL;
11177 +       if (optval != SO_IP_POOL)
11178 +               return -EINVAL;
11179 +       if (*len != sizeof(req)) {
11180 +               return -EFAULT;
11181 +       }
11182 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
11183 +               return -EFAULT;
11184 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
11185 +       if (req.op < IP_POOL_BAD001) {
11186 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
11187 +               return -EFAULT;
11188 +       }
11189 +       switch(req.op) {
11190 +       case IP_POOL_HIGH_NR:
11191 +               DP("ip_pool HIGH_NR\n");
11192 +               req.index = IP_POOL_NONE;
11193 +               for (i=0; i<nr_pool; i++)
11194 +                       if (POOL[i].members)
11195 +                               req.index = i;
11196 +               return copy_to_user(user, &req, sizeof(req));
11197 +       case IP_POOL_LOOKUP:
11198 +               DP("ip_pool LOOKUP\n");
11199 +               pool = lookup(req.index);
11200 +               if (!pool)
11201 +                       return -EINVAL;
11202 +               if (!pool->members)
11203 +                       return -EBADF;
11204 +               req.addr = htonl(pool->first_ip);
11205 +               req.addr2 = htonl(pool->last_ip);
11206 +               return copy_to_user(user, &req, sizeof(req));
11207 +       case IP_POOL_USAGE:
11208 +               DP("ip_pool USE\n");
11209 +               pool = lookup(req.index);
11210 +               if (!pool)
11211 +                       return -EINVAL;
11212 +               if (!pool->members)
11213 +                       return -EBADF;
11214 +               req.addr = pool->nr_use;
11215 +               req.addr2 = pool->nr_match;
11216 +               return copy_to_user(user, &req, sizeof(req));
11217 +       case IP_POOL_TEST_ADDR:
11218 +               DP("ip_pool TEST 0x%08x\n", req.addr);
11219 +               pool = lookup(req.index);
11220 +               if (!pool)
11221 +                       return -EINVAL;
11222 +               res = 0;
11223 +               read_lock_bh(&pool->lock);
11224 +               if (!pool->members) {
11225 +                       DP("ip_pool TEST_ADDR no members in pool\n");
11226 +                       res = -EBADF;
11227 +                       goto unlock_and_return_res;
11228 +               }
11229 +               req.addr = ntohl(req.addr);
11230 +               if (req.addr < pool->first_ip) {
11231 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
11232 +                       res = -ERANGE;
11233 +                       goto unlock_and_return_res;
11234 +               }
11235 +               if (req.addr > pool->last_ip) {
11236 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
11237 +                       res = -ERANGE;
11238 +                       goto unlock_and_return_res;
11239 +               }
11240 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
11241 +                                       pool->members));
11242 +               read_unlock_bh(&pool->lock);
11243 +               return copy_to_user(user, &req, sizeof(req));
11244 +       case IP_POOL_FLUSH:
11245 +               DP("ip_pool FLUSH not yet implemented.\n");
11246 +               return -EBUSY;
11247 +       case IP_POOL_DESTROY:
11248 +               DP("ip_pool DESTROY not yet implemented.\n");
11249 +               return -EBUSY;
11250 +       case IP_POOL_INIT:
11251 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
11252 +               pool = lookup(req.index);
11253 +               if (!pool)
11254 +                       return -EINVAL;
11255 +               req.addr = ntohl(req.addr);
11256 +               req.addr2 = ntohl(req.addr2);
11257 +               if (req.addr > req.addr2) {
11258 +                       DP("ip_pool INIT bad ip range\n");
11259 +                       return -EINVAL;
11260 +               }
11261 +               newbytes = bitmap_bytes(req.addr, req.addr2);
11262 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
11263 +               if (!newmembers) {
11264 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
11265 +                       return -ENOMEM;
11266 +               }
11267 +               memset(newmembers, 0, newbytes);
11268 +               write_lock_bh(&pool->lock);
11269 +               if (pool->members) {
11270 +                       DP("ip_pool INIT pool %d exists\n", req.index);
11271 +                       kfree(newmembers);
11272 +                       res = -EBUSY;
11273 +                       goto unlock_and_return_res;
11274 +               }
11275 +               pool->first_ip = req.addr;
11276 +               pool->last_ip = req.addr2;
11277 +               pool->nr_use = 0;
11278 +               pool->nr_match = 0;
11279 +               pool->members = newmembers;
11280 +               write_unlock_bh(&pool->lock);
11281 +               return 0;
11282 +       case IP_POOL_ADD_ADDR:
11283 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
11284 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
11285 +               return copy_to_user(user, &req, sizeof(req));
11286 +       case IP_POOL_DEL_ADDR:
11287 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
11288 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
11289 +               return copy_to_user(user, &req, sizeof(req));
11290 +       default:
11291 +               DP("ip_pool:getpool bad op %d\n", req.op);
11292 +               return -EINVAL;
11293 +       }
11294 +       return -EINVAL;
11295 +
11296 +unlock_and_return_res:
11297 +       if (pool)
11298 +               read_unlock_bh(&pool->lock);
11299 +       return res;
11300 +}
11301 +
11302 +static struct nf_sockopt_ops so_pool
11303 += { { NULL, NULL }, PF_INET,
11304 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
11305 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
11306 +    0, NULL };
11307 +
11308 +MODULE_PARM(nr_pool, "i");
11309 +
11310 +static int __init init(void)
11311 +{
11312 +       ip_pool_t i;
11313 +       int res;
11314 +
11315 +       if (nr_pool < 1) {
11316 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
11317 +               return -EINVAL;
11318 +       }
11319 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
11320 +       if (!POOL) {
11321 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
11322 +                       nr_pool);
11323 +               return -ENOMEM;
11324 +       }
11325 +       for (i=0; i<nr_pool; i++) {
11326 +               POOL[i].first_ip = 0;
11327 +               POOL[i].last_ip = 0;
11328 +               POOL[i].members = 0;
11329 +               POOL[i].nr_use = 0;
11330 +               POOL[i].nr_match = 0;
11331 +               POOL[i].lock = RW_LOCK_UNLOCKED;
11332 +       }
11333 +       res = nf_register_sockopt(&so_pool);
11334 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
11335 +       if (res != 0) {
11336 +               kfree(POOL);
11337 +               POOL = 0;
11338 +       }
11339 +       return res;
11340 +}
11341 +
11342 +static void __exit fini(void)
11343 +{
11344 +       ip_pool_t i;
11345 +
11346 +       DP("ip_pool:fini BYEBYE\n");
11347 +       nf_unregister_sockopt(&so_pool);
11348 +       for (i=0; i<nr_pool; i++) {
11349 +               if (POOL[i].members) {
11350 +                       kfree(POOL[i].members);
11351 +                       POOL[i].members = 0;
11352 +               }
11353 +       }
11354 +       kfree(POOL);
11355 +       POOL = 0;
11356 +       DP("ip_pool:fini these are the famous last words\n");
11357 +       return;
11358 +}
11359 +
11360 +module_init(init);
11361 +module_exit(fini);
11362 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_queue.c linux-2.6.0-test11/net/ipv4/netfilter/ip_queue.c
11363 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_queue.c        2003-11-26 21:46:12.000000000 +0100
11364 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_queue.c    2003-12-10 23:14:19.440999216 +0100
11365 @@ -417,6 +417,33 @@
11366  }
11367  
11368  static int
11369 +ipq_set_vwmark(struct ipq_vwmark_msg *vmsg, unsigned int len)
11370 +{
11371 +       struct ipq_queue_entry *entry;
11372 +
11373 +       if (vmsg->value > NF_MAX_VERDICT)
11374 +               return -EINVAL;
11375 +
11376 +       entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
11377 +       if (entry == NULL)
11378 +               return -ENOENT;
11379 +       else {
11380 +               int verdict = vmsg->value;
11381 +               
11382 +               if (vmsg->data_len && vmsg->data_len == len)
11383 +                       if (ipq_mangle_ipv4((ipq_verdict_msg_t *)vmsg, entry) < 0)
11384 +                               verdict = NF_DROP;
11385 +
11386 +               /* set mark of associated skb */
11387 +               entry->skb->nfmark = vmsg->nfmark;
11388 +               
11389 +               ipq_issue_verdict(entry, verdict);
11390 +               return 0;
11391 +       }
11392 +}
11393 +
11394 +
11395 +static int
11396  ipq_receive_peer(struct ipq_peer_msg *pmsg,
11397                   unsigned char type, unsigned int len)
11398  {
11399 @@ -438,6 +465,14 @@
11400                         status = ipq_set_verdict(&pmsg->msg.verdict,
11401                                                  len - sizeof(*pmsg));
11402                         break;
11403 +        case IPQM_VWMARK:
11404 +               if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
11405 +                       status = -EINVAL;
11406 +               else
11407 +                       status = ipq_set_vwmark(&pmsg->msg.vwmark,
11408 +                                                len - sizeof(*pmsg));
11409 +                       break;
11410 +
11411         default:
11412                 status = -EINVAL;
11413         }
11414 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.0-test11/net/ipv4/netfilter/iptable_filter.c
11415 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_filter.c  2003-11-26 21:43:35.000000000 +0100
11416 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_filter.c      2003-12-10 23:13:24.664326536 +0100
11417 @@ -52,7 +52,7 @@
11418                 0,
11419                 sizeof(struct ipt_entry),
11420                 sizeof(struct ipt_standard),
11421 -               0, { 0, 0 }, { } },
11422 +               0, NULL, 0, { 0, 0 }, { } },
11423               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11424                 -NF_ACCEPT - 1 } },
11425             /* FORWARD */
11426 @@ -60,7 +60,7 @@
11427                 0,
11428                 sizeof(struct ipt_entry),
11429                 sizeof(struct ipt_standard),
11430 -               0, { 0, 0 }, { } },
11431 +               0, NULL, 0, { 0, 0 }, { } },
11432               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11433                 -NF_ACCEPT - 1 } },
11434             /* LOCAL_OUT */
11435 @@ -68,7 +68,7 @@
11436                 0,
11437                 sizeof(struct ipt_entry),
11438                 sizeof(struct ipt_standard),
11439 -               0, { 0, 0 }, { } },
11440 +               0, NULL, 0, { 0, 0 }, { } },
11441               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11442                 -NF_ACCEPT - 1 } }
11443      },
11444 @@ -77,7 +77,7 @@
11445         0,
11446         sizeof(struct ipt_entry),
11447         sizeof(struct ipt_error),
11448 -       0, { 0, 0 }, { } },
11449 +       0, NULL, 0, { 0, 0 }, { } },
11450        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11451           { } },
11452         "ERROR"
11453 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.0-test11/net/ipv4/netfilter/iptable_mangle.c
11454 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_mangle.c  2003-11-26 21:45:28.000000000 +0100
11455 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_mangle.c      2003-12-10 23:13:24.665326384 +0100
11456 @@ -69,7 +69,7 @@
11457                 0,
11458                 sizeof(struct ipt_entry),
11459                 sizeof(struct ipt_standard),
11460 -               0, { 0, 0 }, { } },
11461 +               0, NULL, 0, { 0, 0 }, { } },
11462               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11463                 -NF_ACCEPT - 1 } },
11464             /* LOCAL_IN */
11465 @@ -77,7 +77,7 @@
11466                 0,
11467                 sizeof(struct ipt_entry),
11468                 sizeof(struct ipt_standard),
11469 -               0, { 0, 0 }, { } },
11470 +               0, NULL, 0, { 0, 0 }, { } },
11471               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11472                 -NF_ACCEPT - 1 } },
11473             /* FORWARD */
11474 @@ -85,7 +85,7 @@
11475                 0,
11476                 sizeof(struct ipt_entry),
11477                 sizeof(struct ipt_standard),
11478 -               0, { 0, 0 }, { } },
11479 +               0, NULL, 0, { 0, 0 }, { } },
11480               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11481                 -NF_ACCEPT - 1 } },
11482             /* LOCAL_OUT */
11483 @@ -93,7 +93,7 @@
11484                 0,
11485                 sizeof(struct ipt_entry),
11486                 sizeof(struct ipt_standard),
11487 -               0, { 0, 0 }, { } },
11488 +               0, NULL, 0, { 0, 0 }, { } },
11489               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11490                 -NF_ACCEPT - 1 } },
11491             /* POST_ROUTING */
11492 @@ -101,7 +101,7 @@
11493                 0,
11494                 sizeof(struct ipt_entry),
11495                 sizeof(struct ipt_standard),
11496 -               0, { 0, 0 }, { } },
11497 +               0, NULL, 0, { 0, 0 }, { } },
11498               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11499                 -NF_ACCEPT - 1 } },
11500      },
11501 @@ -110,7 +110,7 @@
11502         0,
11503         sizeof(struct ipt_entry),
11504         sizeof(struct ipt_error),
11505 -       0, { 0, 0 }, { } },
11506 +       0, NULL, 0, { 0, 0 }, { } },
11507        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11508           { } },
11509         "ERROR"
11510 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.0-test11/net/ipv4/netfilter/iptable_raw.c
11511 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_raw.c     1970-01-01 01:00:00.000000000 +0100
11512 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_raw.c 2003-12-10 23:13:24.665326384 +0100
11513 @@ -0,0 +1,153 @@
11514 +/* 
11515 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
11516 + *
11517 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
11518 + */
11519 +#include <linux/module.h>
11520 +#include <linux/netfilter_ipv4/ip_tables.h>
11521 +
11522 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
11523 +
11524 +/* Standard entry. */
11525 +struct ipt_standard
11526 +{
11527 +       struct ipt_entry entry;
11528 +       struct ipt_standard_target target;
11529 +};
11530 +
11531 +struct ipt_error_target
11532 +{
11533 +       struct ipt_entry_target target;
11534 +       char errorname[IPT_FUNCTION_MAXNAMELEN];
11535 +};
11536 +
11537 +struct ipt_error
11538 +{
11539 +       struct ipt_entry entry;
11540 +       struct ipt_error_target target;
11541 +};
11542 +
11543 +static struct
11544 +{
11545 +       struct ipt_replace repl;
11546 +       struct ipt_standard entries[2];
11547 +       struct ipt_error term;
11548 +} initial_table __initdata
11549 += { { "raw", RAW_VALID_HOOKS, 3,
11550 +      sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
11551 +      { [NF_IP_PRE_ROUTING] 0,
11552 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11553 +      { [NF_IP_PRE_ROUTING] 0,
11554 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11555 +      0, NULL, { } },
11556 +    {
11557 +           /* PRE_ROUTING */
11558 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11559 +               0,
11560 +               sizeof(struct ipt_entry),
11561 +               sizeof(struct ipt_standard),
11562 +               0, NULL, 0, { 0, 0 }, { } },
11563 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11564 +               -NF_ACCEPT - 1 } },
11565 +           /* LOCAL_OUT */
11566 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11567 +               0,
11568 +               sizeof(struct ipt_entry),
11569 +               sizeof(struct ipt_standard),
11570 +               0, NULL, 0, { 0, 0 }, { } },
11571 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11572 +               -NF_ACCEPT - 1 } }
11573 +    },
11574 +    /* ERROR */
11575 +    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11576 +       0,
11577 +       sizeof(struct ipt_entry),
11578 +       sizeof(struct ipt_error),
11579 +       0, NULL, 0, { 0, 0 }, { } },
11580 +      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11581 +         { } },
11582 +       "ERROR"
11583 +      }
11584 +    }
11585 +};
11586 +
11587 +static struct ipt_table packet_raw = {
11588 +       .name = "raw",
11589 +       .table = &initial_table.repl,
11590 +       .valid_hooks =  RAW_VALID_HOOKS,
11591 +       .lock = RW_LOCK_UNLOCKED,
11592 +       .me = THIS_MODULE,
11593 +};
11594 +
11595 +/* The work comes in here from netfilter.c. */
11596 +static unsigned int
11597 +ipt_hook(unsigned int hook,
11598 +        struct sk_buff **pskb,
11599 +        const struct net_device *in,
11600 +        const struct net_device *out,
11601 +        int (*okfn)(struct sk_buff *))
11602 +{
11603 +       return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
11604 +}
11605 +
11606 +/* 'raw' is the very first table. */
11607 +static struct nf_hook_ops ipt_ops[] = {
11608 +       {       /* PRE_ROUTING hook */
11609 +               .hook           = ipt_hook, 
11610 +               .owner          = THIS_MODULE,
11611 +               .pf             = PF_INET, 
11612 +               .hooknum        = NF_IP_PRE_ROUTING, 
11613 +               .priority       = NF_IP_PRI_RAW,
11614 +       },
11615 +       {       /* LOCAL_OUT hook */
11616 +               .hook           = ipt_hook,
11617 +               .owner          = THIS_MODULE,
11618 +               .pf             = PF_INET,
11619 +               .hooknum        = NF_IP_LOCAL_OUT,
11620 +               .priority       = NF_IP_PRI_RAW,
11621 +       },
11622 +};
11623 +
11624 +static int __init init(void)
11625 +{
11626 +       int ret;
11627 +
11628 +       /* Register table */
11629 +       ret = ipt_register_table(&packet_raw);
11630 +       if (ret < 0)
11631 +               return ret;
11632 +
11633 +       /* Register hooks */
11634 +       ret = nf_register_hook(&ipt_ops[0]);
11635 +       if (ret < 0)
11636 +               goto cleanup_table;
11637 +
11638 +       ret = nf_register_hook(&ipt_ops[1]);
11639 +       if (ret < 0)
11640 +               goto cleanup_hook0;
11641 +
11642 +       return ret;
11643 +
11644 + cleanup_hook0:
11645 +       nf_unregister_hook(&ipt_ops[0]);
11646 + cleanup_table:
11647 +       ipt_unregister_table(&packet_raw);
11648 +
11649 +       return ret;
11650 +}
11651 +
11652 +static void __exit fini(void)
11653 +{
11654 +       unsigned int i;
11655 +
11656 +       for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
11657 +               nf_unregister_hook(&ipt_ops[i]);
11658 +
11659 +       ipt_unregister_table(&packet_raw);
11660 +}
11661 +
11662 +module_init(init);
11663 +module_exit(fini);
11664 +MODULE_LICENSE("GPL");
11665 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11666 +MODULE_DESCRIPTION("IPv4 raw table");
11667 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ip_tables.c linux-2.6.0-test11/net/ipv4/netfilter/ip_tables.c
11668 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_tables.c       2003-11-26 21:43:25.000000000 +0100
11669 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_tables.c   2003-12-10 23:14:00.453885696 +0100
11670 @@ -4,6 +4,10 @@
11671   * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11672   * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
11673   *
11674 + *  6 Mar 2002 Robert Olsson <robban@robtex.com>
11675 + * 17 Apr 2003 Chris  Wilson <chris@netservers.co.uk>
11676 + *     - mark_source_chains speedup for complex chains
11677 + *
11678   * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
11679   *     - increase module usage count as soon as we have rules inside
11680   *       a table
11681 @@ -11,6 +15,7 @@
11682  #include <linux/config.h>
11683  #include <linux/cache.h>
11684  #include <linux/skbuff.h>
11685 +#include <linux/socket.h>
11686  #include <linux/kmod.h>
11687  #include <linux/vmalloc.h>
11688  #include <linux/netdevice.h>
11689 @@ -23,8 +28,17 @@
11690  #include <asm/semaphore.h>
11691  #include <linux/proc_fs.h>
11692  
11693 +#include <linux/netfilter.h>
11694  #include <linux/netfilter_ipv4/ip_tables.h>
11695  
11696 +static const char *hooknames[] = { 
11697 +       [NF_IP_PRE_ROUTING] "PREROUTING",
11698 +       [NF_IP_LOCAL_IN] "INPUT",
11699 +       [NF_IP_FORWARD] "FORWARD",
11700 +       [NF_IP_LOCAL_OUT] "OUTPUT",
11701 +       [NF_IP_POST_ROUTING] "POSTROUTING",
11702 +};
11703
11704  MODULE_LICENSE("GPL");
11705  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11706  MODULE_DESCRIPTION("IPv4 packet filter");
11707 @@ -322,6 +336,12 @@
11708  
11709                         t = ipt_get_target(e);
11710                         IP_NF_ASSERT(t->u.kernel.target);
11711 +
11712 +                       /* The packet traced and the rule isn't an unconditional return/END. */
11713 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {       
11714 +                               nf_log_packet(AF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
11715 +                                                table->name, e->chainname, e->rulenum);
11716 +                       }
11717                         /* Standard target? */
11718                         if (!t->u.kernel.target->target) {
11719                                 int v;
11720 @@ -474,6 +494,29 @@
11721         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
11722  }
11723  
11724 +static inline int
11725 +find_error_target(struct ipt_entry *s, 
11726 +                 struct ipt_entry *e,
11727 +                 char **chainname)
11728 +{
11729 +       struct ipt_entry_target *t;
11730 +       static struct ipt_entry *found = NULL;
11731 +
11732 +       if (s == e) {
11733 +               if (!found)
11734 +                       return 0;
11735 +               t = ipt_get_target(found);
11736 +               if (strcmp(t->u.user.name, 
11737 +                          IPT_ERROR_TARGET) == 0) {
11738 +                       *chainname = t->data;
11739 +                       return 1;
11740 +               }
11741 +       } else
11742 +               found = s;
11743 +       
11744 +       return 0;
11745 +}
11746 +
11747  /* All zeroes == unconditional rule. */
11748  static inline int
11749  unconditional(const struct ipt_ip *ip)
11750 @@ -493,6 +536,11 @@
11751  mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
11752  {
11753         unsigned int hook;
11754 +       char *chainname = NULL;
11755 +       u_int32_t rulenum;
11756 +
11757 +       /* keep track of where we have been: */
11758 +       unsigned char *been = vmalloc(newinfo->size);
11759  
11760         /* No recursion; use packet counter to save back ptrs (reset
11761            to 0 as we leave), and comefrom to save source hook bitmask */
11762 @@ -506,6 +554,9 @@
11763  
11764                 /* Set initial back pointer. */
11765                 e->counters.pcnt = pos;
11766 +               memset(been, 0, newinfo->size);
11767 +               rulenum = 1;
11768 +               chainname = (char *) hooknames[hook];
11769  
11770                 for (;;) {
11771                         struct ipt_standard_target *t
11772 @@ -514,10 +565,13 @@
11773                         if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
11774                                 printk("iptables: loop hook %u pos %u %08X.\n",
11775                                        hook, pos, e->comefrom);
11776 +                               vfree(been);
11777                                 return 0;
11778                         }
11779                         e->comefrom
11780                                 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
11781 +                       e->rulenum = rulenum++;
11782 +                       e->chainname = chainname;
11783  
11784                         /* Unconditional return/END. */
11785                         if (e->target_offset == sizeof(struct ipt_entry)
11786 @@ -527,6 +581,10 @@
11787                             && unconditional(&e->ip)) {
11788                                 unsigned int oldpos, size;
11789  
11790 +                               /* Set unconditional rulenum to zero. */
11791 +                               e->rulenum = 0;
11792 +                               e->counters.bcnt = 0;
11793 +
11794                                 /* Return: backtrack through the last
11795                                    big jump. */
11796                                 do {
11797 @@ -552,6 +610,11 @@
11798                                                 (newinfo->entries + pos);
11799                                 } while (oldpos == pos + e->next_offset);
11800  
11801 +                               /* Restore chainname, rulenum. */
11802 +                               chainname = e->chainname;
11803 +                               rulenum = e->counters.bcnt;
11804 +                               e->counters.bcnt = 0;
11805 +
11806                                 /* Move along one */
11807                                 size = e->next_offset;
11808                                 e = (struct ipt_entry *)
11809 @@ -561,12 +624,27 @@
11810                         } else {
11811                                 int newpos = t->verdict;
11812  
11813 -                               if (strcmp(t->target.u.user.name,
11814 +                               if ( (pos < 0 || pos >= newinfo->size
11815 +                                     || !been[pos]) 
11816 +                                   && strcmp(t->target.u.user.name,
11817                                            IPT_STANDARD_TARGET) == 0
11818                                     && newpos >= 0) {
11819                                         /* This a jump; chase it. */
11820 +                                       if (pos >= 0 && pos < newinfo->size)
11821 +                                               been[pos]++;
11822                                         duprintf("Jump rule %u -> %u\n",
11823                                                  pos, newpos);
11824 +                                       e->counters.bcnt = rulenum++;
11825 +                                       rulenum = 1;
11826 +                                       e = (struct ipt_entry *)
11827 +                                               (newinfo->entries + newpos);
11828 +                                       if (IPT_ENTRY_ITERATE(newinfo->entries,
11829 +                                                             newinfo->size,
11830 +                                                             find_error_target,
11831 +                                                             e, &chainname) == 0) {
11832 +                                               printk("ip_tables: table screwed up!\n");
11833 +                                               return 0;
11834 +                                       }
11835                                 } else {
11836                                         /* ... this is a fallthru */
11837                                         newpos = pos + e->next_offset;
11838 @@ -580,6 +658,7 @@
11839                 next:
11840                 duprintf("Finished chain %u\n", hook);
11841         }
11842 +       vfree(been);
11843         return 1;
11844  }
11845  
11846 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_addrtype.c
11847 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_addrtype.c    1970-01-01 01:00:00.000000000 +0100
11848 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_addrtype.c        2003-12-10 23:13:51.092308872 +0100
11849 @@ -0,0 +1,65 @@
11850 +/*
11851 + *  iptables module to match inet_addr_type() of an ip.
11852 + */
11853 +
11854 +#include <linux/module.h>
11855 +#include <linux/skbuff.h>
11856 +#include <linux/netdevice.h>
11857 +#include <net/route.h>
11858 +
11859 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
11860 +#include <linux/netfilter_ipv4/ip_tables.h>
11861 +
11862 +MODULE_LICENSE("GPL");
11863 +
11864 +static inline int match_type(u_int32_t addr, u_int16_t mask)
11865 +{
11866 +       return !!(mask & (1 << inet_addr_type(addr)));
11867 +}
11868 +
11869 +static int match(const struct sk_buff *skb, const struct net_device *in,
11870 +                const struct net_device *out, const void *matchinfo,
11871 +                int offset, const void *hdr, u_int16_t datalen,
11872 +                int *hotdrop)
11873 +{
11874 +       const struct ipt_addrtype_info *info = matchinfo;
11875 +       const struct iphdr *iph = skb->nh.iph;
11876 +       int ret = 1;
11877 +
11878 +       if (info->source)
11879 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
11880 +       if (info->dest)
11881 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
11882 +       
11883 +       return ret;
11884 +}
11885 +
11886 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
11887 +                     void *matchinfo, unsigned int matchsize,
11888 +                     unsigned int hook_mask)
11889 +{
11890 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
11891 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
11892 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
11893 +               return 0;
11894 +       }
11895 +
11896 +       return 1;
11897 +}
11898 +
11899 +static struct ipt_match addrtype_match = { { NULL, NULL }, "addrtype", &match,
11900 +               &checkentry, NULL, THIS_MODULE };
11901 +
11902 +static int __init init(void)
11903 +{
11904 +       return ipt_register_match(&addrtype_match);
11905 +}
11906 +
11907 +static void __exit fini(void)
11908 +{
11909 +       ipt_unregister_match(&addrtype_match);
11910 +
11911 +}
11912 +
11913 +module_init(init);
11914 +module_exit(fini);
11915 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_condition.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_condition.c
11916 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_condition.c   1970-01-01 01:00:00.000000000 +0100
11917 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_condition.c       2003-12-10 23:13:53.356964592 +0100
11918 @@ -0,0 +1,256 @@
11919 +/*-------------------------------------------*\
11920 +|          Netfilter Condition Module         |
11921 +|                                             |
11922 +|  Description: This module allows firewall   |
11923 +|    rules to match using condition variables |
11924 +|    stored in /proc files.                   |
11925 +|                                             |
11926 +|  Author: Stephane Ouellette     2002-10-22  |
11927 +|          <ouellettes@videotron.ca>          |
11928 +|                                             |
11929 +|  History:                                   |
11930 +|    2003-02-10  Second version with improved |
11931 +|                locking and simplified code. |
11932 +|                                             |
11933 +|  This software is distributed under the     |
11934 +|  terms of the GNU GPL.                      |
11935 +\*-------------------------------------------*/
11936 +
11937 +#include<linux/module.h>
11938 +#include<linux/proc_fs.h>
11939 +#include<linux/spinlock.h>
11940 +#include<linux/string.h>
11941 +#include<asm/atomic.h>
11942 +#include<linux/netfilter_ipv4/ip_tables.h>
11943 +#include<linux/netfilter_ipv4/ipt_condition.h>
11944 +
11945 +
11946 +#ifndef CONFIG_PROC_FS
11947 +#error  "Proc file system support is required for this module"
11948 +#endif
11949 +
11950 +
11951 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
11952 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
11953 +MODULE_LICENSE("GPL");
11954 +
11955 +
11956 +struct condition_variable {
11957 +       struct condition_variable *next;
11958 +       struct proc_dir_entry *status_proc;
11959 +       atomic_t refcount;
11960 +        int enabled;   /* TRUE == 1, FALSE == 0 */
11961 +};
11962 +
11963 +
11964 +static rwlock_t list_lock;
11965 +static struct condition_variable *head = NULL;
11966 +static struct proc_dir_entry *proc_net_condition = NULL;
11967 +
11968 +
11969 +static int
11970 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
11971 +                       int length, int *eof, void *data)
11972 +{
11973 +       struct condition_variable *var =
11974 +           (struct condition_variable *) data;
11975 +
11976 +       if (offset == 0) {
11977 +               *start = buffer;
11978 +               buffer[0] = (var->enabled) ? '1' : '0';
11979 +               buffer[1] = '\n';
11980 +               return 2;
11981 +       }
11982 +
11983 +       *eof = 1;
11984 +       return 0;
11985 +}
11986 +
11987 +
11988 +static int
11989 +ipt_condition_write_info(struct file *file, const char *buffer,
11990 +                        unsigned long length, void *data)
11991 +{
11992 +       struct condition_variable *var =
11993 +           (struct condition_variable *) data;
11994 +
11995 +       if (length) {
11996 +               /* Match only on the first character */
11997 +               switch (buffer[0]) {
11998 +               case '0':
11999 +                       var->enabled = 0;
12000 +                       break;
12001 +               case '1':
12002 +                       var->enabled = 1;
12003 +               }
12004 +       }
12005 +
12006 +       return (int) length;
12007 +}
12008 +
12009 +
12010 +static int
12011 +match(const struct sk_buff *skb, const struct net_device *in,
12012 +      const struct net_device *out, const void *matchinfo, int offset,
12013 +      const void *hdr, u_int16_t datalen, int *hotdrop)
12014 +{
12015 +       const struct condition_info *info =
12016 +           (const struct condition_info *) matchinfo;
12017 +       struct condition_variable *var;
12018 +       int condition_status = 0;
12019 +
12020 +       read_lock(&list_lock);
12021 +
12022 +       for (var = head; var; var = var->next) {
12023 +               if (strcmp(info->name, var->status_proc->name) == 0) {
12024 +                       condition_status = var->enabled;
12025 +                       break;
12026 +               }
12027 +       }
12028 +
12029 +       read_unlock(&list_lock);
12030 +
12031 +       return condition_status ^ info->invert;
12032 +}
12033 +
12034 +
12035 +
12036 +static int
12037 +checkentry(const char *tablename, const struct ipt_ip *ip,
12038 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
12039 +{
12040 +       struct condition_info *info = (struct condition_info *) matchinfo;
12041 +       struct condition_variable *var, *newvar;
12042 +
12043 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12044 +               return 0;
12045 +
12046 +       /* The first step is to check if the condition variable already exists. */
12047 +       /* Here, a read lock is sufficient because we won't change the list */
12048 +       read_lock(&list_lock);
12049 +
12050 +       for (var = head; var; var = var->next) {
12051 +               if (strcmp(info->name, var->status_proc->name) == 0) {
12052 +                       atomic_inc(&var->refcount);
12053 +                       read_unlock(&list_lock);
12054 +                       return 1;
12055 +               }
12056 +       }
12057 +
12058 +       read_unlock(&list_lock);
12059 +
12060 +       /* At this point, we need to allocate a new condition variable */
12061 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
12062 +
12063 +       if (!newvar)
12064 +               return -ENOMEM;
12065 +
12066 +       /* Create the condition variable's proc file entry */
12067 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
12068 +
12069 +       if (!newvar->status_proc) {
12070 +         /*
12071 +          * There are two possibilities:
12072 +          *  1- Another condition variable with the same name has been created, which is valid.
12073 +          *  2- There was a memory allocation error.
12074 +          */
12075 +               kfree(newvar);
12076 +               read_lock(&list_lock);
12077 +
12078 +               for (var = head; var; var = var->next) {
12079 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
12080 +                               atomic_inc(&var->refcount);
12081 +                               read_unlock(&list_lock);
12082 +                               return 1;
12083 +                       }
12084 +               }
12085 +
12086 +               read_unlock(&list_lock);
12087 +               return -ENOMEM;
12088 +       }
12089 +
12090 +       atomic_set(&newvar->refcount, 1);
12091 +       newvar->enabled = 0;
12092 +       newvar->status_proc->owner = THIS_MODULE;
12093 +       newvar->status_proc->data = newvar;
12094 +       wmb();
12095 +       newvar->status_proc->read_proc = ipt_condition_read_info;
12096 +       newvar->status_proc->write_proc = ipt_condition_write_info;
12097 +
12098 +       write_lock(&list_lock);
12099 +
12100 +       newvar->next = head;
12101 +       head = newvar;
12102 +
12103 +       write_unlock(&list_lock);
12104 +
12105 +       return 1;
12106 +}
12107 +
12108 +
12109 +static void
12110 +destroy(void *matchinfo, unsigned int matchsize)
12111 +{
12112 +       struct condition_info *info = (struct condition_info *) matchinfo;
12113 +       struct condition_variable *var, *prev = NULL;
12114 +
12115 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12116 +               return;
12117 +
12118 +       write_lock(&list_lock);
12119 +
12120 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
12121 +            prev = var, var = var->next);
12122 +
12123 +       if (var && atomic_dec_and_test(&var->refcount)) {
12124 +               if (prev)
12125 +                       prev->next = var->next;
12126 +               else
12127 +                       head = var->next;
12128 +
12129 +               write_unlock(&list_lock);
12130 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
12131 +               kfree(var);
12132 +       } else
12133 +               write_unlock(&list_lock);
12134 +}
12135 +
12136 +
12137 +static struct ipt_match condition_match = {
12138 +       .name = "condition",
12139 +       .match = &match,
12140 +       .checkentry = &checkentry,
12141 +       .destroy = &destroy,
12142 +       .me = THIS_MODULE
12143 +};
12144 +
12145 +
12146 +static int __init
12147 +init(void)
12148 +{
12149 +       int errorcode;
12150 +
12151 +       rwlock_init(&list_lock);
12152 +       proc_net_condition = proc_mkdir("ipt_condition", proc_net);
12153 +
12154 +       if (proc_net_condition) {
12155 +               errorcode = ipt_register_match(&condition_match);
12156 +
12157 +               if (errorcode)
12158 +                       remove_proc_entry("ipt_condition", proc_net);
12159 +       } else
12160 +               errorcode = -EACCES;
12161 +
12162 +       return errorcode;
12163 +}
12164 +
12165 +
12166 +static void __exit
12167 +fini(void)
12168 +{
12169 +       ipt_unregister_match(&condition_match);
12170 +       remove_proc_entry("ipt_condition", proc_net);
12171 +}
12172 +
12173 +module_init(init);
12174 +module_exit(fini);
12175 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_connlimit.c
12176 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connlimit.c   1970-01-01 01:00:00.000000000 +0100
12177 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connlimit.c       2003-12-10 23:13:26.811000192 +0100
12178 @@ -0,0 +1,232 @@
12179 +/*
12180 + * netfilter module to limit the number of parallel tcp
12181 + * connections per IP address.
12182 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
12183 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
12184 + *             only ignore TIME_WAIT or gone connections
12185 + *
12186 + * based on ...
12187 + *
12188 + * Kernel module to match connection tracking information.
12189 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
12190 + */
12191 +#include <linux/module.h>
12192 +#include <linux/skbuff.h>
12193 +#include <linux/list.h>
12194 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12195 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
12196 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
12197 +#include <linux/netfilter_ipv4/ip_tables.h>
12198 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
12199 +
12200 +#define DEBUG 0
12201 +
12202 +MODULE_LICENSE("GPL");
12203 +
12204 +/* we'll save the tuples of all connections we care about */
12205 +struct ipt_connlimit_conn
12206 +{
12207 +        struct list_head list;
12208 +       struct ip_conntrack_tuple tuple;
12209 +};
12210 +
12211 +struct ipt_connlimit_data {
12212 +       spinlock_t lock;
12213 +       struct list_head iphash[256];
12214 +};
12215 +
12216 +static int ipt_iphash(u_int32_t addr)
12217 +{
12218 +       int hash;
12219 +
12220 +       hash  =  addr        & 0xff;
12221 +       hash ^= (addr >>  8) & 0xff;
12222 +       hash ^= (addr >> 16) & 0xff;
12223 +       hash ^= (addr >> 24) & 0xff;
12224 +       return hash;
12225 +}
12226 +
12227 +static int count_them(struct ipt_connlimit_data *data,
12228 +                     u_int32_t addr, u_int32_t mask,
12229 +                     struct ip_conntrack *ct)
12230 +{
12231 +#if DEBUG
12232 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
12233 +                                    "fin_wait", "time_wait", "close", "close_wait",
12234 +                                    "last_ack", "listen" };
12235 +#endif
12236 +       int addit = 1, matches = 0;
12237 +       struct ip_conntrack_tuple tuple;
12238 +       struct ip_conntrack_tuple_hash *found;
12239 +       struct ipt_connlimit_conn *conn;
12240 +       struct list_head *hash,*lh;
12241 +
12242 +       spin_lock(&data->lock);
12243 +       tuple = ct->tuplehash[0].tuple;
12244 +       hash = &data->iphash[ipt_iphash(addr & mask)];
12245 +
12246 +       /* check the saved connections */
12247 +       for (lh = hash->next; lh != hash; lh = lh->next) {
12248 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
12249 +               found = ip_conntrack_find_get(&conn->tuple,ct);
12250 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
12251 +                   found != NULL &&
12252 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
12253 +                       /* Just to be sure we have it only once in the list.
12254 +                          We should'nt see tuples twice unless someone hooks this
12255 +                          into a table without "-p tcp --syn" */
12256 +                       addit = 0;
12257 +               }
12258 +#if DEBUG
12259 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
12260 +                      ipt_iphash(addr & mask),
12261 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
12262 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
12263 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
12264 +#endif
12265 +               if (NULL == found) {
12266 +                       /* this one is gone */
12267 +                       lh = lh->prev;
12268 +                       list_del(lh->next);
12269 +                       kfree(conn);
12270 +                       continue;
12271 +               }
12272 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
12273 +                       /* we don't care about connections which are
12274 +                          closed already -> ditch it */
12275 +                       lh = lh->prev;
12276 +                       list_del(lh->next);
12277 +                       kfree(conn);
12278 +                       nf_conntrack_put(&found->ctrack->infos[0]);
12279 +                       continue;
12280 +               }
12281 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
12282 +                       /* same source IP address -> be counted! */
12283 +                       matches++;
12284 +               }
12285 +               nf_conntrack_put(&found->ctrack->infos[0]);
12286 +       }
12287 +       if (addit) {
12288 +               /* save the new connection in our list */
12289 +#if DEBUG
12290 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
12291 +                      ipt_iphash(addr & mask),
12292 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
12293 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
12294 +#endif
12295 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
12296 +               if (NULL == conn)
12297 +                       return -1;
12298 +               memset(conn,0,sizeof(*conn));
12299 +               INIT_LIST_HEAD(&conn->list);
12300 +               conn->tuple = tuple;
12301 +               list_add(&conn->list,hash);
12302 +               matches++;
12303 +       }
12304 +       spin_unlock(&data->lock);
12305 +       return matches;
12306 +}
12307 +
12308 +static int
12309 +match(const struct sk_buff *skb,
12310 +      const struct net_device *in,
12311 +      const struct net_device *out,
12312 +      const void *matchinfo,
12313 +      int offset,
12314 +      const void *hdr,
12315 +      u_int16_t datalen,
12316 +      int *hotdrop)
12317 +{
12318 +       const struct ipt_connlimit_info *info = matchinfo;
12319 +       int connections, match;
12320 +       struct ip_conntrack *ct;
12321 +       enum ip_conntrack_info ctinfo;
12322 +
12323 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12324 +       if (NULL == ct) {
12325 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
12326 +               *hotdrop = 1;
12327 +               return 0;
12328 +       }
12329 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
12330 +       if (-1 == connections) {
12331 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
12332 +               *hotdrop = 1; /* let's free some memory :-) */
12333 +               return 0;
12334 +       }
12335 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
12336 +#if DEBUG
12337 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
12338 +              "connections=%d limit=%d match=%s\n",
12339 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
12340 +              connections, info->limit, match ? "yes" : "no");
12341 +#endif
12342 +
12343 +       return match;
12344 +}
12345 +
12346 +static int check(const char *tablename,
12347 +                const struct ipt_ip *ip,
12348 +                void *matchinfo,
12349 +                unsigned int matchsize,
12350 +                unsigned int hook_mask)
12351 +{
12352 +       struct ipt_connlimit_info *info = matchinfo;
12353 +       int i;
12354 +
12355 +       /* verify size */
12356 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
12357 +               return 0;
12358 +
12359 +       /* refuse anything but tcp */
12360 +       if (ip->proto != IPPROTO_TCP)
12361 +               return 0;
12362 +
12363 +       /* init private data */
12364 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
12365 +       spin_lock_init(&(info->data->lock));
12366 +       for (i = 0; i < 256; i++)
12367 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
12368 +       
12369 +       return 1;
12370 +}
12371 +
12372 +static void destroy(void *matchinfo, unsigned int matchinfosize)
12373 +{
12374 +       struct ipt_connlimit_info *info = matchinfo;
12375 +       struct ipt_connlimit_conn *conn;
12376 +       struct list_head *hash;
12377 +       int i;
12378 +
12379 +       /* cleanup */
12380 +       for (i = 0; i < 256; i++) {
12381 +               hash = &(info->data->iphash[i]);
12382 +               while (hash != hash->next) {
12383 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
12384 +                       list_del(hash->next);
12385 +                       kfree(conn);
12386 +               }
12387 +       }
12388 +       kfree(info->data);
12389 +}
12390 +
12391 +static struct ipt_match connlimit_match
12392 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
12393 +
12394 +static int __init init(void)
12395 +{
12396 +       /* NULL if ip_conntrack not a module */
12397 +       if (ip_conntrack_module)
12398 +               __MOD_INC_USE_COUNT(ip_conntrack_module);
12399 +       return ipt_register_match(&connlimit_match);
12400 +}
12401 +
12402 +static void __exit fini(void)
12403 +{
12404 +       ipt_unregister_match(&connlimit_match);
12405 +       if (ip_conntrack_module)
12406 +               __MOD_DEC_USE_COUNT(ip_conntrack_module);
12407 +}
12408 +
12409 +module_init(init);
12410 +module_exit(fini);
12411 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_connmark.c
12412 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connmark.c    1970-01-01 01:00:00.000000000 +0100
12413 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connmark.c        2003-12-10 23:13:54.582778240 +0100
12414 @@ -0,0 +1,55 @@
12415 +/* Kernel module to match connection mark values. */
12416 +#include <linux/module.h>
12417 +#include <linux/skbuff.h>
12418 +
12419 +#include <linux/netfilter_ipv4/ip_tables.h>
12420 +#include <linux/netfilter_ipv4/ipt_connmark.h>
12421 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12422 +
12423 +static int
12424 +match(const struct sk_buff *skb,
12425 +      const struct net_device *in,
12426 +      const struct net_device *out,
12427 +      const void *matchinfo,
12428 +      int offset,
12429 +      const void *hdr,
12430 +      u_int16_t datalen,
12431 +      int *hotdrop)
12432 +{
12433 +       const struct ipt_connmark_info *info = matchinfo;
12434 +       enum ip_conntrack_info ctinfo;
12435 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12436 +       if (!ct)
12437 +           return 0;
12438 +
12439 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
12440 +}
12441 +
12442 +static int
12443 +checkentry(const char *tablename,
12444 +           const struct ipt_ip *ip,
12445 +           void *matchinfo,
12446 +           unsigned int matchsize,
12447 +           unsigned int hook_mask)
12448 +{
12449 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
12450 +               return 0;
12451 +
12452 +       return 1;
12453 +}
12454 +
12455 +static struct ipt_match connmark_match
12456 += { { NULL, NULL }, "connmark", &match, &checkentry, NULL, THIS_MODULE };
12457 +
12458 +static int __init init(void)
12459 +{
12460 +       return ipt_register_match(&connmark_match);
12461 +}
12462 +
12463 +static void __exit fini(void)
12464 +{
12465 +       ipt_unregister_match(&connmark_match);
12466 +}
12467 +
12468 +module_init(init);
12469 +module_exit(fini);
12470 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_CONNMARK.c
12471 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_CONNMARK.c    1970-01-01 01:00:00.000000000 +0100
12472 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_CONNMARK.c        2003-12-10 23:13:54.583778088 +0100
12473 @@ -0,0 +1,87 @@
12474 +/* This is a module which is used for setting/remembering the mark field of
12475 + * an connection, or optionally restore it to the skb
12476 + */
12477 +#include <linux/module.h>
12478 +#include <linux/skbuff.h>
12479 +#include <linux/ip.h>
12480 +#include <net/checksum.h>
12481 +
12482 +#include <linux/netfilter_ipv4/ip_tables.h>
12483 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
12484 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12485 +
12486 +static unsigned int
12487 +target(struct sk_buff **pskb,
12488 +       unsigned int hooknum,
12489 +       const struct net_device *in,
12490 +       const struct net_device *out,
12491 +       const void *targinfo,
12492 +       void *userinfo)
12493 +{
12494 +       const struct ipt_connmark_target_info *markinfo = targinfo;
12495 +
12496 +       enum ip_conntrack_info ctinfo;
12497 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
12498 +       if (ct) {
12499 +           switch(markinfo->mode) {
12500 +           case IPT_CONNMARK_SET:
12501 +               ct->mark = markinfo->mark;
12502 +               break;
12503 +           case IPT_CONNMARK_SAVE:
12504 +               ct->mark = (*pskb)->nfmark;
12505 +               break;
12506 +           case IPT_CONNMARK_RESTORE:
12507 +               if (ct->mark != (*pskb)->nfmark) {
12508 +                   (*pskb)->nfmark = ct->mark;
12509 +                   (*pskb)->nfcache |= NFC_ALTERED;
12510 +               }
12511 +               break;
12512 +           }
12513 +       }
12514 +
12515 +       return IPT_CONTINUE;
12516 +}
12517 +
12518 +static int
12519 +checkentry(const char *tablename,
12520 +          const struct ipt_entry *e,
12521 +           void *targinfo,
12522 +           unsigned int targinfosize,
12523 +           unsigned int hook_mask)
12524 +{
12525 +       struct ipt_connmark_target_info *matchinfo = targinfo;
12526 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
12527 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
12528 +                      targinfosize,
12529 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
12530 +               return 0;
12531 +       }
12532 +
12533 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
12534 +           if (strcmp(tablename, "mangle") != 0) {
12535 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
12536 +                   return 0;
12537 +           }
12538 +       }
12539 +
12540 +       return 1;
12541 +}
12542 +
12543 +static struct ipt_target ipt_connmark_reg
12544 += { { NULL, NULL }, "CONNMARK", target, checkentry, NULL, THIS_MODULE };
12545 +
12546 +static int __init init(void)
12547 +{
12548 +       if (ipt_register_target(&ipt_connmark_reg))
12549 +               return -EINVAL;
12550 +
12551 +       return 0;
12552 +}
12553 +
12554 +static void __exit fini(void)
12555 +{
12556 +       ipt_unregister_target(&ipt_connmark_reg);
12557 +}
12558 +
12559 +module_init(init);
12560 +module_exit(fini);
12561 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_conntrack.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_conntrack.c
12562 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_conntrack.c   2003-11-26 21:45:34.000000000 +0100
12563 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_conntrack.c       2003-12-10 23:13:24.664326536 +0100
12564 @@ -29,7 +29,9 @@
12565  
12566  #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
12567  
12568 -       if (ct)
12569 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
12570 +               statebit = IPT_CONNTRACK_STATE_UNTRACKED;
12571 +       else if (ct)
12572                 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
12573         else
12574                 statebit = IPT_CONNTRACK_STATE_INVALID;
12575 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_dstlimit.c
12576 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_dstlimit.c    1970-01-01 01:00:00.000000000 +0100
12577 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_dstlimit.c        2003-12-10 23:13:27.869839224 +0100
12578 @@ -0,0 +1,623 @@
12579 +/* iptables match extension to limit the number of packets per second
12580 + * seperately for each destination.
12581 + *
12582 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
12583 + *
12584 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
12585 + *
12586 + * based on ipt_limit.c by:
12587 + * JĆ©rĆ“me de Vivie     <devivie@info.enserb.u-bordeaux.fr>
12588 + * HervĆ© Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
12589 + * Rusty Russell       <rusty@rustcorp.com.au>
12590 + *
12591 + * The general idea is to create a hash table for every dstip and have a
12592 + * seperate limit counter per tuple.  This way you can do something like 'limit
12593 + * the number of syn packets for each of my internal addresses.
12594 + *
12595 + * Ideally this would just be implemented as a general 'hash' match, which would
12596 + * allow us to attach any iptables target to it's hash buckets.  But this is
12597 + * not possible in the current iptables architecture.  As always, pkttables for
12598 + * 2.7.x will help ;)
12599 + */
12600 +#include <linux/module.h>
12601 +#include <linux/skbuff.h>
12602 +#include <linux/spinlock.h>
12603 +#include <linux/random.h>
12604 +#include <linux/jhash.h>
12605 +#include <linux/slab.h>
12606 +#include <linux/vmalloc.h>
12607 +#include <linux/tcp.h>
12608 +#include <linux/udp.h>
12609 +#include <linux/proc_fs.h>
12610 +#include <linux/seq_file.h>
12611 +
12612 +#define ASSERT_READ_LOCK(x) 
12613 +#define ASSERT_WRITE_LOCK(x) 
12614 +#include <linux/netfilter_ipv4/lockhelp.h>
12615 +#include <linux/netfilter_ipv4/listhelp.h>
12616 +
12617 +#include <linux/netfilter_ipv4/ip_tables.h>
12618 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
12619 +
12620 +/* FIXME: this is just for IP_NF_ASSERRT */
12621 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12622 +
12623 +#define MS2JIFFIES(x) ((x*HZ)/1000)
12624 +
12625 +MODULE_LICENSE("GPL");
12626 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
12627 +MODULE_DESCRIPTION("iptables match for limiting per destination");
12628 +
12629 +/* need to declare this at the top */
12630 +static struct proc_dir_entry *dstlimit_procdir;
12631 +static struct file_operations dl_file_ops;
12632 +
12633 +/* hash table crap */
12634 +
12635 +struct dsthash_dst {
12636 +       u_int32_t src_ip;
12637 +       u_int32_t dst_ip;
12638 +       u_int16_t port;
12639 +};
12640 +
12641 +struct dsthash_ent {
12642 +       /* static / read-only parts in the beginning */
12643 +       struct list_head list;
12644 +       struct dsthash_dst dst;
12645 +
12646 +       /* modified structure members in the end */
12647 +       unsigned long expires;          /* precalculated expiry time */
12648 +       struct {
12649 +               unsigned long prev;     /* last modification */
12650 +               u_int32_t credit;
12651 +               u_int32_t credit_cap, cost;
12652 +       } rateinfo;
12653 +};
12654 +
12655 +struct ipt_dstlimit_htable {
12656 +       struct ipt_dstlimit_info *minfo; /* public structure */
12657 +
12658 +       /* used internally */
12659 +       spinlock_t lock;                /* lock for list_head */
12660 +       u_int32_t rnd;                  /* random seed for hash */
12661 +       struct timer_list timer;        /* timer for gc */
12662 +       atomic_t count;                 /* number entries in table */
12663 +
12664 +       /* seq_file stuff */
12665 +       struct proc_dir_entry *pde;
12666 +
12667 +       struct list_head hash[0];       /* hashtable itself */
12668 +};
12669 +
12670 +static kmem_cache_t *dstlimit_cachep;
12671 +
12672 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
12673 +{
12674 +       return (ent->dst.dst_ip == b->dst_ip 
12675 +               && ent->dst.port == b->port
12676 +               && ent->dst.src_ip == b->src_ip);
12677 +}
12678 +
12679 +static inline u_int32_t
12680 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
12681 +{
12682 +       return (jhash_3words(dst->dst_ip, dst->port, 
12683 +                            dst->src_ip, ht->rnd) % ht->minfo->size);
12684 +}
12685 +
12686 +static inline struct dsthash_ent *
12687 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12688 +{
12689 +       struct dsthash_ent *ent;
12690 +       u_int32_t hash = hash_dst(ht, dst);
12691 +       MUST_BE_LOCKED(&ht->lock);
12692 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
12693 +       return ent;
12694 +}
12695 +
12696 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
12697 +static struct dsthash_ent *
12698 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12699 +{
12700 +       struct dsthash_ent *ent;
12701 +
12702 +       /* initialize hash with random val at the time we allocate
12703 +        * the first hashtable entry */
12704 +       if (!ht->rnd)
12705 +               get_random_bytes(&ht->rnd, 4);
12706 +
12707 +       if (ht->minfo->max &&
12708 +           atomic_read(&ht->count) >= ht->minfo->max) {
12709 +               /* FIXME: do something. question is what.. */
12710 +               if (net_ratelimit())
12711 +                       printk("max count of %u reached\n", ht->minfo->max);
12712 +               return NULL;
12713 +       }
12714 +
12715 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
12716 +       if (!ent) {
12717 +               if (net_ratelimit())
12718 +                       printk("Can't allocate dsthash_ent\n");
12719 +               return NULL;
12720 +       }
12721 +
12722 +       atomic_inc(&ht->count);
12723 +
12724 +       ent->dst.dst_ip = dst->dst_ip;
12725 +       ent->dst.port = dst->port;
12726 +       ent->dst.src_ip = dst->src_ip;
12727 +
12728 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
12729 +
12730 +       return ent;
12731 +}
12732 +
12733 +static inline void 
12734 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
12735 +{
12736 +       MUST_BE_LOCKED(&ht->lock);
12737 +
12738 +       list_del(&ent->list);
12739 +       kmem_cache_free(dstlimit_cachep, ent);
12740 +       atomic_dec(&ht->count);
12741 +}
12742 +
12743 +static void htable_gc(unsigned long htlong);
12744 +
12745 +static int htable_create(struct ipt_dstlimit_info *minfo)
12746 +{
12747 +       int i;
12748 +       struct ipt_dstlimit_htable *hinfo;
12749 +
12750 +       if (!minfo->size) {
12751 +               minfo->size = (((num_physpages << PAGE_SHIFT) / 16384)
12752 +                           / sizeof(struct list_head));
12753 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
12754 +                       minfo->size = 8192;
12755 +               if (minfo->size < 16)
12756 +                       minfo->size = 16;
12757 +       }
12758 +       if (!minfo->max)
12759 +               minfo->max = 8 * minfo->size;
12760 +       else if (minfo->max < minfo->size)
12761 +               minfo->max = minfo->size;
12762 +
12763 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
12764 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
12765 +                       + (sizeof(struct list_head) * minfo->size));
12766 +       if (!hinfo) {
12767 +               printk(KERN_ERR "Unable to create ipt_dstlimit hash\n");
12768 +               return -1;
12769 +       }
12770 +
12771 +       for (i = 0; i < minfo->size; i++)
12772 +               INIT_LIST_HEAD(&hinfo->hash[i]);
12773 +
12774 +       minfo->hinfo = hinfo;
12775 +
12776 +       hinfo->minfo = minfo;
12777 +       atomic_set(&hinfo->count, 0);
12778 +       hinfo->rnd = 0;
12779 +
12780 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
12781 +
12782 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
12783 +       if (!hinfo->pde) {
12784 +               vfree(hinfo);
12785 +               return -1;
12786 +       }
12787 +       hinfo->pde->proc_fops = &dl_file_ops;
12788 +       hinfo->pde->data = hinfo;
12789 +
12790 +       init_timer(&hinfo->timer);
12791 +       hinfo->timer.expires = jiffies + MS2JIFFIES(minfo->gc_interval);
12792 +       hinfo->timer.data = (unsigned long )hinfo;
12793 +       hinfo->timer.function = htable_gc;
12794 +       add_timer(&hinfo->timer);
12795 +
12796 +       return 0;
12797 +}
12798 +
12799 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12800 +{
12801 +       return 1;
12802 +}
12803 +
12804 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12805 +{
12806 +       return (jiffies >= he->expires);
12807 +}
12808 +
12809 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
12810 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
12811 +                                             struct dsthash_ent *he))
12812 +{
12813 +       int i;
12814 +
12815 +       IP_NF_ASSERT(ht->minfo->size && ht->minfo->max);
12816 +
12817 +       /* lock hash table and iterate over it */
12818 +       LOCK_BH(&ht->lock);
12819 +       for (i = 0; i < ht->minfo->size; i++) {
12820 +               struct dsthash_ent *dh, *n;
12821 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
12822 +                       if ((*select)(ht, dh))
12823 +                               __dsthash_free(ht, dh);
12824 +               }
12825 +       }
12826 +       UNLOCK_BH(&ht->lock);
12827 +}
12828 +
12829 +/* hash table garbage collector, run by timer */
12830 +static void htable_gc(unsigned long htlong)
12831 +{
12832 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
12833 +
12834 +       htable_selective_cleanup(ht, select_gc);
12835 +
12836 +       /* re-add the timer accordingly */
12837 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->minfo->gc_interval);
12838 +       add_timer(&ht->timer);
12839 +}
12840 +
12841 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
12842 + * see net/sched/sch_tbf.c in the linux source tree
12843 + */
12844 +
12845 +/* Rusty: This is my (non-mathematically-inclined) understanding of
12846 +   this algorithm.  The `average rate' in jiffies becomes your initial
12847 +   amount of credit `credit' and the most credit you can ever have
12848 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
12849 +   test, `cost'.
12850 +
12851 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
12852 +   If you get credit balance more than this, the extra credit is
12853 +   discarded.  Every time the match passes, you lose `cost' credits;
12854 +   if you don't have that many, the test fails.
12855 +
12856 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
12857 +
12858 +   To get the maximum range, we multiply by this factor (ie. you get N
12859 +   credits per jiffy).  We want to allow a rate as low as 1 per day
12860 +   (slowest userspace tool allows), which means
12861 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
12862 +*/
12863 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
12864 +
12865 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
12866 + * us the power of 2 below the theoretical max, so GCC simply does a
12867 + * shift. */
12868 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
12869 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
12870 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
12871 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
12872 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
12873 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
12874 +
12875 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
12876 +
12877 +/* Precision saver. */
12878 +static inline u_int32_t
12879 +user2credits(u_int32_t user)
12880 +{
12881 +       /* If multiplying would overflow... */
12882 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
12883 +               /* Divide first. */
12884 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
12885 +
12886 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
12887 +}
12888 +
12889 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
12890 +{
12891 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
12892 +                                       * CREDITS_PER_JIFFY;
12893 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
12894 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
12895 +}
12896 +
12897 +static int
12898 +dstlimit_match(const struct sk_buff *skb,
12899 +               const struct net_device *in,
12900 +               const struct net_device *out,
12901 +               const void *matchinfo,
12902 +               int offset,
12903 +               const void *hdr,
12904 +               u_int16_t datalen,
12905 +               int *hotdrop)
12906 +{
12907 +       struct ipt_dstlimit_info *r = 
12908 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
12909 +       unsigned long now = jiffies;
12910 +       struct dsthash_ent *dh;
12911 +       struct dsthash_dst dst;
12912 +
12913 +       memset(&dst, 0, sizeof(dst));
12914 +
12915 +       /* dest ip is always in hash */
12916 +       dst.dst_ip = skb->nh.iph->daddr;
12917 +
12918 +       /* source ip only if respective hashmode, otherwise set to
12919 +        * zero */
12920 +       if (r->mode & IPT_DSTLIMIT_HASH_SIP)
12921 +               dst.src_ip = skb->nh.iph->saddr;
12922 +
12923 +       /* dest port only if respective mode */
12924 +       if (r->mode & IPT_DSTLIMIT_HASH_DPT) {
12925 +               switch (skb->nh.iph->protocol) {
12926 +                       struct tcphdr *th;
12927 +                       struct udphdr *uh;
12928 +               case IPPROTO_TCP:
12929 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12930 +                       dst.port = th->dest;
12931 +                       break;
12932 +               case IPPROTO_UDP:
12933 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12934 +                       dst.port = uh->dest;
12935 +                       break;
12936 +               default:
12937 +                       break;
12938 +               }
12939 +       } 
12940 +
12941 +       LOCK_BH(&r->hinfo->lock);
12942 +       dh = __dsthash_find(r->hinfo, &dst);
12943 +       if (!dh) {
12944 +               dh = __dsthash_alloc_init(r->hinfo, &dst);
12945 +
12946 +               if (!dh) {
12947 +                       /* enomem... don't match == DROP */
12948 +                       if (net_ratelimit())
12949 +                               printk("%s: ENOMEM\n", __FUNCTION__);
12950 +                       UNLOCK_BH(&r->hinfo->lock);
12951 +                       return 0;
12952 +               }
12953 +
12954 +               dh->expires = jiffies + MS2JIFFIES(r->expire);
12955 +
12956 +               dh->rateinfo.prev = jiffies;
12957 +               dh->rateinfo.credit = user2credits(r->avg * r->burst);
12958 +               dh->rateinfo.credit_cap = user2credits(r->avg * r->burst);
12959 +               dh->rateinfo.cost = user2credits(r->avg);
12960 +
12961 +               UNLOCK_BH(&r->hinfo->lock);
12962 +               return 0;
12963 +       }
12964 +
12965 +       /* update expiration timeout */
12966 +       dh->expires = now + MS2JIFFIES(r->expire);
12967 +
12968 +       rateinfo_recalc(dh, now);
12969 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
12970 +               /* We're underlimit. */
12971 +               dh->rateinfo.credit -= dh->rateinfo.cost;
12972 +               UNLOCK_BH(&r->hinfo->lock);
12973 +               return 1;
12974 +       }
12975 +
12976 +               UNLOCK_BH(&r->hinfo->lock);
12977 +
12978 +       /* default case: we're overlimit, thus don't match */
12979 +       return 0;
12980 +}
12981 +
12982 +static int
12983 +dstlimit_checkentry(const char *tablename,
12984 +                    const struct ipt_ip *ip,
12985 +                    void *matchinfo,
12986 +                    unsigned int matchsize,
12987 +                    unsigned int hook_mask)
12988 +{
12989 +       struct ipt_dstlimit_info *r = matchinfo;
12990 +
12991 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
12992 +               return 0;
12993 +
12994 +       /* Check for overflow. */
12995 +       if (r->burst == 0
12996 +           || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
12997 +               printk("Overflow in ipt_dstlimit, try lower: %u/%u\n",
12998 +                      r->avg, r->burst);
12999 +               return 0;
13000 +       }
13001 +
13002 +       if (r->mode == 0 
13003 +           || r->mode > (IPT_DSTLIMIT_HASH_DPT
13004 +                         |IPT_DSTLIMIT_HASH_DIP
13005 +                         |IPT_DSTLIMIT_HASH_SIP))
13006 +               return 0;
13007 +
13008 +       if (!r->gc_interval)
13009 +               return 0;
13010 +       
13011 +       if (!r->expire)
13012 +               return 0;
13013 +
13014 +       if (htable_create(r) != 0) {
13015 +               printk("Unable to create dstlimit htable\n");
13016 +               return 0;
13017 +       }
13018 +
13019 +       /* Ugly hack: For SMP, we only want to use one set */
13020 +       r->u.master = r;
13021 +
13022 +       return 1;
13023 +}
13024 +
13025 +static void
13026 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
13027 +{
13028 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
13029 +
13030 +       r = r->u.master;
13031 +
13032 +       /* remove timer, if it is pending */
13033 +       if (timer_pending(&r->hinfo->timer))
13034 +               del_timer(&r->hinfo->timer);
13035 +
13036 +       /* remove proc entry */
13037 +       remove_proc_entry(r->name, dstlimit_procdir);
13038 +
13039 +       htable_selective_cleanup(r->hinfo, select_all);
13040 +       vfree(&r->hinfo);
13041 +}
13042 +
13043 +static struct ipt_match ipt_dstlimit = { 
13044 +       .list = { .prev = NULL, .next = NULL }, 
13045 +       .name = "dstlimit", 
13046 +       .match = dstlimit_match, 
13047 +       .checkentry = dstlimit_checkentry, 
13048 +       .destroy = dstlimit_destroy,
13049 +       .me = THIS_MODULE 
13050 +};
13051 +
13052 +/* PROC stuff */
13053 +
13054 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
13055 +{
13056 +       struct proc_dir_entry *pde = s->private;
13057 +       struct ipt_dstlimit_htable *htable = pde->data;
13058 +       unsigned int *bucket;
13059 +
13060 +       LOCK_BH(&htable->lock);
13061 +       if (*pos >= htable->minfo->size)
13062 +               return NULL;
13063 +
13064 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
13065 +       if (!bucket)
13066 +               return ERR_PTR(-ENOMEM);
13067 +
13068 +       *bucket = *pos;
13069 +       return bucket;
13070 +}
13071 +
13072 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
13073 +{
13074 +       struct proc_dir_entry *pde = s->private;
13075 +       struct ipt_dstlimit_htable *htable = pde->data;
13076 +       unsigned int *bucket = (unsigned int *)v;
13077 +
13078 +       *pos = ++(*bucket);
13079 +       if (*pos >= htable->minfo->size) {
13080 +               kfree(v);
13081 +               return NULL;
13082 +       }
13083 +       return bucket;
13084 +}
13085 +
13086 +static void dl_seq_stop(struct seq_file *s, void *v)
13087 +{
13088 +       struct proc_dir_entry *pde = s->private;
13089 +       struct ipt_dstlimit_htable *htable = pde->data;
13090 +
13091 +       UNLOCK_BH(&htable->lock);
13092 +}
13093 +
13094 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
13095 +{
13096 +       /* recalculate to show accurate numbers */
13097 +       rateinfo_recalc(ent, jiffies);
13098 +
13099 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
13100 +                       (ent->expires - jiffies)/HZ,
13101 +                       NIPQUAD(ent->dst.src_ip),
13102 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
13103 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
13104 +                       ent->rateinfo.cost);
13105 +}
13106 +
13107 +static int dl_seq_show(struct seq_file *s, void *v)
13108 +{
13109 +       struct proc_dir_entry *pde = s->private;
13110 +       struct ipt_dstlimit_htable *htable = pde->data;
13111 +       unsigned int *bucket = (unsigned int *)v;
13112 +
13113 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
13114 +                     struct dsthash_ent *, s)) {
13115 +               /* buffer was filled and unable to print that tuple */
13116 +               return 1;
13117 +       }
13118 +       return 0;
13119 +}
13120 +
13121 +static struct seq_operations dl_seq_ops = {
13122 +       .start = dl_seq_start,
13123 +       .next  = dl_seq_next,
13124 +       .stop  = dl_seq_stop,
13125 +       .show  = dl_seq_show
13126 +};
13127 +
13128 +static int dl_proc_open(struct inode *inode, struct file *file)
13129 +{
13130 +       int ret = seq_open(file, &dl_seq_ops);
13131 +
13132 +       if (!ret) {
13133 +               struct seq_file *sf = file->private_data;
13134 +               sf->private = PDE(inode);
13135 +       }
13136 +       return ret;
13137 +}
13138 +
13139 +static struct file_operations dl_file_ops = {
13140 +       .owner   = THIS_MODULE,
13141 +       .open    = dl_proc_open,
13142 +       .read    = seq_read,
13143 +       .llseek  = seq_lseek,
13144 +       .release = seq_release
13145 +};
13146 +
13147 +static int init_or_fini(int fini)
13148 +{
13149 +       int ret = 0;
13150 +
13151 +       if (fini)
13152 +               goto cleanup;
13153 +
13154 +       if (ipt_register_match(&ipt_dstlimit)) {
13155 +               ret = -EINVAL;
13156 +               goto cleanup_nothing;
13157 +       }
13158 +
13159 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
13160 +        * quite small ? */
13161 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
13162 +                                           sizeof(struct dsthash_ent), 0,
13163 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
13164 +       if (!dstlimit_cachep) {
13165 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
13166 +               ret = -ENOMEM;
13167 +               goto cleanup_unreg_match;
13168 +       }
13169 +
13170 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
13171 +       if (!dstlimit_procdir) {
13172 +               printk(KERN_ERR "Unable to create proc dir entry\n");
13173 +               ret = -ENOMEM;
13174 +               goto cleanup_free_slab;
13175 +       }
13176 +
13177 +       return ret;
13178 +
13179 +cleanup:
13180 +       remove_proc_entry("ipt_dstlimit", proc_net);
13181 +cleanup_free_slab:
13182 +       kmem_cache_destroy(dstlimit_cachep);
13183 +cleanup_unreg_match:
13184 +       ipt_unregister_match(&ipt_dstlimit);
13185 +cleanup_nothing:
13186 +       return ret;
13187 +       
13188 +}
13189 +
13190 +static int __init init(void)
13191 +{
13192 +       return init_or_fini(0);
13193 +}
13194 +
13195 +static void __exit fini(void)
13196 +{
13197 +       init_or_fini(1);
13198 +}
13199 +
13200 +module_init(init);
13201 +module_exit(fini);
13202 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_fuzzy.c
13203 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_fuzzy.c       1970-01-01 01:00:00.000000000 +0100
13204 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_fuzzy.c   2003-12-10 23:13:30.017512728 +0100
13205 @@ -0,0 +1,190 @@
13206 +/*
13207 + *  This module implements a simple TSK FLC 
13208 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
13209 + * to limit , in an adaptive and flexible way , the packet rate crossing 
13210 + * a given stream . It serves as an initial and very simple (but effective)
13211 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
13212 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
13213 + * into our code in a precise , adaptive and efficient manner. 
13214 + *  The goal is very similar to that of "limit" match , but using techniques of
13215 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
13216 + * avoiding over and undershoots - and stuff like that .
13217 + *
13218 + *
13219 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
13220 + * 2002-08-17  : Changed to eliminate floating point operations .
13221 + * 2002-08-23  : Coding style changes .
13222 +*/
13223 +
13224 +#include <linux/module.h>
13225 +#include <linux/skbuff.h>
13226 +#include <linux/ip.h>
13227 +#include <linux/random.h>
13228 +#include <net/tcp.h>
13229 +#include <linux/spinlock.h>
13230 +#include <linux/netfilter_ipv4/ip_tables.h>
13231 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
13232 +
13233 +/*
13234 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
13235 + Expressed in percentage
13236 +*/
13237 +
13238 +#define PAR_LOW                1/100
13239 +#define PAR_HIGH       1
13240 +
13241 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
13242 +
13243 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
13244 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
13245 +MODULE_LICENSE("GPL");
13246 +
13247 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13248 +{
13249 +       if (tx >= maxi) return 100;
13250 +
13251 +       if (tx <= mini) return 0;
13252 +
13253 +       return ( (100*(tx-mini)) / (maxi-mini) ) ;
13254 +}
13255 +
13256 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13257 +{
13258 +       if (tx <= mini) return 100;
13259 +
13260 +       if (tx >= maxi) return 0;
13261 +
13262 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) ) ;
13263 +
13264 +}
13265 +
13266 +static int
13267 +ipt_fuzzy_match(const struct sk_buff *pskb,
13268 +              const struct net_device *in,
13269 +              const struct net_device *out,
13270 +              const void *matchinfo,
13271 +              int offset,
13272 +              const void *hdr,
13273 +              u_int16_t datalen,
13274 +              int *hotdrop)
13275 +{
13276 +       /* From userspace */
13277 +       
13278 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
13279 +
13280 +       u_int8_t random_number;
13281 +       unsigned long amount ;
13282 +       u_int8_t howhigh , howlow ;
13283 +       
13284 +
13285 +       spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
13286 +
13287 +       info->bytes_total += pskb->len ;
13288 +       info->packets_total++ ;
13289 +
13290 +       info->present_time = jiffies ;
13291 +       
13292 +       if ( info->present_time >= info->previous_time )
13293 +               amount = info->present_time - info->previous_time ;
13294 +       else { 
13295 +               /* There was a transition : I choose to re-sample 
13296 +                  and keep the old acceptance rate...
13297 +               */
13298 +
13299 +               amount = 0 ;
13300 +               info->previous_time = info->present_time ;
13301 +               info->bytes_total = info->packets_total = 0;
13302 +            };
13303 +       
13304 +       if (  amount > HZ/10 ) /* More than 100 ms elapsed ... */
13305 +               {
13306 +
13307 +       info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total )  \
13308 +                                       / amount ) ;
13309 +
13310 +               info->previous_time = info->present_time ;
13311 +               info->bytes_total = info->packets_total = 0 ;
13312 +
13313 +       howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
13314 +       howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
13315 +
13316 +    info->acceptance_rate = (u_int8_t) \
13317 +                          ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
13318 +
13319 +    /* In fact , the above defuzzification would require a denominator
13320 +       proportional to (howhigh+howlow) but , in this particular case ,
13321 +       that expression is constant .
13322 +        An imediate consequence is that it isn't necessary to call 
13323 +       both mf_high and mf_low - but to keep things understandable ,
13324 +       I did so .
13325 +     */ 
13326 +
13327 +               }
13328 +       
13329 +       spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
13330 +
13331 +
13332 +       if ( info->acceptance_rate < 100 )
13333 +       {                
13334 +               get_random_bytes((void *)(&random_number), 1);
13335 +
13336 +               /*  If within the acceptance , it can pass => don't match */
13337 +               if ( random_number <= (255 * info->acceptance_rate) / 100 )
13338 +                       return 0 ;
13339 +               else
13340 +                       return 1; /* It can't pass ( It matches ) */
13341 +       } ;
13342 +
13343 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
13344 +       
13345 +}
13346 +
13347 +static int
13348 +ipt_fuzzy_checkentry(const char *tablename,
13349 +                  const struct ipt_ip *e,
13350 +                  void *matchinfo,
13351 +                  unsigned int matchsize,
13352 +                  unsigned int hook_mask)
13353 +{
13354 +       
13355 +       const struct ipt_fuzzy_info *info = matchinfo;
13356 +
13357 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
13358 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
13359 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
13360 +               return 0;
13361 +       }
13362 +
13363 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
13364 +       || (info->minimum_rate >= info->maximum_rate ))
13365 +               {
13366 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
13367 +               return 0;
13368 +               }
13369 +
13370 +       return 1;
13371 +}
13372 +
13373 +static struct ipt_match ipt_fuzzy_reg = { 
13374 +       {NULL, NULL},
13375 +       "fuzzy",
13376 +       ipt_fuzzy_match,
13377 +       ipt_fuzzy_checkentry,
13378 +       NULL,
13379 +       THIS_MODULE };
13380 +
13381 +static int __init init(void)
13382 +{
13383 +       if (ipt_register_match(&ipt_fuzzy_reg))
13384 +               return -EINVAL;
13385 +
13386 +       return 0;
13387 +}
13388 +
13389 +static void __exit fini(void)
13390 +{
13391 +       ipt_unregister_match(&ipt_fuzzy_reg);
13392 +}
13393 +
13394 +module_init(init);
13395 +module_exit(fini);
13396 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPMARK.c
13397 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPMARK.c      1970-01-01 01:00:00.000000000 +0100
13398 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPMARK.c  2003-12-10 23:13:59.369050616 +0100
13399 @@ -0,0 +1,88 @@
13400 +/* This is a module which is used for setting the NFMARK field of an skb. */
13401 +#include <linux/module.h>
13402 +#include <linux/skbuff.h>
13403 +#include <linux/ip.h>
13404 +#include <net/checksum.h>
13405 +
13406 +#include <linux/netfilter_ipv4/ip_tables.h>
13407 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
13408 +
13409 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
13410 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
13411 +MODULE_LICENSE("GPL");
13412 +
13413 +static unsigned int
13414 +target(struct sk_buff **pskb,
13415 +       unsigned int hooknum,
13416 +       const struct net_device *in,
13417 +       const struct net_device *out,
13418 +       const void *targinfo,
13419 +       void *userinfo)
13420 +{
13421 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
13422 +
13423 +       struct iphdr *iph = (*pskb)->nh.iph;
13424 +
13425 +       unsigned long mark;
13426 +       char *a, t;
13427 +
13428 +       if(ipmarkinfo->addr == IPT_IPMARK_SRC)
13429 +         mark = (unsigned long) iph->saddr;
13430 +       else
13431 +         mark = (unsigned long) iph->daddr;
13432 +
13433 +// mark has ip address in little indian, we have to change the byte order:
13434 +       a = (char *) &mark;
13435 +       t = *a; *a=*(a+3); *(a+3)=t;
13436 +       t=*(a+1); *(a+1)=*(a+2); *(a+2)=t;
13437 +
13438 +       mark &= ipmarkinfo->andmask;
13439 +       mark |= ipmarkinfo->ormask;
13440 +       
13441 +       if((*pskb)->nfmark != mark) {
13442 +               (*pskb)->nfmark = mark;
13443 +               (*pskb)->nfcache |= NFC_ALTERED;
13444 +       }
13445 +       return IPT_CONTINUE;
13446 +}
13447 +
13448 +static int
13449 +checkentry(const char *tablename,
13450 +          const struct ipt_entry *e,
13451 +           void *targinfo,
13452 +           unsigned int targinfosize,
13453 +           unsigned int hook_mask)
13454 +{
13455 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
13456 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
13457 +                      targinfosize,
13458 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
13459 +               return 0;
13460 +       }
13461 +
13462 +       if (strcmp(tablename, "mangle") != 0) {
13463 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13464 +               return 0;
13465 +       }
13466 +
13467 +       return 1;
13468 +}
13469 +
13470 +static struct ipt_target ipt_ipmark_reg
13471 += { { NULL, NULL }, "IPMARK", target, checkentry, NULL, THIS_MODULE };
13472 +
13473 +static int __init init(void)
13474 +{
13475 +       if (ipt_register_target(&ipt_ipmark_reg))
13476 +               return -EINVAL;
13477 +
13478 +       return 0;
13479 +}
13480 +
13481 +static void __exit fini(void)
13482 +{
13483 +       ipt_unregister_target(&ipt_ipmark_reg);
13484 +}
13485 +
13486 +module_init(init);
13487 +module_exit(fini);
13488 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipv4options.c
13489 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
13490 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipv4options.c     2003-12-10 23:13:32.270170272 +0100
13491 @@ -0,0 +1,170 @@
13492 +/*
13493 +  This is a module which is used to match ipv4 options.
13494 +  This file is distributed under the terms of the GNU General Public
13495 +  License (GPL). Copies of the GPL can be obtained from:
13496 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
13497 +
13498 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
13499 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
13500 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
13501 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
13502 +*/
13503 +
13504 +#include <linux/module.h>
13505 +#include <linux/skbuff.h>
13506 +#include <net/ip.h>
13507 +
13508 +#include <linux/netfilter_ipv4/ip_tables.h>
13509 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
13510 +
13511 +MODULE_LICENSE("GPL");
13512 +
13513 +static int
13514 +match(const struct sk_buff *skb,
13515 +      const struct net_device *in,
13516 +      const struct net_device *out,
13517 +      const void *matchinfo,
13518 +      int offset,
13519 +      const void *hdr,
13520 +      u_int16_t datalen,
13521 +      int *hotdrop)
13522 +{
13523 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
13524 +       const struct iphdr *iph = skb->nh.iph;
13525 +       const struct ip_options *opt;
13526 +
13527 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
13528 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
13529 +
13530 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
13531 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13532 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13533 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13534 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13535 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
13536 +                       return 0;
13537 +               return 1;
13538 +       }
13539 +       else {
13540 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
13541 +                       /* there are options, and we don't need to care which one */
13542 +                       return 1;
13543 +               else {
13544 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
13545 +                               /* there are options but we don't want any ! */
13546 +                               return 0;
13547 +               }
13548 +       }
13549 +
13550 +       opt = &(IPCB(skb)->opt);
13551 +
13552 +       /* source routing */
13553 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
13554 +               if (!((opt->srr) & (opt->is_strictroute)))
13555 +                       return 0;
13556 +       }
13557 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
13558 +               if (!((opt->srr) & (!opt->is_strictroute)))
13559 +                       return 0;
13560 +       }
13561 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
13562 +               if (opt->srr)
13563 +                       return 0;
13564 +       }
13565 +       /* record route */
13566 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
13567 +               if (!opt->rr)
13568 +                       return 0;
13569 +       }
13570 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
13571 +               if (opt->rr)
13572 +                       return 0;
13573 +       }
13574 +       /* timestamp */
13575 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
13576 +               if (!opt->ts)
13577 +                       return 0;
13578 +       }
13579 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
13580 +               if (opt->ts)
13581 +                       return 0;
13582 +       }
13583 +       /* router-alert option  */
13584 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
13585 +               if (!opt->router_alert)
13586 +                       return 0;
13587 +       }
13588 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
13589 +               if (opt->router_alert)
13590 +                       return 0;
13591 +       }
13592 +
13593 +       /* we match ! */
13594 +       return 1;
13595 +}
13596 +
13597 +static int
13598 +checkentry(const char *tablename,
13599 +          const struct ipt_ip *ip,
13600 +          void *matchinfo,
13601 +          unsigned int matchsize,
13602 +          unsigned int hook_mask)
13603 +{
13604 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
13605 +       /* Check the size */
13606 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
13607 +               return 0;
13608 +       /* Now check the coherence of the data ... */
13609 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
13610 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
13611 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
13612 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
13613 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
13614 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
13615 +               return 0; /* opposites */
13616 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
13617 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13618 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13619 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13620 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13621 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
13622 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
13623 +               return 0; /* opposites */
13624 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
13625 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
13626 +               return 0; /* cannot match in the same time loose and strict source routing */
13627 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13628 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
13629 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
13630 +               return 0; /* opposites */
13631 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
13632 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
13633 +               return 0; /* opposites */
13634 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
13635 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
13636 +               return 0; /* opposites */
13637 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
13638 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
13639 +               return 0; /* opposites */
13640 +
13641 +       /* everything looks ok. */
13642 +       return 1;
13643 +}
13644 +
13645 +static struct ipt_match ipv4options_match
13646 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
13647 +
13648 +static int __init init(void)
13649 +{
13650 +       printk("ipt_ipv4options loading\n");
13651 +       return ipt_register_match(&ipv4options_match);
13652 +}
13653 +
13654 +static void __exit fini(void)
13655 +{
13656 +       ipt_unregister_match(&ipv4options_match);
13657 +       printk("ipt_ipv4options unloaded\n");
13658 +}
13659 +
13660 +module_init(init);
13661 +module_exit(fini);
13662 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
13663 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c       1970-01-01 01:00:00.000000000 +0100
13664 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c   2003-12-10 23:13:33.336008240 +0100
13665 @@ -0,0 +1,84 @@
13666 +/**
13667 + * Strip all IP options in the IP packet header.
13668 + *
13669 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
13670 + * This software is distributed under GNU GPL v2, 1991
13671 + */
13672 +
13673 +#include <linux/module.h>
13674 +#include <linux/skbuff.h>
13675 +#include <linux/ip.h>
13676 +#include <net/checksum.h>
13677 +
13678 +#include <linux/netfilter_ipv4/ip_tables.h>
13679 +
13680 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
13681 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
13682 +MODULE_LICENSE("GPL");
13683 +
13684 +static unsigned int
13685 +target(struct sk_buff **pskb,
13686 +       unsigned int hooknum,
13687 +       const struct net_device *in,
13688 +       const struct net_device *out,
13689 +       const void *targinfo,
13690 +       void *userinfo)
13691 +{
13692 +       struct iphdr *iph = (*pskb)->nh.iph;
13693 +       struct sk_buff *skb = (*pskb);
13694 +       struct ip_options * opt;
13695 +       unsigned char * optiph = skb->nh.raw;
13696 +       int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
13697 +       
13698 +
13699 +       /* if no options in packet then nothing to clear. */
13700 +       if (iph->ihl * 4 == sizeof(struct iphdr))
13701 +               return IPT_CONTINUE;
13702 +
13703 +       /* else clear all options */
13704 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
13705 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
13706 +       opt = &(IPCB(skb)->opt);
13707 +       opt->is_data = 0;
13708 +       opt->optlen = l;
13709 +
13710 +       skb->nfcache |= NFC_ALTERED;
13711 +
13712 +        return IPT_CONTINUE;
13713 +}
13714 +
13715 +static int
13716 +checkentry(const char *tablename,
13717 +          const struct ipt_entry *e,
13718 +           void *targinfo,
13719 +           unsigned int targinfosize,
13720 +           unsigned int hook_mask)
13721 +{
13722 +       if (strcmp(tablename, "mangle")) {
13723 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13724 +               return 0;
13725 +       }
13726 +       /* nothing else to check because no parameters */
13727 +       return 1;
13728 +}
13729 +
13730 +static struct ipt_target ipt_ipv4optsstrip_reg
13731 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
13732 +
13733 +static int __init init(void)
13734 +{
13735 +       if (ipt_register_target(&ipt_ipv4optsstrip_reg))
13736 +               return -EINVAL;
13737 +       printk("ipt_IPV4OPTSSTRIP loaded\n");
13738 +
13739 +       return 0;
13740 +}
13741 +
13742 +static void __exit fini(void)
13743 +{
13744 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
13745 +       printk("ipt_IPV4OPTSSTRIP unloaded\n");
13746 +}
13747 +
13748 +module_init(init);
13749 +module_exit(fini);
13750 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_LOG.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_LOG.c
13751 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_LOG.c 2003-11-26 21:45:28.000000000 +0100
13752 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_LOG.c     2003-12-10 23:13:22.346678872 +0100
13753 @@ -4,12 +4,14 @@
13754  #include <linux/module.h>
13755  #include <linux/spinlock.h>
13756  #include <linux/skbuff.h>
13757 +#include <linux/socket.h>
13758  #include <linux/ip.h>
13759  #include <net/icmp.h>
13760  #include <net/udp.h>
13761  #include <net/tcp.h>
13762  #include <net/route.h>
13763  
13764 +#include <linux/netfilter.h>
13765  #include <linux/netfilter_ipv4/ip_tables.h>
13766  #include <linux/netfilter_ipv4/ipt_LOG.h>
13767  
13768 @@ -17,6 +19,10 @@
13769  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
13770  MODULE_DESCRIPTION("iptables syslog logging module");
13771  
13772 +static unsigned int nflog = 1;
13773 +MODULE_PARM(nflog, "i");
13774 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
13775 +
13776  #if 0
13777  #define DEBUGP printk
13778  #else
13779 @@ -315,28 +321,25 @@
13780         /* maxlen = 230+   91  + 230 + 252 = 803 */
13781  }
13782  
13783 -static unsigned int
13784 -ipt_log_target(struct sk_buff **pskb,
13785 +static void
13786 +ipt_log_packet(unsigned int hooknum,
13787 +              const struct sk_buff *skb,
13788                const struct net_device *in,
13789                const struct net_device *out,
13790 -              unsigned int hooknum,
13791 -              const void *targinfo,
13792 -              void *userinfo)
13793 +              const struct ipt_log_info *loginfo,
13794 +              const char *level_string,
13795 +              const char *prefix)
13796  {
13797 -       const struct ipt_log_info *loginfo = targinfo;
13798 -       char level_string[4] = "< >";
13799 -
13800 -       level_string[1] = '0' + (loginfo->level % 8);
13801         spin_lock_bh(&log_lock);
13802         printk(level_string);
13803         printk("%sIN=%s OUT=%s ",
13804 -              loginfo->prefix,
13805 +              prefix == NULL ? loginfo->prefix : prefix,
13806                in ? in->name : "",
13807                out ? out->name : "");
13808  #ifdef CONFIG_BRIDGE_NETFILTER
13809 -       if ((*pskb)->nf_bridge) {
13810 -               struct net_device *physindev = (*pskb)->nf_bridge->physindev;
13811 -               struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
13812 +       if (skb->nf_bridge) {
13813 +               struct net_device *physindev = skb->nf_bridge->physindev;
13814 +               struct net_device *physoutdev = skb->nf_bridge->physoutdev;
13815  
13816                 if (physindev && in != physindev)
13817                         printk("PHYSIN=%s ", physindev->name);
13818 @@ -348,25 +351,56 @@
13819         if (in && !out) {
13820                 /* MAC logging for input chain only. */
13821                 printk("MAC=");
13822 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len
13823 -                   && (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) {
13824 +               if (skb->dev && skb->dev->hard_header_len
13825 +                   && skb->mac.raw != (void*)skb->nh.iph) {
13826                         int i;
13827 -                       unsigned char *p = (*pskb)->mac.raw;
13828 -                       for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
13829 +                       unsigned char *p = skb->mac.raw;
13830 +                       for (i = 0; i < skb->dev->hard_header_len; i++,p++)
13831                                 printk("%02x%c", *p,
13832 -                                      i==(*pskb)->dev->hard_header_len - 1
13833 +                                      i==skb->dev->hard_header_len - 1
13834                                        ? ' ':':');
13835                 } else
13836                         printk(" ");
13837         }
13838  
13839 -       dump_packet(loginfo, *pskb, 0);
13840 +       dump_packet(loginfo, skb, 0);
13841         printk("\n");
13842         spin_unlock_bh(&log_lock);
13843 +}
13844 +
13845 +static unsigned int
13846 +ipt_log_target(struct sk_buff **pskb,
13847 +              const struct net_device *in,
13848 +              const struct net_device *out,
13849 +              unsigned int hooknum,
13850 +              const void *targinfo,
13851 +              void *userinfo)
13852 +{
13853 +       const struct ipt_log_info *loginfo = targinfo;
13854 +       char level_string[4] = "< >";
13855 +
13856 +       level_string[1] = '0' + (loginfo->level % 8);
13857 +       ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
13858  
13859         return IPT_CONTINUE;
13860  }
13861  
13862 +static void
13863 +ipt_logfn(unsigned int hooknum,
13864 +         const struct sk_buff *skb,
13865 +         const struct net_device *in,
13866 +         const struct net_device *out,
13867 +         const char *prefix)
13868 +{
13869 +       struct ipt_log_info loginfo = { 
13870 +               .level = 0, 
13871 +               .logflags = IPT_LOG_MASK, 
13872 +               .prefix = "" 
13873 +       };
13874 +
13875 +       ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
13876 +}
13877 +
13878  static int ipt_log_checkentry(const char *tablename,
13879                               const struct ipt_entry *e,
13880                               void *targinfo,
13881 @@ -406,12 +440,17 @@
13882  {
13883         if (ipt_register_target(&ipt_log_reg))
13884                 return -EINVAL;
13885 +       if (nflog)
13886 +               nf_log_register(PF_INET, &ipt_logfn);
13887  
13888         return 0;
13889  }
13890  
13891  static void __exit fini(void)
13892  {
13893 +       if (nflog)
13894 +               nf_log_unregister(PF_INET, &ipt_logfn);
13895 +
13896         ipt_unregister_target(&ipt_log_reg);
13897  }
13898  
13899 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mark.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_mark.c
13900 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mark.c        2003-11-26 21:46:13.000000000 +0100
13901 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mark.c    2003-12-10 23:14:21.807639432 +0100
13902 @@ -17,9 +17,15 @@
13903        int offset,
13904        int *hotdrop)
13905  {
13906 -       const struct ipt_mark_info *info = matchinfo;
13907 +       const struct ipt_mark_info *info = (struct ipt_mark_info *)matchinfo;
13908  
13909 -       return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13910 +       if (info->bit_op == IPT_MARK_BIT_OP_NONE)
13911 +               return (skb->nfmark == info->mark) ^ info->invert;
13912 +       else
13913 +               if (info->bit_op == IPT_MARK_BIT_OP_AND)
13914 +                       return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13915 +               else
13916 +                       return ((skb->nfmark | info->mask) == info->mark) ^ info->invert;
13917  }
13918  
13919  static int
13920 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_mport.c
13921 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mport.c       1970-01-01 01:00:00.000000000 +0100
13922 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mport.c   2003-12-10 23:13:34.441840128 +0100
13923 @@ -0,0 +1,112 @@
13924 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
13925 +   the same place so we can treat them as equal. */
13926 +#include <linux/module.h>
13927 +#include <linux/types.h>
13928 +#include <linux/udp.h>
13929 +#include <linux/skbuff.h>
13930 +
13931 +#include <linux/netfilter_ipv4/ipt_mport.h>
13932 +#include <linux/netfilter_ipv4/ip_tables.h>
13933 +
13934 +MODULE_LICENSE("GPL");
13935 +
13936 +#if 0
13937 +#define duprintf(format, args...) printk(format , ## args)
13938 +#else
13939 +#define duprintf(format, args...)
13940 +#endif
13941 +
13942 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
13943 +static inline int
13944 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
13945 +{
13946 +       unsigned int i;
13947 +        unsigned int m;
13948 +        u_int16_t pflags = minfo->pflags;
13949 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
13950 +                u_int16_t s, e;
13951 +
13952 +                if (pflags & m
13953 +                    && minfo->ports[i] == 65535)
13954 +                        return 0;
13955 +
13956 +                s = minfo->ports[i];
13957 +
13958 +                if (pflags & m) {
13959 +                        e = minfo->ports[++i];
13960 +                        m <<= 1;
13961 +                } else
13962 +                        e = s;
13963 +
13964 +                if (minfo->flags & IPT_MPORT_SOURCE
13965 +                    && src >= s && src <= e)
13966 +                        return 1;
13967 +
13968 +               if (minfo->flags & IPT_MPORT_DESTINATION
13969 +                   && dst >= s && dst <= e)
13970 +                       return 1;
13971 +       }
13972 +
13973 +       return 0;
13974 +}
13975 +
13976 +static int
13977 +match(const struct sk_buff *skb,
13978 +      const struct net_device *in,
13979 +      const struct net_device *out,
13980 +      const void *matchinfo,
13981 +      int offset,
13982 +      const void *hdr,
13983 +      u_int16_t datalen,
13984 +      int *hotdrop)
13985 +{
13986 +       const struct udphdr *udp = hdr;
13987 +       const struct ipt_mport *minfo = matchinfo;
13988 +
13989 +       /* Must be big enough to read ports. */
13990 +       if (offset == 0 && datalen < sizeof(struct udphdr)) {
13991 +               /* We've been asked to examine this packet, and we
13992 +                  can't.  Hence, no choice but to drop. */
13993 +                       duprintf("ipt_mport:"
13994 +                                " Dropping evil offset=0 tinygram.\n");
13995 +                       *hotdrop = 1;
13996 +                       return 0;
13997 +       }
13998 +
13999 +       /* Must not be a fragment. */
14000 +       return !offset
14001 +               && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
14002 +}
14003 +
14004 +/* Called when user tries to insert an entry of this type. */
14005 +static int
14006 +checkentry(const char *tablename,
14007 +          const struct ipt_ip *ip,
14008 +          void *matchinfo,
14009 +          unsigned int matchsize,
14010 +          unsigned int hook_mask)
14011 +{
14012 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
14013 +               return 0;
14014 +
14015 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
14016 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
14017 +               && !(ip->invflags & IPT_INV_PROTO)
14018 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
14019 +}
14020 +
14021 +static struct ipt_match mport_match
14022 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
14023 +
14024 +static int __init init(void)
14025 +{
14026 +       return ipt_register_match(&mport_match);
14027 +}
14028 +
14029 +static void __exit fini(void)
14030 +{
14031 +       ipt_unregister_match(&mport_match);
14032 +}
14033 +
14034 +module_init(init);
14035 +module_exit(fini);
14036 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_NETLINK.c
14037 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NETLINK.c     1970-01-01 01:00:00.000000000 +0100
14038 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_NETLINK.c 2003-12-10 23:13:35.507678096 +0100
14039 @@ -0,0 +1,119 @@
14040 +#include <linux/module.h>
14041 +#include <linux/version.h>
14042 +#include <linux/config.h>
14043 +#include <linux/socket.h>
14044 +#include <linux/skbuff.h>
14045 +#include <linux/kernel.h>
14046 +#include <linux/netlink.h>
14047 +#include <linux/netdevice.h>
14048 +#include <linux/mm.h>
14049 +#include <linux/socket.h>
14050 +#include <linux/netfilter_ipv4/ip_tables.h>
14051 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
14052 +#include <net/sock.h>
14053 +
14054 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
14055 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
14056 +MODULE_LICENSE("GPL");
14057 +
14058 +#if 0
14059 +#define DEBUGP printk
14060 +#else
14061 +#define DEBUGP(format, args...)
14062 +#endif
14063 +
14064 +static struct sock *ipfwsk;
14065 +
14066 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
14067 +                                   unsigned int hooknum,
14068 +                                   const struct net_device *in,
14069 +                                   const struct net_device *out,
14070 +                                   const void *targinfo, void *userinfo)
14071 +{
14072 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
14073 +       struct iphdr *ip = (*pskb)->nh.iph;
14074 +       struct sk_buff *outskb;
14075 +       struct netlink_t nlhdr;
14076 +       size_t len=0;
14077 +
14078 +       /* Allocate a socket buffer */
14079 +       if ( MASK(nld->flags, USE_SIZE) )
14080 +               len = nld->size+sizeof(nlhdr);
14081 +       else
14082 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
14083 +
14084 +       outskb=alloc_skb(len, GFP_ATOMIC);
14085 +
14086 +       if (outskb) {
14087 +               nlhdr.len=len;
14088 +               
14089 +               if ( MASK(nld->flags, USE_MARK) )
14090 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
14091 +               else
14092 +                       nlhdr.mark=(*pskb)->nfmark;
14093 +               
14094 +               if ( in && in->name ) {
14095 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
14096 +               }else if ( out && out->name ){
14097 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
14098 +               }
14099 +
14100 +               skb_put(outskb, len);
14101 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
14102 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
14103 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
14104 +       }else{
14105 +               if (net_ratelimit())
14106 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
14107 +       }
14108 +
14109 +       if ( MASK(nld->flags, USE_DROP) )
14110 +               return NF_DROP;
14111 +
14112 +       return IPT_CONTINUE;
14113 +}
14114 +
14115 +static int ipt_netlink_checkentry(const char *tablename,
14116 +                              const struct ipt_entry *e,
14117 +                              void *targinfo,
14118 +                              unsigned int targinfosize,
14119 +                              unsigned int hookmask)
14120 +{
14121 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
14122 +
14123 +       return 1;
14124 +}
14125 +
14126 +static struct ipt_target ipt_netlink_reg = { 
14127 +       {NULL, NULL},
14128 +       "NETLINK",
14129 +       ipt_netlink_target,
14130 +       ipt_netlink_checkentry,
14131 +       NULL,
14132 +       THIS_MODULE
14133 +};
14134 +
14135 +static int __init init(void)
14136 +{
14137 +       DEBUGP("ipt_NETLINK: init module\n");   
14138 +
14139 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
14140 +               return -EINVAL;
14141 +       }
14142 +
14143 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
14144 +               return -EINVAL;
14145 +       }
14146 +
14147 +       return 0;
14148 +}
14149 +
14150 +static void __exit fini(void)
14151 +{
14152 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
14153 +       ipt_unregister_target(&ipt_netlink_reg);
14154 +       if(ipfwsk->socket) sock_release(ipfwsk->socket);
14155 +}
14156 +
14157 +module_init(init);
14158 +module_exit(fini);
14159 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NOTRACK.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_NOTRACK.c
14160 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NOTRACK.c     1970-01-01 01:00:00.000000000 +0100
14161 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_NOTRACK.c 2003-12-10 23:13:24.663326688 +0100
14162 @@ -0,0 +1,79 @@
14163 +/* This is a module which is used for setting up fake conntracks
14164 + * on packets so that they are not seen by the conntrack/NAT code.
14165 + */
14166 +#include <linux/module.h>
14167 +#include <linux/skbuff.h>
14168 +
14169 +#include <linux/netfilter_ipv4/ip_tables.h>
14170 +#include <linux/netfilter_ipv4/ip_conntrack.h>
14171 +
14172 +static unsigned int
14173 +target(struct sk_buff **pskb,
14174 +       const struct net_device *in,
14175 +       const struct net_device *out,
14176 +       unsigned int hooknum,
14177 +       const void *targinfo,
14178 +       void *userinfo)
14179 +{
14180 +       /* Previously seen (loopback)? Ignore. */
14181 +       if ((*pskb)->nfct != NULL)
14182 +               return IPT_CONTINUE;
14183 +
14184 +       /* Attach fake conntrack entry. 
14185 +          If there is a real ct entry correspondig to this packet, 
14186 +          it'll hang aroun till timing out. We don't deal with it
14187 +          for performance reasons. JK */
14188 +       (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
14189 +       nf_conntrack_get((*pskb)->nfct);
14190 +
14191 +       return IPT_CONTINUE;
14192 +}
14193 +
14194 +static int
14195 +checkentry(const char *tablename,
14196 +          const struct ipt_entry *e,
14197 +           void *targinfo,
14198 +           unsigned int targinfosize,
14199 +           unsigned int hook_mask)
14200 +{
14201 +       if (targinfosize != 0) {
14202 +               printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
14203 +                      targinfosize);
14204 +               return 0;
14205 +       }
14206 +
14207 +       if (strcmp(tablename, "raw") != 0) {
14208 +               printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
14209 +               return 0;
14210 +       }
14211 +
14212 +       return 1;
14213 +}
14214 +
14215 +static struct ipt_target ipt_notrack_reg = { 
14216 +       .name           = "NOTRACK", 
14217 +       .target         = target, 
14218 +       .checkentry     = checkentry, 
14219 +       .destroy        = NULL, 
14220 +       .me             = THIS_MODULE,
14221 +};
14222 +
14223 +static int __init init(void)
14224 +{
14225 +       if (ipt_register_target(&ipt_notrack_reg))
14226 +               return -EINVAL;
14227 +
14228 +       return 0;
14229 +}
14230 +
14231 +static void __exit fini(void)
14232 +{
14233 +       ipt_unregister_target(&ipt_notrack_reg);
14234 +}
14235 +
14236 +module_init(init);
14237 +module_exit(fini);
14238 +
14239 +MODULE_LICENSE("GPL");
14240 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
14241 +MODULE_DESCRIPTION("IPv4 NOTRACK target");
14242 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_nth.c
14243 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
14244 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_nth.c     2003-12-10 23:13:37.748337464 +0100
14245 @@ -0,0 +1,172 @@
14246 +/*
14247 +  This is a module which is used for match support for every Nth packet
14248 +  This file is distributed under the terms of the GNU General Public
14249 +  License (GPL). Copies of the GPL can be obtained from:
14250 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
14251 +
14252 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14253 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
14254 +        * added support for multiple counters
14255 +        * added support for matching on individual packets
14256 +          in the counter cycle
14257 +
14258 +*/
14259 +
14260 +#include <linux/module.h>
14261 +#include <linux/skbuff.h>
14262 +#include <linux/ip.h>
14263 +#include <net/tcp.h>
14264 +#include <linux/spinlock.h>
14265 +#include <linux/netfilter_ipv4/ip_tables.h>
14266 +#include <linux/netfilter_ipv4/ipt_nth.h>
14267 +
14268 +MODULE_LICENSE("GPL");
14269 +
14270 +/*
14271 + * State information.
14272 + */
14273 +struct state {
14274 +       spinlock_t lock;
14275 +       u_int16_t number;
14276 +};
14277 +
14278 +static struct state states[IPT_NTH_NUM_COUNTERS];
14279 +
14280 +static int
14281 +ipt_nth_match(const struct sk_buff *pskb,
14282 +             const struct net_device *in,
14283 +             const struct net_device *out,
14284 +             const void *matchinfo,
14285 +             int offset,
14286 +             const void *hdr,
14287 +             u_int16_t datalen,
14288 +             int *hotdrop)
14289 +{
14290 +       /* Parameters from userspace */
14291 +       const struct ipt_nth_info *info = matchinfo;
14292 +        unsigned counter = info->counter;
14293 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
14294 +       {
14295 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14296 +               return 0;
14297 +        };
14298 +
14299 +        spin_lock(&states[counter].lock);
14300 +
14301 +        /* Are we matching every nth packet?*/
14302 +        if (info->packet == 0xFF)
14303 +        {
14304 +               /* We're matching every nth packet and only every nth packet*/
14305 +               /* Do we match or invert match? */
14306 +               if (info->not == 0)
14307 +               {
14308 +                       if (states[counter].number == 0)
14309 +                       {
14310 +                               ++states[counter].number;
14311 +                               goto match;
14312 +                       }
14313 +                       if (states[counter].number >= info->every)
14314 +                               states[counter].number = 0; /* reset the counter */
14315 +                       else
14316 +                               ++states[counter].number;
14317 +                       goto dontmatch;
14318 +               }
14319 +               else
14320 +               {
14321 +                       if (states[counter].number == 0)
14322 +                       {
14323 +                               ++states[counter].number;
14324 +                               goto dontmatch;
14325 +                       }
14326 +                       if (states[counter].number >= info->every)
14327 +                               states[counter].number = 0;
14328 +                       else
14329 +                               ++states[counter].number;
14330 +                       goto match;
14331 +               }
14332 +        }
14333 +        else
14334 +        {
14335 +               /* We're using the --packet, so there must be a rule for every value */
14336 +               if (states[counter].number == info->packet)
14337 +               {
14338 +                       /* only increment the counter when a match happens */
14339 +                       if (states[counter].number >= info->every)
14340 +                               states[counter].number = 0; /* reset the counter */
14341 +                       else
14342 +                               ++states[counter].number;
14343 +                       goto match;
14344 +               }
14345 +               else
14346 +                       goto dontmatch;
14347 +       }
14348 +
14349 + dontmatch:
14350 +       /* don't match */
14351 +       spin_unlock(&states[counter].lock);
14352 +       return 0;
14353 +
14354 + match:
14355 +       spin_unlock(&states[counter].lock);
14356 +       return 1;
14357 +}
14358 +
14359 +static int
14360 +ipt_nth_checkentry(const char *tablename,
14361 +                  const struct ipt_ip *e,
14362 +                  void *matchinfo,
14363 +                  unsigned int matchsize,
14364 +                  unsigned int hook_mask)
14365 +{
14366 +       /* Parameters from userspace */
14367 +       const struct ipt_nth_info *info = matchinfo;
14368 +        unsigned counter = info->counter;
14369 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
14370 +       {
14371 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14372 +                       return 0;
14373 +               };
14374 +
14375 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
14376 +               printk("nth: matchsize %u != %u\n", matchsize,
14377 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
14378 +               return 0;
14379 +       }
14380 +
14381 +       states[counter].number = info->startat;
14382 +
14383 +       return 1;
14384 +}
14385 +
14386 +static struct ipt_match ipt_nth_reg = { 
14387 +       {NULL, NULL},
14388 +       "nth",
14389 +       ipt_nth_match,
14390 +       ipt_nth_checkentry,
14391 +       NULL,
14392 +       THIS_MODULE };
14393 +
14394 +static int __init init(void)
14395 +{
14396 +       unsigned counter;
14397 +        memset(&states, 0, sizeof(states));
14398 +       if (ipt_register_match(&ipt_nth_reg))
14399 +               return -EINVAL;
14400 +
14401 +        for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
14402 +       {
14403 +               spin_lock_init(&(states[counter].lock));
14404 +        };
14405 +
14406 +       printk("ipt_nth match loaded\n");
14407 +       return 0;
14408 +}
14409 +
14410 +static void __exit fini(void)
14411 +{
14412 +       ipt_unregister_match(&ipt_nth_reg);
14413 +       printk("ipt_nth match unloaded\n");
14414 +}
14415 +
14416 +module_init(init);
14417 +module_exit(fini);
14418 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_osf.c
14419 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
14420 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_osf.c     2003-12-10 23:13:38.896162968 +0100
14421 @@ -0,0 +1,699 @@
14422 +/*
14423 + * ipt_osf.c
14424 + *
14425 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
14426 + *
14427 + *
14428 + * This program is free software; you can redistribute it and/or modify
14429 + * it under the terms of the GNU General Public License as published by
14430 + * the Free Software Foundation; either version 2 of the License, or
14431 + * (at your option) any later version.
14432 + *
14433 + * This program is distributed in the hope that it will be useful,
14434 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14435 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14436 + * GNU General Public License for more details.
14437 + *
14438 + * You should have received a copy of the GNU General Public License
14439 + * along with this program; if not, write to the Free Software
14440 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14441 + */
14442 +
14443 +/*
14444 + * OS fingerprint matching module.
14445 + * It simply compares various parameters from SYN packet with
14446 + * some hardcoded ones.
14447 + *
14448 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
14449 + * for his p0f.
14450 + */
14451 +
14452 +#include <linux/smp.h>
14453 +#include <linux/module.h>
14454 +#include <linux/skbuff.h>
14455 +#include <linux/file.h>
14456 +#include <linux/ip.h>
14457 +#include <linux/proc_fs.h>
14458 +#include <linux/fs.h>
14459 +#include <linux/slab.h>
14460 +#include <linux/spinlock.h>
14461 +#include <linux/ctype.h>
14462 +#include <linux/list.h>
14463 +
14464 +#include <net/sock.h>
14465 +#include <net/ip.h>
14466 +
14467 +#include <linux/netfilter_ipv4/ip_tables.h>
14468 +
14469 +#include <linux/netfilter_ipv4/ipt_osf.h>
14470 +
14471 +//#define OSF_DEBUG
14472 +
14473 +#ifdef OSF_DEBUG
14474 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
14475 +#define loga(x...)             printk(x)
14476 +#else
14477 +#define log(x...)              do {} while(0)
14478 +#define loga(x...)             do {} while(0)
14479 +#endif
14480 +
14481 +#define FMATCH_WRONG           0
14482 +#define FMATCH_OK              1
14483 +#define FMATCH_OPT_WRONG       2
14484 +
14485 +#define OPTDEL                 ','
14486 +#define OSFPDEL                ':'
14487 +#define MAXOPTSTRLEN           128
14488 +#define OSFFLUSH               "FLUSH"
14489 +
14490 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
14491 +static struct list_head        finger_list;    
14492 +
14493 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
14494 +                     const void *, int, const void *, u_int16_t, int *);
14495 +static int checkentry(const char *, const struct ipt_ip *, void *,
14496 +                          unsigned int, unsigned int);
14497 +
14498 +static struct ipt_match osf_match = 
14499 +{ 
14500 +       { NULL, NULL }, 
14501 +       "osf", 
14502 +       &match, 
14503 +       &checkentry, 
14504 +       NULL, 
14505 +       THIS_MODULE 
14506 +};
14507 +
14508 +static int
14509 +match(const struct sk_buff *skb,
14510 +      const struct net_device *in,
14511 +      const struct net_device *out,
14512 +      const void *matchinfo,
14513 +      int offset,
14514 +      const void *hdr,
14515 +      u_int16_t datalen,
14516 +      int *hotdrop)
14517 +{
14518 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
14519 +       struct iphdr *ip = skb->nh.iph;
14520 +       struct tcphdr *tcp;
14521 +       int fmatch = FMATCH_WRONG;
14522 +       unsigned long totlen, optsize = 0, window;
14523 +       unsigned char df, *optp = NULL, *_optp = NULL;
14524 +       char check_WSS = 0;
14525 +       struct list_head *ent;
14526 +       struct osf_finger *f;
14527 +
14528 +       if (!ip || !info)
14529 +               return 0;
14530 +                               
14531 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
14532 +
14533 +       if (!tcp->syn)
14534 +               return 0;
14535 +       
14536 +       totlen = ntohs(ip->tot_len);
14537 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
14538 +       window = ntohs(tcp->window);
14539 +       
14540 +       if (tcp->doff*4 > sizeof(struct tcphdr))
14541 +       {
14542 +               _optp = optp = (char *)(tcp+1);
14543 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
14544 +       }
14545 +
14546 +       
14547 +       /* Actually we can create hash/table of all genres and search
14548 +        * only in appropriate part, but here is initial variant,
14549 +        * so will use slow path.
14550 +        */
14551 +       read_lock(&osf_lock);
14552 +       list_for_each(ent, &finger_list)
14553 +       {
14554 +               f = list_entry(ent, struct osf_finger, flist);
14555 +               
14556 +               if (strcmp(info->genre, f->genre)) 
14557 +                       continue;
14558 +
14559 +               optp = _optp;
14560 +
14561 +               if (    ip->ttl == f->ttl &&
14562 +                       totlen  == f->ss &&
14563 +                       df      == f->df)
14564 +               {
14565 +                       unsigned long foptsize;
14566 +                       int optnum;
14567 +                       unsigned short mss = 0;
14568 +
14569 +                       check_WSS = 0;
14570 +
14571 +                       switch (f->wss.wc)
14572 +                       {
14573 +                               case 0:   check_WSS = 0; break;
14574 +                               case 'S': check_WSS = 1; break;
14575 +                               case 'T': check_WSS = 2; break;
14576 +                               case '%': check_WSS = 3; break;
14577 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
14578 +                                                        f->wss.wc, f->genre, f->details);
14579 +                                        check_WSS = 4;
14580 +                                        break;
14581 +                       }
14582 +                       if (check_WSS == 4)
14583 +                               continue;
14584 +
14585 +                       /* Check options */
14586 +
14587 +                       foptsize = 0;
14588 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
14589 +                               foptsize += f->opt[optnum].length;
14590 +
14591 +                               
14592 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
14593 +                               continue;
14594 +
14595 +                       if (!optp)
14596 +                       {
14597 +                               fmatch = FMATCH_OK;
14598 +                               loga("\tYEP : matching without options.\n");
14599 +                               break;
14600 +                       }
14601 +                       
14602 +
14603 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
14604 +                       {
14605 +                               if (f->opt[optnum].kind == (*optp))
14606 +                               {
14607 +                                       unsigned char len = f->opt[optnum].length;
14608 +                                       unsigned char *optend = optp + len;
14609 +
14610 +                                       fmatch = FMATCH_OK;
14611 +
14612 +                                       if (*optp == OSFOPT_MSS) /* MSS */
14613 +                                               mss = ntohs(*(unsigned short *)(optp+2));
14614 +                                       
14615 +                                       if (len != 1)
14616 +                                       {
14617 +                                               /* Skip kind and length fields*/
14618 +                                               optp += 2; 
14619 +
14620 +                                               if (f->opt[optnum].wc.wc != 0)
14621 +                                               {
14622 +                                                       unsigned long tmp = 0;
14623 +                                                       
14624 +                                                       /* Hmmm... It looks a bit ugly. :) */
14625 +                                                       memcpy(&tmp, &f->opt[optnum].wc.val, 
14626 +                                                               (len > sizeof(unsigned long)?
14627 +                                                                       sizeof(unsigned long):len));
14628 +
14629 +                                                       tmp = ntohl(tmp);
14630 +                                                       if (tmp != f->opt[optnum].wc.val)
14631 +                                                               fmatch = FMATCH_OPT_WRONG;
14632 +                                               }
14633 +                                       }
14634 +
14635 +                                       optp = optend;
14636 +                               }
14637 +                               else
14638 +                                       fmatch = FMATCH_OPT_WRONG;
14639 +
14640 +                               if (fmatch != FMATCH_OK)
14641 +                                       break;
14642 +                       }
14643 +
14644 +                       if (fmatch != FMATCH_OPT_WRONG)
14645 +                       {
14646 +                               fmatch = FMATCH_WRONG;
14647 +
14648 +                               switch (check_WSS)
14649 +                               {
14650 +                                       case 0:
14651 +                                               if (window == f->wss.val)
14652 +                                                       fmatch = FMATCH_OK;
14653 +                                               break;
14654 +                                       case 1: /* MSS */
14655 +                                               if (window == f->wss.val*mss)
14656 +                                                       fmatch = FMATCH_OK;
14657 +                                               break;
14658 +                                       case 2: /* MTU */
14659 +                                               if (window == f->wss.val*(mss+40))
14660 +                                                       fmatch = FMATCH_OK;
14661 +                                               break;
14662 +                                       case 3: /* MOD */
14663 +                                               if (window % f->wss.val == 0)
14664 +                                                       fmatch = FMATCH_OK;
14665 +                                               break;
14666 +                               }
14667 +                       }
14668 +                                       
14669 +
14670 +                       if (fmatch == FMATCH_OK)
14671 +                       {
14672 +
14673 +                               log("genre %s[%25s]: ttl=%d, size=%lu, df=%d, "
14674 +                                       "check_WSS=%d, win=%lu, optsize=%lu:\n", 
14675 +                                       f->genre, f->details, 
14676 +                                       ip->ttl, totlen, df, 
14677 +                                       check_WSS, window, optsize);
14678 +                               break;
14679 +                       }
14680 +               }
14681 +       }
14682 +       read_unlock(&osf_lock);
14683 +
14684 +       return (fmatch == FMATCH_OK)?1:0;
14685 +}
14686 +
14687 +static int
14688 +checkentry(const char *tablename,
14689 +           const struct ipt_ip *ip,
14690 +           void *matchinfo,
14691 +           unsigned int matchsize,
14692 +           unsigned int hook_mask)
14693 +{
14694 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
14695 +               return 0;
14696 +       if (ip->proto != IPPROTO_TCP)
14697 +              return 0;
14698 +
14699 +       return 1;
14700 +}
14701 +
14702 +static char * osf_strchr(char *ptr, char c)
14703 +{
14704 +       char *tmp;
14705 +
14706 +       tmp = strchr(ptr, c);
14707 +
14708 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
14709 +               tmp++;
14710 +
14711 +       return tmp;
14712 +}
14713 +
14714 +static struct osf_finger * finger_alloc()
14715 +{
14716 +       struct osf_finger *f;
14717 +
14718 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
14719 +       if (f)
14720 +               memset(f, 0, sizeof(struct osf_finger));
14721 +       
14722 +       return f;
14723 +}
14724 +
14725 +static void finger_free(struct osf_finger *f)
14726 +{
14727 +       memset(f, 0, sizeof(struct osf_finger));
14728 +       kfree(f);
14729 +}
14730 +
14731 +
14732 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
14733 +{
14734 +       int i, op;
14735 +       char *ptr, wc;
14736 +       unsigned long val;
14737 +
14738 +       ptr = &obuf[0];
14739 +       i = 0;
14740 +       while (ptr != NULL && i < olen)
14741 +       {
14742 +               val = 0;
14743 +               op = 0;
14744 +               wc = 0;
14745 +               switch (obuf[i])
14746 +               {
14747 +                       case 'N': 
14748 +                               op = OSFOPT_NOP;
14749 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14750 +                               if (ptr)
14751 +                               {
14752 +                                       *ptr = '\0';
14753 +                                       ptr++;
14754 +                                       i += (int)(ptr-&obuf[i]);
14755 +
14756 +                               }
14757 +                               else
14758 +                                       i++;
14759 +                               break;
14760 +                       case 'S': 
14761 +                               op = OSFOPT_SACKP;
14762 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14763 +                               if (ptr)
14764 +                               {
14765 +                                       *ptr = '\0';
14766 +                                       ptr++;
14767 +                                       i += (int)(ptr-&obuf[i]);
14768 +
14769 +                               }
14770 +                               else
14771 +                                       i++;
14772 +                               break;
14773 +                       case 'T': 
14774 +                               op = OSFOPT_TS;
14775 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14776 +                               if (ptr)
14777 +                               {
14778 +                                       *ptr = '\0';
14779 +                                       ptr++;
14780 +                                       i += (int)(ptr-&obuf[i]);
14781 +
14782 +                               }
14783 +                               else
14784 +                                       i++;
14785 +                               break;
14786 +                       case 'W': 
14787 +                               op = OSFOPT_WSO;
14788 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14789 +                               if (ptr)
14790 +                               {
14791 +                                       switch (obuf[i+1])
14792 +                                       {
14793 +                                               case '%':       wc = '%'; break;
14794 +                                               case 'S':       wc = 'S'; break;
14795 +                                               case 'T':       wc = 'T'; break;
14796 +                                               default:        wc = 0; break;
14797 +                                       }
14798 +                                       
14799 +                                       *ptr = '\0';
14800 +                                       ptr++;
14801 +                                       if (wc)
14802 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
14803 +                                       else
14804 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
14805 +                                       i += (int)(ptr-&obuf[i]);
14806 +
14807 +                               }
14808 +                               else
14809 +                                       i++;
14810 +                               break;
14811 +                       case 'M': 
14812 +                               op = OSFOPT_MSS;
14813 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14814 +                               if (ptr)
14815 +                               {
14816 +                                       if (obuf[i+1] == '%')
14817 +                                               wc = '%';
14818 +                                       *ptr = '\0';
14819 +                                       ptr++;
14820 +                                       if (wc)
14821 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
14822 +                                       else
14823 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
14824 +                                       i += (int)(ptr-&obuf[i]);
14825 +
14826 +                               }
14827 +                               else
14828 +                                       i++;
14829 +                               break;
14830 +                       case 'E': 
14831 +                               op = OSFOPT_EOL;
14832 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14833 +                               if (ptr)
14834 +                               {
14835 +                                       *ptr = '\0';
14836 +                                       ptr++;
14837 +                                       i += (int)(ptr-&obuf[i]);
14838 +
14839 +                               }
14840 +                               else
14841 +                                       i++;
14842 +                               break;
14843 +                       default:
14844 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14845 +                               if (ptr)
14846 +                               {
14847 +                                       ptr++;
14848 +                                       i += (int)(ptr-&obuf[i]);
14849 +
14850 +                               }
14851 +                               else
14852 +                                       i++;
14853 +                               break;
14854 +               }
14855 +
14856 +               opt[*optnum].kind       = IANA_opts[op].kind;
14857 +               opt[*optnum].length     = IANA_opts[op].length;
14858 +               opt[*optnum].wc.wc      = wc;
14859 +               opt[*optnum].wc.val     = val;
14860 +
14861 +               log("opt %2d: kind=%2d, length=%2d, wc.wc=%d, wc.val=%5lu\n",
14862 +                       *optnum, opt[*optnum].kind, opt[*optnum].length, 
14863 +                       opt[*optnum].wc.wc, opt[*optnum].wc.val);
14864 +               
14865 +               (*optnum)++;
14866 +       }
14867 +}
14868 +
14869 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
14870 +{
14871 +       struct list_head *ent;
14872 +       struct osf_finger *f = NULL;
14873 +       int i;
14874 +       
14875 +       *eof = 1;
14876 +       count = 0;
14877 +
14878 +       read_lock_bh(&osf_lock);
14879 +       list_for_each(ent, &finger_list)
14880 +       {
14881 +               f = list_entry(ent, struct osf_finger, flist);
14882 +
14883 +               log("%s - %s: ttl=%d, wss=%c%lu, df=%d, size=%lu",
14884 +                       f->genre, f->details, f->ttl, (f->wss.wc)?f->wss.wc:' ', f->wss.val, f->df, f->ss);
14885 +               
14886 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
14887 +                                       f->genre, f->version,
14888 +                                       f->subtype, f->details);
14889 +               
14890 +               if (f->opt_num)
14891 +               {
14892 +                       loga(" OPT: ");
14893 +                       //count += sprintf(buf+count, " OPT: ");
14894 +                       for (i=0; i<f->opt_num; ++i)
14895 +                       {
14896 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
14897 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14898 +                               loga("%d.%c%lu; ", 
14899 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14900 +                       }
14901 +               }
14902 +               loga("\n");
14903 +               count += sprintf(buf+count, "\n");
14904 +       }
14905 +       read_unlock_bh(&osf_lock);
14906 +
14907 +       return count;
14908 +}
14909 +
14910 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
14911 +{
14912 +       int cnt;
14913 +       unsigned long i;
14914 +       char obuf[MAXOPTSTRLEN];
14915 +       struct osf_finger *finger;
14916 +       struct list_head *ent, *n;
14917 +
14918 +       char *pbeg, *pend;
14919 +
14920 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
14921 +       {
14922 +               int i = 0;
14923 +               write_lock_bh(&osf_lock);
14924 +               list_for_each_safe(ent, n, &finger_list)
14925 +               {
14926 +                       i++;
14927 +                       finger = list_entry(ent, struct osf_finger, flist);
14928 +                       list_del(&finger->flist);
14929 +                       finger_free(finger);
14930 +               }
14931 +               write_unlock_bh(&osf_lock);
14932 +       
14933 +               log("Flushed %d entries.\n", i);
14934 +               
14935 +               return count;
14936 +       }
14937 +
14938 +       
14939 +       cnt = 0;
14940 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
14941 +               if (buffer[i] == ':')
14942 +                       cnt++;
14943 +
14944 +       if (cnt != 8 || i != count)
14945 +       {
14946 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
14947 +                       cnt, i, count);
14948 +               return count;
14949 +       }
14950 +
14951 +       memset(obuf, 0, sizeof(obuf));
14952 +       
14953 +       finger = finger_alloc();
14954 +       if (!finger)
14955 +       {
14956 +               log("Failed to allocate new fingerprint entry.\n");
14957 +               return -ENOMEM;
14958 +       }
14959 +
14960 +       pbeg = (char *)buffer;
14961 +       pend = osf_strchr(pbeg, OSFPDEL);
14962 +       if (pend)
14963 +       {
14964 +               *pend = '\0';
14965 +               if (pbeg[0] == 'S')
14966 +               {
14967 +                       finger->wss.wc = 'S';
14968 +                       if (pbeg[1] == '%')
14969 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14970 +                       else if (pbeg[1] == '*')
14971 +                               finger->wss.val = 0;
14972 +                       else 
14973 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14974 +               }
14975 +               else if (pbeg[0] == 'T')
14976 +               {
14977 +                       finger->wss.wc = 'T';
14978 +                       if (pbeg[1] == '%')
14979 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14980 +                       else if (pbeg[1] == '*')
14981 +                               finger->wss.val = 0;
14982 +                       else 
14983 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14984 +               }
14985 +               if (isdigit(pbeg[0]))
14986 +               {
14987 +                       finger->wss.wc = 0;
14988 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
14989 +               }
14990 +
14991 +               pbeg = pend+1;
14992 +       }
14993 +       pend = osf_strchr(pbeg, OSFPDEL);
14994 +       if (pend)
14995 +       {
14996 +               *pend = '\0';
14997 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
14998 +               pbeg = pend+1;
14999 +       }
15000 +       pend = osf_strchr(pbeg, OSFPDEL);
15001 +       if (pend)
15002 +       {
15003 +               *pend = '\0';
15004 +               finger->df = simple_strtoul(pbeg, NULL, 10);
15005 +               pbeg = pend+1;
15006 +       }
15007 +       pend = osf_strchr(pbeg, OSFPDEL);
15008 +       if (pend)
15009 +       {
15010 +               *pend = '\0';
15011 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
15012 +               pbeg = pend+1;
15013 +       }
15014 +
15015 +       pend = osf_strchr(pbeg, OSFPDEL);
15016 +       if (pend)
15017 +       {
15018 +               *pend = '\0';
15019 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
15020 +               pbeg = pend+1;
15021 +       }
15022 +
15023 +       pend = osf_strchr(pbeg, OSFPDEL);
15024 +       if (pend)
15025 +       {
15026 +               *pend = '\0';
15027 +               if (pbeg[0] == '@' || pbeg[0] == '*')
15028 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
15029 +               else
15030 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
15031 +               pbeg = pend+1;
15032 +       }
15033 +       
15034 +       pend = osf_strchr(pbeg, OSFPDEL);
15035 +       if (pend)
15036 +       {
15037 +               *pend = '\0';
15038 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
15039 +               pbeg = pend+1;
15040 +       }
15041 +       
15042 +       pend = osf_strchr(pbeg, OSFPDEL);
15043 +       if (pend)
15044 +       {
15045 +               *pend = '\0';
15046 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
15047 +               pbeg = pend+1;
15048 +       }
15049 +
15050 +       cnt = snprintf(finger->details, 
15051 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
15052 +                       "%s", pbeg);
15053 +       
15054 +       log("%s - %s[%s] : %s\n", 
15055 +               finger->genre, finger->version,
15056 +               finger->subtype, finger->details);
15057 +       
15058 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
15059 +       
15060 +
15061 +       write_lock_bh(&osf_lock);
15062 +       list_add(&finger->flist, &finger_list);
15063 +       write_unlock_bh(&osf_lock);
15064 +
15065 +       return count;
15066 +}
15067 +
15068 +static int __init osf_init(void)
15069 +{
15070 +       int err;
15071 +       struct proc_dir_entry *p;
15072 +
15073 +       log("Startng OS fingerprint matching module.\n");
15074 +
15075 +       INIT_LIST_HEAD(&finger_list);
15076 +       
15077 +       err = ipt_register_match(&osf_match);
15078 +       if (err)
15079 +       {
15080 +               log("Failed to register OS fingerprint matching module.\n");
15081 +               return -ENXIO;
15082 +       }
15083 +
15084 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
15085 +       if (!p)
15086 +       {
15087 +               ipt_unregister_match(&osf_match);
15088 +               return -ENXIO;
15089 +       }
15090 +
15091 +       p->write_proc = osf_proc_write;
15092 +       p->read_proc  = osf_proc_read;
15093 +
15094 +       return 0;
15095 +}
15096 +
15097 +static void __exit osf_fini(void)
15098 +{
15099 +       struct list_head *ent, *n;
15100 +       struct osf_finger *f;
15101 +       
15102 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
15103 +       ipt_unregister_match(&osf_match);
15104 +
15105 +       list_for_each_safe(ent, n, &finger_list)
15106 +       {
15107 +               f = list_entry(ent, struct osf_finger, flist);
15108 +               list_del(&f->flist);
15109 +               finger_free(f);
15110 +       }
15111 +       
15112 +       log("OS fingerprint matching module finished.\n");
15113 +}
15114 +
15115 +module_init(osf_init);
15116 +module_exit(osf_fini);
15117 +
15118 +MODULE_LICENSE("GPL");
15119 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
15120 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
15121 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_pool.c
15122 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_pool.c        1970-01-01 01:00:00.000000000 +0100
15123 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_pool.c    2003-12-10 23:13:39.982997744 +0100
15124 @@ -0,0 +1,71 @@
15125 +/* Kernel module to match an IP address pool. */
15126 +
15127 +#include <linux/module.h>
15128 +#include <linux/ip.h>
15129 +#include <linux/skbuff.h>
15130 +
15131 +#include <linux/netfilter_ipv4/ip_tables.h>
15132 +#include <linux/netfilter_ipv4/ip_pool.h>
15133 +#include <linux/netfilter_ipv4/ipt_pool.h>
15134 +
15135 +static inline int match_pool(
15136 +       ip_pool_t index,
15137 +       __u32 addr,
15138 +       int inv
15139 +) {
15140 +       if (ip_pool_match(index, ntohl(addr)))
15141 +               inv = !inv;
15142 +       return inv;
15143 +}
15144 +
15145 +static int match(
15146 +       const struct sk_buff *skb,
15147 +       const struct net_device *in,
15148 +       const struct net_device *out,
15149 +       const void *matchinfo,
15150 +       int offset,
15151 +       const void *hdr,
15152 +       u_int16_t datalen,
15153 +       int *hotdrop
15154 +) {
15155 +       const struct ipt_pool_info *info = matchinfo;
15156 +       const struct iphdr *iph = skb->nh.iph;
15157 +
15158 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
15159 +                                               info->flags&IPT_POOL_INV_SRC))
15160 +               return 0;
15161 +
15162 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
15163 +                                               info->flags&IPT_POOL_INV_DST))
15164 +               return 0;
15165 +
15166 +       return 1;
15167 +}
15168 +
15169 +static int checkentry(
15170 +       const char *tablename,
15171 +       const struct ipt_ip *ip,
15172 +       void *matchinfo,
15173 +       unsigned int matchsize,
15174 +       unsigned int hook_mask
15175 +) {
15176 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
15177 +               return 0;
15178 +       return 1;
15179 +}
15180 +
15181 +static struct ipt_match pool_match
15182 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
15183 +
15184 +static int __init init(void)
15185 +{
15186 +       return ipt_register_match(&pool_match);
15187 +}
15188 +
15189 +static void __exit fini(void)
15190 +{
15191 +       ipt_unregister_match(&pool_match);
15192 +}
15193 +
15194 +module_init(init);
15195 +module_exit(fini);
15196 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_POOL.c
15197 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_POOL.c        1970-01-01 01:00:00.000000000 +0100
15198 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_POOL.c    2003-12-10 23:13:39.982997744 +0100
15199 @@ -0,0 +1,116 @@
15200 +/* ipt_POOL.c - netfilter target to manipulate IP pools
15201 + *
15202 + * This target can be used almost everywhere. It acts on some specified
15203 + * IP pool, adding or deleting some IP address in the pool. The address
15204 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
15205 + * of the packet under inspection.
15206 + *
15207 + * The target normally returns IPT_CONTINUE.
15208 + */
15209 +
15210 +#include <linux/types.h>
15211 +#include <linux/ip.h>
15212 +#include <linux/timer.h>
15213 +#include <linux/module.h>
15214 +#include <linux/netfilter.h>
15215 +#include <linux/netdevice.h>
15216 +#include <linux/if.h>
15217 +#include <linux/inetdevice.h>
15218 +#include <net/protocol.h>
15219 +#include <net/checksum.h>
15220 +#include <linux/netfilter_ipv4.h>
15221 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
15222 +#include <linux/netfilter_ipv4/ipt_pool.h>
15223 +
15224 +#if 0
15225 +#define DEBUGP printk
15226 +#else
15227 +#define DEBUGP(format, args...)
15228 +#endif
15229 +
15230 +/*** NOTE NOTE NOTE NOTE ***
15231 +**
15232 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
15233 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
15234 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
15235 +** is modified for the source IP address of the packet under inspection.
15236 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
15237 +**
15238 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
15239 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
15240 +**
15241 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
15242 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
15243 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
15244 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
15245 +*/
15246 +
15247 +static int
15248 +do_check(const char *tablename,
15249 +              const struct ipt_entry *e,
15250 +              void *targinfo,
15251 +              unsigned int targinfosize,
15252 +              unsigned int hook_mask)
15253 +{
15254 +       const struct ipt_pool_info *ipi = targinfo;
15255 +
15256 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
15257 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
15258 +               return 0;
15259 +       }
15260 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
15261 +       return 1;
15262 +}
15263 +
15264 +static unsigned int
15265 +do_target(struct sk_buff **pskb,
15266 +               unsigned int hooknum,
15267 +               const struct net_device *in,
15268 +               const struct net_device *out,
15269 +               const void *targinfo,
15270 +               void *userinfo)
15271 +{
15272 +       const struct ipt_pool_info *ipi = targinfo;
15273 +       int modified;
15274 +       unsigned int verdict = IPT_CONTINUE;
15275 +
15276 +       if (ipi->src != IP_POOL_NONE) {
15277 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
15278 +                                       ipi->flags & IPT_POOL_DEL_SRC);
15279 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
15280 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
15281 +                               verdict = NF_ACCEPT;
15282 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
15283 +                               verdict = NF_DROP;
15284 +               }
15285 +       }
15286 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
15287 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
15288 +                                       ipi->flags & IPT_POOL_DEL_DST);
15289 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
15290 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
15291 +                               verdict = NF_ACCEPT;
15292 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
15293 +                               verdict = NF_DROP;
15294 +               }
15295 +       }
15296 +       return verdict;
15297 +}
15298 +
15299 +static struct ipt_target pool_reg
15300 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
15301 +
15302 +static int __init init(void)
15303 +{
15304 +       DEBUGP("init ipt_POOL\n");
15305 +       return ipt_register_target(&pool_reg);
15306 +}
15307 +
15308 +static void __exit fini(void)
15309 +{
15310 +       DEBUGP("fini ipt_POOL\n");
15311 +       ipt_unregister_target(&pool_reg);
15312 +}
15313 +
15314 +module_init(init);
15315 +module_exit(fini);
15316 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_psd.c
15317 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
15318 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_psd.c     2003-12-10 23:13:41.104827200 +0100
15319 @@ -0,0 +1,361 @@
15320 +/*
15321 +  This is a module which is used for PSD (portscan detection)
15322 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
15323 +  and LOG target module.
15324 +
15325 +  Copyright (C) 2000,2001 astaro AG
15326 +
15327 +  This file is distributed under the terms of the GNU General Public
15328 +  License (GPL). Copies of the GPL can be obtained from:
15329 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
15330 +
15331 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
15332 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
15333 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
15334 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
15335 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
15336 +*/
15337 +
15338 +#include <linux/module.h>
15339 +#include <linux/skbuff.h>
15340 +#include <linux/ip.h>
15341 +#include <net/tcp.h>
15342 +#include <linux/spinlock.h>
15343 +#include <linux/netfilter_ipv4/ip_tables.h>
15344 +#include <linux/netfilter_ipv4/ipt_psd.h>
15345 +
15346 +#if 0
15347 +#define DEBUGP printk
15348 +#else
15349 +#define DEBUGP(format, args...)
15350 +#endif
15351 +
15352 +MODULE_LICENSE("GPL");
15353 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
15354 +
15355 +#define HF_DADDR_CHANGING   0x01
15356 +#define HF_SPORT_CHANGING   0x02
15357 +#define HF_TOS_CHANGING            0x04
15358 +#define HF_TTL_CHANGING            0x08
15359 +            
15360 +/*
15361 + * Information we keep per each target port
15362 + */
15363 +struct port {
15364 +       u_int16_t number;      /* port number */ 
15365 +       u_int8_t proto;        /* protocol number */
15366 +       u_int8_t and_flags;    /* tcp ANDed flags */
15367 +       u_int8_t or_flags;     /* tcp ORed flags */
15368 +};
15369 +
15370 +/*
15371 + * Information we keep per each source address.
15372 + */
15373 +struct host {
15374 +       struct host *next;              /* Next entry with the same hash */
15375 +       clock_t timestamp;              /* Last update time */
15376 +       struct in_addr src_addr;        /* Source address */
15377 +       struct in_addr dest_addr;       /* Destination address */
15378 +       unsigned short src_port;        /* Source port */
15379 +       int count;                      /* Number of ports in the list */
15380 +       int weight;                     /* Total weight of ports in the list */
15381 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
15382 +       unsigned char tos;              /* TOS */
15383 +       unsigned char ttl;              /* TTL */
15384 +       unsigned char flags;            /* HF_ flags bitmask */
15385 +};
15386 +
15387 +/*
15388 + * State information.
15389 + */
15390 +static struct {
15391 +       spinlock_t lock;
15392 +       struct host list[LIST_SIZE];    /* List of source addresses */
15393 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
15394 +       int index;                      /* Oldest entry to be replaced */
15395 +} state;
15396 +
15397 +/*
15398 + * Convert an IP address into a hash table index.
15399 + */
15400 +static inline int hashfunc(struct in_addr addr)
15401 +{
15402 +       unsigned int value;
15403 +       int hash;
15404 +
15405 +       value = addr.s_addr;
15406 +       hash = 0;
15407 +       do {
15408 +               hash ^= value;
15409 +       } while ((value >>= HASH_LOG));
15410 +
15411 +       return hash & (HASH_SIZE - 1);
15412 +}
15413 +
15414 +static int
15415 +ipt_psd_match(const struct sk_buff *pskb,
15416 +             const struct net_device *in,
15417 +             const struct net_device *out,
15418 +             const void *matchinfo,
15419 +             int offset,
15420 +             const void *hdr,
15421 +             u_int16_t datalen,
15422 +             int *hotdrop)
15423 +{
15424 +       struct iphdr *ip_hdr;
15425 +       struct tcphdr *tcp_hdr;
15426 +       struct in_addr addr;
15427 +       u_int16_t src_port,dest_port;
15428 +       u_int8_t tcp_flags, proto;
15429 +       clock_t now;
15430 +       struct host *curr, *last, **head;
15431 +       int hash, index, count;
15432 +
15433 +       /* Parameters from userspace */
15434 +       const struct ipt_psd_info *psdinfo = matchinfo;
15435 +
15436 +       /* IP header */
15437 +       ip_hdr = pskb->nh.iph;
15438 +
15439 +       /* Sanity check */
15440 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
15441 +               DEBUGP("PSD: sanity check failed\n");
15442 +               return 0;
15443 +       }
15444 +
15445 +       /* TCP or UDP ? */
15446 +       proto = ip_hdr->protocol;
15447 +
15448 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
15449 +               DEBUGP("PSD: protocol not supported\n");
15450 +               return 0;
15451 +       }
15452 +
15453 +       /* Get the source address, source & destination ports, and TCP flags */
15454 +
15455 +       addr.s_addr = ip_hdr->saddr;
15456 +
15457 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
15458 +
15459 +       /* Yep, itĀ“s dirty */
15460 +       src_port = tcp_hdr->source;
15461 +       dest_port = tcp_hdr->dest;
15462 +
15463 +       if (proto == IPPROTO_TCP) {
15464 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
15465 +       }
15466 +       else {
15467 +               tcp_flags = 0x00;
15468 +       }
15469 +
15470 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
15471 +        * them spoof us. [DHCP needs this feature - HW] */
15472 +       if (!addr.s_addr) {
15473 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
15474 +               return 0;
15475 +       }
15476 +
15477 +       /* Use jiffies here not to depend on someone setting the time while we're
15478 +        * running; we need to be careful with possible return value overflows. */
15479 +       now = jiffies;
15480 +
15481 +       spin_lock(&state.lock);
15482 +
15483 +       /* Do we know this source address already? */
15484 +       count = 0;
15485 +       last = NULL;
15486 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
15487 +               do {
15488 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
15489 +                       count++;
15490 +                       if (curr->next) last = curr;
15491 +               } while ((curr = curr->next));
15492 +
15493 +       if (curr) {
15494 +
15495 +               /* We know this address, and the entry isn't too old. Update it. */
15496 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
15497 +                   time_after_eq(now, curr->timestamp)) {
15498 +
15499 +                       /* Just update the appropriate list entry if we've seen this port already */
15500 +                       for (index = 0; index < curr->count; index++) {
15501 +                               if (curr->ports[index].number == dest_port) {
15502 +                                       curr->ports[index].proto = proto;
15503 +                                       curr->ports[index].and_flags &= tcp_flags;
15504 +                                       curr->ports[index].or_flags |= tcp_flags;
15505 +                                       goto out_no_match;
15506 +                               }
15507 +                       }
15508 +
15509 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
15510 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
15511 +                               goto out_no_match;
15512 +
15513 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
15514 +                       curr->timestamp = now;
15515 +
15516 +                       /* Logged this scan already? Then drop the packet. */
15517 +                       if (curr->weight >= psdinfo->weight_threshold)
15518 +                               goto out_match;
15519 +
15520 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
15521 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
15522 +                               curr->flags |= HF_DADDR_CHANGING;
15523 +                       if (curr->src_port != src_port)
15524 +                               curr->flags |= HF_SPORT_CHANGING;
15525 +                       if (curr->tos != ip_hdr->tos)
15526 +                               curr->flags |= HF_TOS_CHANGING;
15527 +                       if (curr->ttl != ip_hdr->ttl)
15528 +                               curr->flags |= HF_TTL_CHANGING;
15529 +
15530 +                       /* Update the total weight */
15531 +                       curr->weight += (ntohs(dest_port) < 1024) ?
15532 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15533 +
15534 +                       /* Got enough destination ports to decide that this is a scan? */
15535 +                       /* Then log it and drop the packet. */
15536 +                       if (curr->weight >= psdinfo->weight_threshold)
15537 +                               goto out_match;
15538 +
15539 +                       /* Remember the new port */
15540 +                       if (curr->count < SCAN_MAX_COUNT) {
15541 +                               curr->ports[curr->count].number = dest_port;
15542 +                               curr->ports[curr->count].proto = proto;
15543 +                               curr->ports[curr->count].and_flags = tcp_flags;
15544 +                               curr->ports[curr->count].or_flags = tcp_flags;
15545 +                               curr->count++;
15546 +                       }
15547 +
15548 +                       goto out_no_match;
15549 +               }
15550 +
15551 +               /* We know this address, but the entry is outdated. Mark it unused, and
15552 +                * remove from the hash table. We'll allocate a new entry instead since
15553 +                * this one might get re-used too soon. */
15554 +               curr->src_addr.s_addr = 0;
15555 +               if (last)
15556 +                       last->next = last->next->next;
15557 +               else if (*head)
15558 +                       *head = (*head)->next;
15559 +               last = NULL;
15560 +       }
15561 +
15562 +       /* We don't need an ACK from a new source address */
15563 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
15564 +               goto out_no_match;
15565 +
15566 +       /* Got too many source addresses with the same hash value? Then remove the
15567 +        * oldest one from the hash table, so that they can't take too much of our
15568 +        * CPU time even with carefully chosen spoofed IP addresses. */
15569 +       if (count >= HASH_MAX && last) last->next = NULL;
15570 +
15571 +       /* We're going to re-use the oldest list entry, so remove it from the hash
15572 +        * table first (if it is really already in use, and isn't removed from the
15573 +        * hash table already because of the HASH_MAX check above). */
15574 +
15575 +       /* First, find it */
15576 +       if (state.list[state.index].src_addr.s_addr)
15577 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
15578 +       else
15579 +               head = &last;
15580 +       last = NULL;
15581 +       if ((curr = *head))
15582 +       do {
15583 +               if (curr == &state.list[state.index]) break;
15584 +               last = curr;
15585 +       } while ((curr = curr->next));
15586 +
15587 +       /* Then, remove it */
15588 +       if (curr) {
15589 +               if (last)
15590 +                       last->next = last->next->next;
15591 +               else if (*head)
15592 +                       *head = (*head)->next;
15593 +       }
15594 +
15595 +       /* Get our list entry */
15596 +       curr = &state.list[state.index++];
15597 +       if (state.index >= LIST_SIZE) state.index = 0;
15598 +
15599 +       /* Link it into the hash table */
15600 +       head = &state.hash[hash];
15601 +       curr->next = *head;
15602 +       *head = curr;
15603 +
15604 +       /* And fill in the fields */
15605 +       curr->timestamp = now;
15606 +       curr->src_addr = addr;
15607 +       curr->dest_addr.s_addr = ip_hdr->daddr;
15608 +       curr->src_port = src_port;
15609 +       curr->count = 1;
15610 +       curr->weight = (ntohs(dest_port) < 1024) ?
15611 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15612 +       curr->ports[0].number = dest_port;
15613 +       curr->ports[0].proto = proto;
15614 +       curr->ports[0].and_flags = tcp_flags;
15615 +       curr->ports[0].or_flags = tcp_flags;
15616 +       curr->tos = ip_hdr->tos;
15617 +       curr->ttl = ip_hdr->ttl;
15618 +
15619 +out_no_match:
15620 +       spin_unlock(&state.lock);
15621 +       return 0;
15622 +
15623 +out_match:
15624 +       spin_unlock(&state.lock);
15625 +       return 1;
15626 +}
15627 +
15628 +static int ipt_psd_checkentry(const char *tablename,
15629 +                             const struct ipt_ip *e,
15630 +                             void *matchinfo,
15631 +                             unsigned int matchsize,
15632 +                             unsigned int hook_mask)
15633 +{
15634 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
15635 +
15636 +       /* we accept TCP only */
15637 +/*     if (e->ip.proto != IPPROTO_TCP) { */
15638 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
15639 +/*             return 0; */
15640 +/*     } */
15641 +
15642 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
15643 +               DEBUGP("PSD: matchsize %u != %u\n",
15644 +                      matchsize,
15645 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
15646 +               return 0;
15647 +       }
15648 +
15649 +       return 1;
15650 +}
15651 +
15652 +static struct ipt_match ipt_psd_reg = { 
15653 +       {NULL, NULL},
15654 +       "psd",
15655 +       ipt_psd_match,
15656 +       ipt_psd_checkentry,
15657 +       NULL,
15658 +       THIS_MODULE };
15659 +
15660 +static int __init init(void)
15661 +{
15662 +       if (ipt_register_match(&ipt_psd_reg))
15663 +               return -EINVAL;
15664 +
15665 +       memset(&state, 0, sizeof(state));
15666 +
15667 +       spin_lock_init(&(state.lock));
15668 +
15669 +       printk("netfilter PSD loaded - (c) astaro AG\n");
15670 +       return 0;
15671 +}
15672 +
15673 +static void __exit fini(void)
15674 +{
15675 +       ipt_unregister_match(&ipt_psd_reg);
15676 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
15677 +}
15678 +
15679 +module_init(init);
15680 +module_exit(fini);
15681 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_quota.c
15682 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_quota.c       1970-01-01 01:00:00.000000000 +0100
15683 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_quota.c   2003-12-10 23:13:42.204660000 +0100
15684 @@ -0,0 +1,81 @@
15685 +/* 
15686 + * netfilter module to enforce network quotas
15687 + *
15688 + * Sam Johnston <samj@samj.net>
15689 + */
15690 +#include <linux/module.h>
15691 +#include <linux/skbuff.h>
15692 +#include <linux/spinlock.h>
15693 +#include <linux/interrupt.h>
15694 +
15695 +#include <linux/netfilter_ipv4/ip_tables.h>
15696 +#include <linux/netfilter_ipv4/ipt_quota.h>
15697 +
15698 +MODULE_LICENSE("GPL");
15699 +
15700 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
15701 +
15702 +static int
15703 +match(const struct sk_buff *skb,
15704 +      const struct net_device *in,
15705 +      const struct net_device *out,
15706 +      const void *matchinfo,
15707 +      int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
15708 +{
15709 +
15710 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
15711 +
15712 +        spin_lock_bh(&quota_lock);
15713 +
15714 +        if (q->quota >= datalen) {
15715 +                /* we can afford this one */
15716 +                q->quota -= datalen;
15717 +                spin_unlock_bh(&quota_lock);
15718 +
15719 +#ifdef DEBUG_IPT_QUOTA
15720 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
15721 +#endif
15722 +                return 1;
15723 +        }
15724 +
15725 +        /* so we do not allow even small packets from now on */
15726 +        q->quota = 0;
15727 +
15728 +#ifdef DEBUG_IPT_QUOTA
15729 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
15730 +#endif
15731 +
15732 +        spin_unlock_bh(&quota_lock);
15733 +        return 0;
15734 +}
15735 +
15736 +static int
15737 +checkentry(const char *tablename,
15738 +           const struct ipt_ip *ip,
15739 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
15740 +{
15741 +        /* TODO: spinlocks? sanity checks? */
15742 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
15743 +                return 0;
15744 +
15745 +        return 1;
15746 +}
15747 +
15748 +static struct ipt_match quota_match
15749 +    = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
15750 +
15751 +static int __init
15752 +init(void)
15753 +{
15754 +        return ipt_register_match(&quota_match);
15755 +}
15756 +
15757 +static void __exit
15758 +fini(void)
15759 +{
15760 +        ipt_unregister_match(&quota_match);
15761 +}
15762 +
15763 +module_init(init);
15764 +module_exit(fini);
15765 +
15766 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_random.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_random.c
15767 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_random.c      1970-01-01 01:00:00.000000000 +0100
15768 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_random.c  2003-12-10 23:13:44.404325600 +0100
15769 @@ -0,0 +1,96 @@
15770 +/*
15771 +  This is a module which is used for a "random" match support.
15772 +  This file is distributed under the terms of the GNU General Public
15773 +  License (GPL). Copies of the GPL can be obtained from:
15774 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
15775 +
15776 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
15777 +*/
15778 +
15779 +#include <linux/module.h>
15780 +#include <linux/skbuff.h>
15781 +#include <linux/ip.h>
15782 +#include <linux/random.h>
15783 +#include <net/tcp.h>
15784 +#include <linux/spinlock.h>
15785 +#include <linux/netfilter_ipv4/ip_tables.h>
15786 +#include <linux/netfilter_ipv4/ipt_random.h>
15787 +
15788 +MODULE_LICENSE("GPL");
15789 +
15790 +static int
15791 +ipt_rand_match(const struct sk_buff *pskb,
15792 +              const struct net_device *in,
15793 +              const struct net_device *out,
15794 +              const void *matchinfo,
15795 +              int offset,
15796 +              const void *hdr,
15797 +              u_int16_t datalen,
15798 +              int *hotdrop)
15799 +{
15800 +       /* Parameters from userspace */
15801 +       const struct ipt_rand_info *info = matchinfo;
15802 +       u_int8_t random_number;
15803 +
15804 +       /* get 1 random number from the kernel random number generation routine */
15805 +       get_random_bytes((void *)(&random_number), 1);
15806 +
15807 +       /* Do we match ? */
15808 +       if (random_number <= info->average)
15809 +               return 1;
15810 +       else
15811 +               return 0;
15812 +}
15813 +
15814 +static int
15815 +ipt_rand_checkentry(const char *tablename,
15816 +                  const struct ipt_ip *e,
15817 +                  void *matchinfo,
15818 +                  unsigned int matchsize,
15819 +                  unsigned int hook_mask)
15820 +{
15821 +       /* Parameters from userspace */
15822 +       const struct ipt_rand_info *info = matchinfo;
15823 +
15824 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
15825 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
15826 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
15827 +               return 0;
15828 +       }
15829 +
15830 +       /* must be  1 <= average % <= 99 */
15831 +       /* 1  x 2.55 = 2   */
15832 +       /* 99 x 2.55 = 252 */
15833 +       if ((info->average < 2) || (info->average > 252)) {
15834 +               printk("ipt_random:  invalid average %u\n", info->average);
15835 +               return 0;
15836 +       }
15837 +
15838 +       return 1;
15839 +}
15840 +
15841 +static struct ipt_match ipt_rand_reg = { 
15842 +       {NULL, NULL},
15843 +       "random",
15844 +       ipt_rand_match,
15845 +       ipt_rand_checkentry,
15846 +       NULL,
15847 +       THIS_MODULE };
15848 +
15849 +static int __init init(void)
15850 +{
15851 +       if (ipt_register_match(&ipt_rand_reg))
15852 +               return -EINVAL;
15853 +
15854 +       printk("ipt_random match loaded\n");
15855 +       return 0;
15856 +}
15857 +
15858 +static void __exit fini(void)
15859 +{
15860 +       ipt_unregister_match(&ipt_rand_reg);
15861 +       printk("ipt_random match unloaded\n");
15862 +}
15863 +
15864 +module_init(init);
15865 +module_exit(fini);
15866 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_realm.c
15867 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_realm.c       1970-01-01 01:00:00.000000000 +0100
15868 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_realm.c   2003-12-10 23:13:45.528154752 +0100
15869 @@ -0,0 +1,68 @@
15870 +/* Kernel module to match realm from routing. */
15871 +#include <linux/module.h>
15872 +#include <linux/skbuff.h>
15873 +#include <linux/netdevice.h>
15874 +#include <net/route.h>
15875 +
15876 +#include <linux/netfilter_ipv4/ipt_realm.h>
15877 +#include <linux/netfilter_ipv4/ip_tables.h>
15878 +
15879 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
15880 +MODULE_LICENSE("GPL");
15881 +
15882 +static int
15883 +match(const struct sk_buff *skb,
15884 +      const struct net_device *in,
15885 +      const struct net_device *out,
15886 +      const void *matchinfo,
15887 +      int offset,
15888 +      const void *hdr,
15889 +      u_int16_t datalen,
15890 +      int *hotdrop)
15891 +{
15892 +       const struct ipt_realm_info *info = matchinfo;
15893 +       struct dst_entry *dst = skb->dst;
15894 +       u32 id;
15895 +    
15896 +       if(dst == NULL)
15897 +               return 0;
15898 +       id = dst->tclassid;
15899 +
15900 +       return (info->id == (id & info->mask)) ^ info->invert;
15901 +}
15902 +
15903 +static int check(const char *tablename,
15904 +                 const struct ipt_ip *ip,
15905 +                 void *matchinfo,
15906 +                 unsigned int matchsize,
15907 +                 unsigned int hook_mask)
15908 +{
15909 +       if (hook_mask
15910 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
15911 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
15912 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
15913 +                      "LOCAL_IN or FORWARD.\n");
15914 +               return 0;
15915 +       }
15916 +
15917 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
15918 +               return 0;
15919 +
15920 +       return 1;
15921 +}
15922 +
15923 +static struct ipt_match realm_match
15924 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
15925 +
15926 +static int __init init(void)
15927 +{
15928 +       return ipt_register_match(&realm_match);
15929 +}
15930 +
15931 +static void __exit fini(void)
15932 +{
15933 +       ipt_unregister_match(&realm_match);
15934 +}
15935 +
15936 +module_init(init);
15937 +module_exit(fini);
15938 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_REJECT.c
15939 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_REJECT.c      2003-11-26 21:45:22.000000000 +0100
15940 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_REJECT.c  2003-12-10 23:14:20.643816360 +0100
15941 @@ -2,6 +2,7 @@
15942   * This is a module which is used for rejecting packets.
15943   * Added support for customized reject packets (Jozsef Kadlecsik).
15944   * Added support for ICMP type-3-code-13 (Maciej Soltysiak). [RFC 1812]
15945 + * Added support for fake source IP in icmp-unreach (Fabrice MARIE & Guillaume MORIN).
15946   */
15947  #include <linux/config.h>
15948  #include <linux/module.h>
15949 @@ -204,13 +205,13 @@
15950         kfree_skb(nskb);
15951  }
15952  
15953 -static void send_unreach(struct sk_buff *skb_in, int code)
15954 +static void send_unreach(struct sk_buff *skb_in, int code, u_int8_t fake_source_address)
15955  {
15956         struct iphdr *iph;
15957         struct udphdr *udph;
15958         struct icmphdr *icmph;
15959         struct sk_buff *nskb;
15960 -       u32 saddr;
15961 +       u32 saddr,packet_daddr;
15962         u8 tos;
15963         int hh_len, length;
15964         struct rtable *rt = (struct rtable*)skb_in->dst;
15965 @@ -274,7 +275,7 @@
15966                         return;
15967         }
15968  
15969 -       saddr = iph->daddr;
15970 +       packet_daddr = saddr = iph->daddr;
15971         if (!(rt->rt_flags & RTCF_LOCAL))
15972                 saddr = 0;
15973  
15974 @@ -322,7 +323,16 @@
15975         iph->ttl = MAXTTL;
15976         ip_select_ident(iph, &rt->u.dst, NULL);
15977         iph->protocol=IPPROTO_ICMP;
15978 -       iph->saddr=rt->rt_src;
15979 +
15980 +        /* fake source IP if we have to
15981 +           if fake_source_address == 1, we fake the source IP
15982 +           from the packet destination address dynamically.
15983 +        */
15984 +        if (fake_source_address == 1)
15985 +                iph->saddr = packet_daddr;
15986 +        else
15987 +               iph->saddr=rt->rt_src;
15988 +
15989         iph->daddr=rt->rt_dst;
15990         iph->check=0;
15991         iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
15992 @@ -370,25 +380,25 @@
15993            must return an absolute verdict. --RR */
15994         switch (reject->with) {
15995         case IPT_ICMP_NET_UNREACHABLE:
15996 -               send_unreach(*pskb, ICMP_NET_UNREACH);
15997 +               send_unreach(*pskb, ICMP_NET_UNREACH, reject->fake_source_address);
15998                 break;
15999         case IPT_ICMP_HOST_UNREACHABLE:
16000 -               send_unreach(*pskb, ICMP_HOST_UNREACH);
16001 +               send_unreach(*pskb, ICMP_HOST_UNREACH, reject->fake_source_address);
16002                 break;
16003         case IPT_ICMP_PROT_UNREACHABLE:
16004 -               send_unreach(*pskb, ICMP_PROT_UNREACH);
16005 +               send_unreach(*pskb, ICMP_PROT_UNREACH, reject->fake_source_address);
16006                 break;
16007         case IPT_ICMP_PORT_UNREACHABLE:
16008 -               send_unreach(*pskb, ICMP_PORT_UNREACH);
16009 +               send_unreach(*pskb, ICMP_PORT_UNREACH, reject->fake_source_address);
16010                 break;
16011         case IPT_ICMP_NET_PROHIBITED:
16012 -               send_unreach(*pskb, ICMP_NET_ANO);
16013 +               send_unreach(*pskb, ICMP_NET_ANO, reject->fake_source_address);
16014                 break;
16015         case IPT_ICMP_HOST_PROHIBITED:
16016 -               send_unreach(*pskb, ICMP_HOST_ANO);
16017 +               send_unreach(*pskb, ICMP_HOST_ANO, reject->fake_source_address);
16018                 break;
16019         case IPT_ICMP_ADMIN_PROHIBITED:
16020 -               send_unreach(*pskb, ICMP_PKT_FILTERED);
16021 +               send_unreach(*pskb, ICMP_PKT_FILTERED, reject->fake_source_address);
16022                 break;
16023         case IPT_TCP_RESET:
16024                 send_reset(*pskb, hooknum);
16025 @@ -435,6 +445,11 @@
16026                         DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
16027                         return 0;
16028                 }
16029 +               /* cannot fake source address */
16030 +               if (rejinfo->fake_source_address != 0) {
16031 +                       DEBUGP("REJECT: fake-source-address illegal for TCP-RESET\n");
16032 +                       return 0;
16033 +               }
16034         }
16035  
16036         return 1;
16037 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ROUTE.c
16038 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ROUTE.c       1970-01-01 01:00:00.000000000 +0100
16039 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ROUTE.c   2003-12-10 23:14:07.502814096 +0100
16040 @@ -0,0 +1,369 @@
16041 +/*
16042 + * This implements the ROUTE target, which enables you to setup unusual
16043 + * routes not supported by the standard kernel routing table.
16044 + *
16045 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
16046 + *
16047 + * v 1.8 2003/07/25
16048 + *
16049 + * This software is distributed under GNU GPL v2, 1991
16050 + */
16051 +
16052 +#include <linux/module.h>
16053 +#include <linux/skbuff.h>
16054 +#include <linux/ip.h>
16055 +#include <linux/netfilter_ipv4/ip_tables.h>
16056 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
16057 +#include <linux/netdevice.h>
16058 +#include <linux/route.h>
16059 +#include <net/ip.h>
16060 +#include <net/route.h>
16061 +#include <net/icmp.h>
16062 +
16063 +#if 0
16064 +#define DEBUGP printk
16065 +#else
16066 +#define DEBUGP(format, args...)
16067 +#endif
16068 +
16069 +
16070 +/* Try to route the packet according to the routing keys specified in
16071 + * route_info. Keys are :
16072 + *  - ifindex : 
16073 + *      0 if no oif preferred, 
16074 + *      otherwise set to the index of the desired oif
16075 + *  - route_info->gw :
16076 + *      0 if no gateway specified,
16077 + *      otherwise set to the next host to which the pkt must be routed
16078 + * If success, skb->dev is the output device to which the packet must 
16079 + * be sent and skb->dst is not NULL
16080 + *
16081 + * RETURN: -1 if an error occured
16082 + *          1 if the packet was succesfully routed to the 
16083 + *            destination desired
16084 + *          0 if the kernel routing table could not route the packet
16085 + *            according to the keys specified
16086 + */
16087 +static int route(struct sk_buff *skb,
16088 +                unsigned int ifindex,
16089 +                const struct ipt_route_target_info *route_info)
16090 +{
16091 +       int err;
16092 +       struct rtable *rt;
16093 +       struct iphdr *iph = skb->nh.iph;
16094 +       struct rt_key key = { 
16095 +               dst:iph->daddr,
16096 +               src:0,
16097 +               oif:ifindex, 
16098 +               tos:RT_TOS(iph->tos) 
16099 +       };
16100 +       
16101 +       /* The destination address may be overloaded by the target */
16102 +       if (route_info->gw)
16103 +               key.dst = route_info->gw;
16104 +       
16105 +       /* Trying to route the packet using the standard routing table. */
16106 +       if ((err = ip_route_output_key(&rt, &key))) {
16107 +               if (net_ratelimit()) 
16108 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
16109 +               return -1;
16110 +       }
16111 +       
16112 +       /* Drop old route. */
16113 +       dst_release(skb->dst);
16114 +       skb->dst = NULL;
16115 +
16116 +       /* Success if no oif specified or if the oif correspond to the 
16117 +        * one desired */
16118 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
16119 +               skb->dst = &rt->u.dst;
16120 +               skb->dev = skb->dst->dev;
16121 +               return 1;
16122 +       }
16123 +       
16124 +       /* The interface selected by the routing table is not the one
16125 +        * specified by the user. This may happen because the dst address
16126 +        * is one of our own addresses.
16127 +        */
16128 +       if (net_ratelimit()) 
16129 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
16130 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
16131 +       
16132 +       return 0;
16133 +}
16134 +
16135 +
16136 +/* Stolen from ip_finish_output2
16137 + * PRE : skb->dev is set to the device we are leaving by
16138 + *       skb->dst is not NULL
16139 + * POST: the packet is sent with the link layer header pushed
16140 + *       the packet is destroyed
16141 + */
16142 +static void ip_direct_send(struct sk_buff *skb)
16143 +{
16144 +       struct dst_entry *dst = skb->dst;
16145 +       struct hh_cache *hh = dst->hh;
16146 +
16147 +       if (hh) {
16148 +               read_lock_bh(&hh->hh_lock);
16149 +               memcpy(skb->data - 16, hh->hh_data, 16);
16150 +               read_unlock_bh(&hh->hh_lock);
16151 +               skb_push(skb, hh->hh_len);
16152 +               hh->hh_output(skb);
16153 +       } else if (dst->neighbour)
16154 +               dst->neighbour->output(skb);
16155 +       else {
16156 +               if (net_ratelimit())
16157 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
16158 +               kfree_skb(skb);
16159 +       }
16160 +}
16161 +
16162 +
16163 +/* PRE : skb->dev is set to the device we are leaving by
16164 + * POST: - the packet is directly sent to the skb->dev device, without 
16165 + *         pushing the link layer header.
16166 + *       - the packet is destroyed
16167 + */
16168 +static inline int dev_direct_send(struct sk_buff *skb)
16169 +{
16170 +       return dev_queue_xmit(skb);
16171 +}
16172 +
16173 +
16174 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
16175 +                             struct sk_buff *skb) 
16176 +{
16177 +       unsigned int ifindex = 0;
16178 +       struct net_device *dev_out = NULL;
16179 +
16180 +       /* The user set the interface name to use.
16181 +        * Getting the current interface index.
16182 +        */
16183 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
16184 +               ifindex = dev_out->ifindex;
16185 +       } else {
16186 +               /* Unknown interface name : packet dropped */
16187 +               if (net_ratelimit()) 
16188 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
16189 +               return NF_DROP;
16190 +       }
16191 +
16192 +       /* Trying the standard way of routing packets */
16193 +       switch (route(skb, ifindex, route_info)) {
16194 +       case 1:
16195 +               dev_put(dev_out);
16196 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
16197 +                       return IPT_CONTINUE;
16198 +
16199 +               ip_direct_send(skb);
16200 +               return NF_STOLEN;
16201 +
16202 +       case 0:
16203 +               /* Failed to send to oif. Trying the hard way */
16204 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
16205 +                       return NF_DROP;
16206 +
16207 +               if (net_ratelimit()) 
16208 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
16209 +                              ifindex);
16210 +
16211 +               /* We have to force the use of an interface.
16212 +                * This interface must be a tunnel interface since
16213 +                * otherwise we can't guess the hw address for
16214 +                * the packet. For a tunnel interface, no hw address
16215 +                * is needed.
16216 +                */
16217 +               if ((dev_out->type != ARPHRD_TUNNEL)
16218 +                   && (dev_out->type != ARPHRD_IPGRE)) {
16219 +                       if (net_ratelimit()) 
16220 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
16221 +                       dev_put(dev_out);
16222 +                       return NF_DROP;
16223 +               }
16224 +       
16225 +               /* Send the packet. This will also free skb
16226 +                * Do not go through the POST_ROUTING hook because 
16227 +                * skb->dst is not set and because it will probably
16228 +                * get confused by the destination IP address.
16229 +                */
16230 +               skb->dev = dev_out;
16231 +               dev_direct_send(skb);
16232 +               dev_put(dev_out);
16233 +               return NF_STOLEN;
16234 +               
16235 +       default:
16236 +               /* Unexpected error */
16237 +               dev_put(dev_out);
16238 +               return NF_DROP;
16239 +       }
16240 +}
16241 +
16242 +
16243 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
16244 +                             struct sk_buff *skb) 
16245 +{
16246 +       struct net_device *dev_out = NULL;
16247 +       unsigned int ifindex = 0;
16248 +
16249 +       /* Getting the current interface index. */
16250 +       if ((dev_out = dev_get_by_name(route_info->iif)))
16251 +               ifindex = dev_out->ifindex;
16252 +       else {
16253 +               /* Unknown interface name : packet dropped */
16254 +               if (net_ratelimit()) 
16255 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
16256 +               return NF_DROP;
16257 +       }
16258 +
16259 +       skb->dev = dev_out;
16260 +       dst_release(skb->dst);
16261 +       skb->dst = NULL;
16262 +               
16263 +       netif_rx(skb);
16264 +
16265 +       return NF_STOLEN;
16266 +}
16267 +
16268 +
16269 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
16270 +                            struct sk_buff *skb) 
16271 +{
16272 +       if (route(skb, 0, route_info)!=1)
16273 +               return NF_DROP;
16274 +
16275 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
16276 +               return IPT_CONTINUE;
16277 +
16278 +       ip_direct_send(skb);
16279 +       return NF_STOLEN;
16280 +}
16281 +
16282 +
16283 +static unsigned int ipt_route_target(struct sk_buff **pskb,
16284 +                                    unsigned int hooknum,
16285 +                                    const struct net_device *in,
16286 +                                    const struct net_device *out,
16287 +                                    const void *targinfo,
16288 +                                    void *userinfo)
16289 +{
16290 +       const struct ipt_route_target_info *route_info = targinfo;
16291 +       struct sk_buff *skb = *pskb;
16292 +
16293 +       /* If we are at PREROUTING or INPUT hook
16294 +        * the TTL isn't decreased by the IP stack
16295 +        */
16296 +       if (hooknum == NF_IP_PRE_ROUTING ||
16297 +           hooknum == NF_IP_LOCAL_IN) {
16298 +
16299 +               struct iphdr *iph = skb->nh.iph;
16300 +
16301 +               if (iph->ttl <= 1) {
16302 +                       struct rtable *rt;
16303 +
16304 +                       if (ip_route_output(&rt, iph->saddr, iph->daddr,
16305 +                                           RT_TOS(iph->tos) | RTO_CONN,
16306 +                                           0)) {
16307 +                               return NF_DROP;
16308 +                       }
16309 +
16310 +                       if (skb->dev == rt->u.dst.dev) {
16311 +                               /* Drop old route. */
16312 +                               dst_release(skb->dst);
16313 +                               skb->dst = &rt->u.dst;
16314 +
16315 +                               /* this will traverse normal stack, and 
16316 +                                * thus call conntrack on the icmp packet */
16317 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
16318 +                                         ICMP_EXC_TTL, 0);
16319 +                       }
16320 +
16321 +                       return NF_DROP;
16322 +               }
16323 +
16324 +               ip_decrease_ttl(iph);
16325 +       }
16326 +
16327 +       /* Tell conntrack to forget this packet since it may get confused 
16328 +        * when a packet is leaving with dst address == our address.
16329 +        * Good idea ? Dunno. Need advice.
16330 +        */
16331 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
16332 +               nf_conntrack_put(skb->nfct);
16333 +               skb->nfct = NULL;
16334 +               skb->nfcache = 0;
16335 +#ifdef CONFIG_NETFILTER_DEBUG
16336 +               skb->nf_debug = 0;
16337 +#endif
16338 +       }
16339 +
16340 +       if (route_info->oif[0]) 
16341 +               return route_oif(route_info, *pskb);
16342 +       
16343 +       if (route_info->iif[0]) 
16344 +               return route_iif(route_info, *pskb);
16345 +
16346 +       if (route_info->gw) 
16347 +               return route_gw(route_info, *pskb);
16348 +
16349 +       if (net_ratelimit()) 
16350 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
16351 +
16352 +       return IPT_CONTINUE;
16353 +}
16354 +
16355 +
16356 +static int ipt_route_checkentry(const char *tablename,
16357 +                               const struct ipt_entry *e,
16358 +                               void *targinfo,
16359 +                               unsigned int targinfosize,
16360 +                               unsigned int hook_mask)
16361 +{
16362 +       if (strcmp(tablename, "mangle") != 0) {
16363 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
16364 +                      tablename);
16365 +               return 0;
16366 +       }
16367 +
16368 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
16369 +                           | (1 << NF_IP_LOCAL_IN)
16370 +                           | (1 << NF_IP_FORWARD)
16371 +                           | (1 << NF_IP_LOCAL_OUT)
16372 +                           | (1 << NF_IP_POST_ROUTING))) {
16373 +               printk("ipt_ROUTE: bad hook\n");
16374 +               return 0;
16375 +       }
16376 +
16377 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
16378 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
16379 +                      targinfosize,
16380 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
16381 +               return 0;
16382 +       }
16383 +
16384 +       return 1;
16385 +}
16386 +
16387 +
16388 +static struct ipt_target ipt_route_reg
16389 += { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
16390 +    THIS_MODULE };
16391 +
16392 +
16393 +static int __init init(void)
16394 +{
16395 +       if (ipt_register_target(&ipt_route_reg))
16396 +               return -EINVAL;
16397 +
16398 +       return 0;
16399 +}
16400 +
16401 +
16402 +static void __exit fini(void)
16403 +{
16404 +       ipt_unregister_target(&ipt_route_reg);
16405 +}
16406 +
16407 +module_init(init);
16408 +module_exit(fini);
16409 +MODULE_LICENSE("GPL");
16410 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_rpc.c
16411 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
16412 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_rpc.c     2003-12-10 23:14:10.155410840 +0100
16413 @@ -0,0 +1,428 @@
16414 +/* RPC extension for IP connection matching, Version 2.2
16415 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
16416 + *     - original rpc tracking module
16417 + *     - "recent" connection handling for kernel 2.3+ netfilter
16418 + *
16419 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
16420 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
16421 + *
16422 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
16423 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
16424 + *     - extended matching to support filtering on procedures
16425 + *
16426 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
16427 + *
16428 + *     This program is free software; you can redistribute it and/or
16429 + *     modify it under the terms of the GNU General Public License
16430 + *     as published by the Free Software Foundation; either version
16431 + *     2 of the License, or (at your option) any later version.
16432 + **
16433 + *     Module load syntax:
16434 + *     insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
16435 + *
16436 + *     Please give the ports of all RPC servers you wish to connect to.
16437 + *     If you don't specify ports, the default will be port 111.
16438 + **
16439 + *     Note to all:
16440 + *
16441 + *     RPCs should not be exposed to the internet - ask the Pentagon;
16442 + *
16443 + *       "The unidentified crackers pleaded guilty in July to charges
16444 + *        of juvenile delinquency stemming from a string of Pentagon
16445 + *        network intrusions in February.
16446 + *
16447 + *        The youths, going by the names TooShort and Makaveli, used
16448 + *        a common server security hole to break in, according to
16449 + *        Dane Jasper, owner of the California Internet service
16450 + *        provider, Sonic. They used the hole, known as the 'statd'
16451 + *        exploit, to attempt more than 800 break-ins, Jasper said."
16452 + *
16453 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
16454 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
16455 + **
16456 + */
16457 +
16458 +#include <linux/module.h>
16459 +#include <linux/skbuff.h>
16460 +#include <linux/list.h>
16461 +#include <linux/udp.h>
16462 +#include <linux/tcp.h>
16463 +#include <linux/netfilter_ipv4/ip_conntrack.h>
16464 +#include <linux/netfilter_ipv4/ip_tables.h>
16465 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
16466 +#include <linux/netfilter_ipv4/lockhelp.h>
16467 +#include <linux/netfilter_ipv4/ipt_rpc.h>
16468 +
16469 +#define MAX_PORTS 8
16470 +static int ports[MAX_PORTS];
16471 +static int ports_n_c = 0;
16472 +
16473 +#ifdef MODULE_PARM
16474 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
16475 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
16476 +#endif
16477 +
16478 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
16479 +MODULE_DESCRIPTION("RPC connection matching module");
16480 +MODULE_LICENSE("GPL");
16481 +
16482 +#if 0
16483 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
16484 +                                       format, ## args)
16485 +#else
16486 +#define DEBUGP(format, args...)
16487 +#endif
16488 +
16489 +EXPORT_NO_SYMBOLS;
16490 +
16491 +/* vars from ip_conntrack_rpc_tcp */
16492 +extern struct list_head request_p_list_tcp;
16493 +extern struct module *ip_conntrack_rpc_tcp;
16494 +
16495 +/* vars from ip_conntrack_rpc_udp */
16496 +extern struct list_head request_p_list_udp;
16497 +extern struct module *ip_conntrack_rpc_udp;
16498 +
16499 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
16500 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
16501 +
16502 +#define ASSERT_READ_LOCK(x)                                    \
16503 +do {                                                           \
16504 +       if (x == &request_p_list_udp)                           \
16505 +               MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);        \
16506 +       else if (x == &request_p_list_tcp)                      \
16507 +               MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);        \
16508 +} while (0)
16509 +
16510 +#define ASSERT_WRITE_LOCK(x)                                   \
16511 +do {                                                           \
16512 +       if (x == &request_p_list_udp)                           \
16513 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);       \
16514 +       else if (x == &request_p_list_tcp)                      \
16515 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);       \
16516 +} while (0)
16517 +
16518 +#include <linux/netfilter_ipv4/listhelp.h>
16519 +
16520 +const int IPT_RPC_CHAR_LEN = 11;
16521 +
16522 +
16523 +static int k_atoi(char *string)
16524 +{
16525 +       unsigned int result = 0;
16526 +       int maxoctet = IPT_RPC_CHAR_LEN;
16527 +
16528 +       for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
16529 +               if (*string < 0)
16530 +                       return(0);
16531 +               if (*string == 0)
16532 +                       break;
16533 +               if (*string < 48 || *string > 57) {
16534 +                       return(0);
16535 +               }
16536 +               result = result * 10 + ( *string - 48 );
16537 +       }
16538 +       return(result);
16539 +}
16540 +
16541 +
16542 +static int match_rpcs(char *c_procs, int i_procs, int proc)
16543 +{
16544 +       int   proc_ctr;
16545 +       char *proc_ptr;
16546 +       unsigned int proc_num;
16547 +
16548 +       DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
16549 +
16550 +       if (i_procs == -1)
16551 +               return 1;
16552 +
16553 +       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
16554 +
16555 +               proc_ptr = c_procs;
16556 +               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
16557 +               proc_num = k_atoi(proc_ptr);
16558 +
16559 +               if (proc_num == proc)
16560 +                       return 1;
16561 +       }
16562 +
16563 +       return 0;
16564 +}
16565 +
16566 +
16567 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
16568 +                       int *hotdrop, int dir, struct ip_conntrack *ct,
16569 +                       int offset, struct list_head request_p_list)
16570 +{
16571 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
16572 +       struct request_p *req_p;
16573 +       u_int32_t xid;
16574 +
16575 +
16576 +       /* Get XID */
16577 +       xid = *data;
16578 +
16579 +       /* This does sanity checking on RPC payloads,
16580 +        * and permits only the RPC "get port" (3)
16581 +        * in authorised procedures in client
16582 +        * communications with the portmapper.
16583 +        */
16584 +
16585 +       data += 5;
16586 +
16587 +       /* Get RPC requestor */
16588 +       if (IXDR_GET_INT32(data) != 3) {
16589 +               DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
16590 +               if(rpcinfo->strict == 1)
16591 +                       *hotdrop = 1;
16592 +               return 0;
16593 +       }
16594 +       DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
16595 +
16596 +       data++;
16597 +
16598 +       /* Jump Credentials and Verfifier */
16599 +       data = data + IXDR_GET_INT32(data) + 2;
16600 +       data = data + IXDR_GET_INT32(data) + 2;
16601 +
16602 +       /* Get RPC procedure */
16603 +       if (match_rpcs((char *)&rpcinfo->c_procs,
16604 +           rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
16605 +               DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
16606 +                       (unsigned int)IXDR_GET_INT32(data));
16607 +
16608 +               /* If the RPC conntrack half entry already exists .. */
16609 +
16610 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
16611 +                       case IPPROTO_UDP:
16612 +                               WRITE_LOCK(&ipct_rpc_udp_lock);
16613 +                       case IPPROTO_TCP:
16614 +                               WRITE_LOCK(&ipct_rpc_tcp_lock);
16615 +               }
16616 +               req_p = LIST_FIND(&request_p_list, request_p_cmp,
16617 +                                 struct request_p *, xid,
16618 +                                 ct->tuplehash[dir].tuple.src.ip,
16619 +                                 ct->tuplehash[dir].tuple.src.u.all);
16620 +
16621 +               if (req_p) {
16622 +                       DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16623 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
16624 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16625 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
16626 +
16627 +                       /* .. remove it */
16628 +                       if (del_timer(&req_p->timeout))
16629 +                               req_p->timeout.expires = 0;
16630 +
16631 +                               LIST_DELETE(&request_p_list, req_p);
16632 +                       DEBUGP("RPC req_p removed. [done]\n");
16633 +
16634 +               } else {
16635 +                       DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16636 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
16637 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16638 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
16639 +
16640 +               }
16641 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
16642 +                       case IPPROTO_UDP:
16643 +                               WRITE_UNLOCK(&ipct_rpc_udp_lock);
16644 +                       case IPPROTO_TCP:
16645 +                               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
16646 +               }
16647 +
16648 +               if(rpcinfo->strict == 1)
16649 +                       *hotdrop = 1;
16650 +               return 0;
16651 +       }
16652 +
16653 +       DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
16654 +               (unsigned int)IXDR_GET_INT32(data));
16655 +       return (1 && (!offset));
16656 +}
16657 +
16658 +
16659 +static int match(const struct sk_buff *skb, const struct net_device *in,
16660 +                const struct net_device *out, const void *matchinfo,
16661 +                int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
16662 +{
16663 +       struct ip_conntrack *ct;
16664 +       enum ip_conntrack_info ctinfo;
16665 +       const u_int32_t *data;
16666 +       enum ip_conntrack_dir dir;
16667 +       const struct tcphdr *tcp;
16668 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
16669 +       int port, portsok;
16670 +       int tval;
16671 +
16672 +
16673 +       DEBUGP("new packet to evaluate ..\n");
16674 +
16675 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
16676 +       if (!ct) {
16677 +               DEBUGP("no ct available [skip]\n");
16678 +               return 0;
16679 +       }
16680 +
16681 +       DEBUGP("ct detected. [cont]\n");
16682 +       dir = CTINFO2DIR(ctinfo);
16683 +
16684 +       /* we only want the client to server packets for matching */
16685 +       if (dir != IP_CT_DIR_ORIGINAL)
16686 +               return 0;
16687 +
16688 +       /* This does sanity checking on UDP or TCP packets,
16689 +        * like their respective modules.
16690 +        */
16691 +
16692 +       switch (ct->tuplehash[0].tuple.dst.protonum) {
16693 +
16694 +               case IPPROTO_UDP:
16695 +                       DEBUGP("PROTO_UDP [cont]\n");
16696 +                       if (offset == 0 && datalen < sizeof(struct udphdr)) {
16697 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
16698 +                               return 0;
16699 +                       }
16700 +
16701 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
16702 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16703 +                                       portsok++;
16704 +                                       break;
16705 +                               }
16706 +                       }
16707 +                       if (portsok == 0) {
16708 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16709 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16710 +                               return 0;
16711 +                       }
16712 +
16713 +                       if ((datalen - sizeof(struct udphdr)) != 56) {
16714 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
16715 +                               if (rpcinfo->strict == 1)
16716 +                                       *hotdrop = 1;
16717 +                               return 0;
16718 +                       }
16719 +                       DEBUGP("packet length is correct. [cont]\n");
16720 +
16721 +                       /* Get to the data */
16722 +                       data = (const u_int32_t *)hdr + 2;
16723 +
16724 +                       /* Check the RPC data */
16725 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
16726 +                                               dir, ct, offset,
16727 +                                               request_p_list_udp);
16728 +
16729 +                       return tval;
16730 +                       
16731 +               
16732 +               case IPPROTO_TCP:
16733 +                       DEBUGP("PROTO_TCP [cont]\n");
16734 +                       if (offset == 0 && datalen < sizeof(struct tcphdr)) {
16735 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
16736 +                               return 0;
16737 +                       }
16738 +       
16739 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
16740 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16741 +                                       portsok++;
16742 +                                       break;
16743 +                               }
16744 +                       }
16745 +                       if (portsok == 0) {
16746 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16747 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16748 +                               return 0;
16749 +                       }
16750 +
16751 +                       tcp = hdr;
16752 +                       if (datalen == (tcp->doff * 4)) {
16753 +                               DEBUGP("packet does not contain any data. [match]\n");
16754 +                               return (1 && (!offset));
16755 +                       }
16756 +
16757 +                       /* Tests if packet len is ok */
16758 +                       if ((datalen - (tcp->doff * 4)) != 60) {
16759 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
16760 +                               if(rpcinfo->strict == 1)
16761 +                                       *hotdrop = 1;
16762 +                               return 0;
16763 +                       }
16764 +                       DEBUGP("packet length is correct. [cont]\n");
16765 +
16766 +                       /* Get to the data */
16767 +                       data = (const u_int32_t *)tcp + tcp->doff + 1;  
16768 +
16769 +                       /* Check the RPC data */
16770 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
16771 +                                               dir, ct, offset,
16772 +                                               request_p_list_tcp);
16773 +
16774 +                       return tval;
16775 +
16776 +       }
16777 +
16778 +       DEBUGP("transport protocol=%u, is not supported [skip]\n",
16779 +               ct->tuplehash[0].tuple.dst.protonum);
16780 +       return 0;
16781 +}
16782 +
16783 +
16784 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
16785 +                  unsigned int matchsize, unsigned int hook_mask)
16786 +{
16787 +       if (hook_mask
16788 +           & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
16789 +               | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
16790 +               printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
16791 +               return 0;
16792 +       }
16793 +
16794 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
16795 +               return 0;
16796 +
16797 +       return 1;
16798 +}
16799 +
16800 +
16801 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
16802 +                                       &match, &checkentry, NULL,
16803 +                                       THIS_MODULE };
16804 +
16805 +
16806 +static int __init init(void)
16807 +{
16808 +       int port;
16809 +
16810 +       DEBUGP("incrementing usage counts\n");
16811 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
16812 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
16813 +
16814 +       /* If no port given, default to standard RPC port */
16815 +       if (ports[0] == 0)
16816 +               ports[0] = RPC_PORT;
16817 +
16818 +       DEBUGP("registering match [%s] for;\n", rpc_match.name);
16819 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
16820 +               DEBUGP("  port %i (UDP|TCP);\n", ports[port]);
16821 +               ports_n_c++;
16822 +       }
16823 +       
16824 +       return ipt_register_match(&rpc_match);
16825 +}
16826 +
16827 +
16828 +static void fini(void)
16829 +{
16830 +       DEBUGP("unregistering match\n");
16831 +       ipt_unregister_match(&rpc_match);
16832 +
16833 +       DEBUGP("decrementing usage counts\n");
16834 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
16835 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
16836 +}
16837 +
16838 +
16839 +module_init(init);
16840 +module_exit(fini);
16841 +
16842 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_sctp.c
16843 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_sctp.c        1970-01-01 01:00:00.000000000 +0100
16844 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_sctp.c    2003-12-10 23:13:25.745162224 +0100
16845 @@ -0,0 +1,125 @@
16846 +/* IP tables module for matching the SCTP header
16847 + *
16848 + * $ipt_sctp.c,v 1.3 2002/05/29 15:09:00 laforge Exp$
16849 + *
16850 + * (C) 2003 by Harald Welte <laforge@gnumonks.org>
16851 + *
16852 + * This software is distributed under the terms GNU GPL v2
16853 + */
16854 +
16855 +#include <linux/module.h>
16856 +#include <linux/skbuff.h>
16857 +#include <linux/sctp.h>
16858 +
16859 +#include <linux/netfilter_ipv4/ip_tables.h>
16860 +#include <linux/netfilter_ipv4/ipt_sctp.h>
16861 +
16862 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
16863 +MODULE_DESCRIPTION("IP tables SCTP matching module");
16864 +MODULE_LICENSE("GPL");
16865 +
16866 +/* Returns 1 if the port is matched by the range, 0 otherwise */
16867 +static inline int
16868 +port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
16869 +{
16870 +       int ret;
16871 +
16872 +       ret = (port >= min && port <= max) ^ invert;
16873 +       return ret;
16874 +}
16875 +
16876 +static int chunk_match(const struct sk_buff *skb, u_int32_t chunks, u_int32_t chunk_mask)
16877 +{
16878 +       sctp_chunkhdr_t *ch = (sctp_chunkhdr_t *) skb->data;
16879 +
16880 +       u_int32_t chunks_present = 0;
16881 +
16882 +       do {
16883 +               u_int8_t *ch_end;
16884 +               ch_end = ((u_int8_t *) ch) + WORD_ROUND(ntohs(ch->length));
16885 +
16886 +               if (ch->type < 32)
16887 +                       chunks_present |= (1 << ch_type);
16888 +               else if (ch->type == SCTP_CID_ASCONF)
16889 +                       chunks_present |= (1 << 31);
16890 +               else if (ch->type == SCTP_CID_ASCONF_ACK)
16891 +                       chunks_present |= (1 << 30);
16892 +
16893 +               ch = (sctp_chunkhdr_t *) ch_end;
16894 +       } while (ch_end < skb->tail);
16895 +
16896 +       return ((chunks_present& chunk_mask) == chunks);
16897 +}
16898 +
16899 +static int match(const struct sk_buff *skb, const struct net_device *in,
16900 +                const struct net_device *out, const void *matchinfo,
16901 +                int offset, const void *hdr, u_int16_t datalen,
16902 +                int *hotdrop)
16903 +{
16904 +       const struct ipt_sctp_info *info = matchinfo;
16905 +       const struct iphdr *iph = skb->nh.iph;
16906 +       const struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
16907 +
16908 +       if (iph->protocol != IPPROTO_SCTP)
16909 +               return 0;
16910 +
16911 +       if (offset == 1) {
16912 +               duprintf("Dropping evil SCTP offset=1 frag.\n");
16913 +               *hotdrop = 1;
16914 +               return 0;
16915 +       } else if (offset == 0 && datalen < sizeof(struct sctphdr)) {
16916 +               /* We've been askd o examine this packet, and we can't.
16917 +                * Hence, no choice but to drop. */
16918 +               duprintf("Dropping evil SCTP offset=0 tinygram.\n");
16919 +               *hotdrop = 1;
16920 +               return 0;
16921 +       }
16922 +
16923 +       return (!offset
16924 +               && port_match(info->spts[0], info->spts[1],
16925 +                             ntohs(sh->source),
16926 +                             !!(info->invflags & IPT_SCTP_INV_SRCPT))
16927 +               && port_match(info->dpts[0], info->dpts[1],
16928 +                             ntohs(sh->dest),
16929 +                             !!(info->invflags & IPT_SCTP_INV_DSTPT))
16930 +               && chunk_match(skb, info->chunks, info->chunk_mask)
16931 +              );
16932 +}
16933 +
16934 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
16935 +                     void *matchinfo, unsigned int matchsize,
16936 +                     unsigned int hook_mask)
16937 +{
16938 +       const struct ipt_sctp_info *info = matchinfo;
16939 +
16940 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_sctp_info)))
16941 +               return 0;
16942 +
16943 +       if (ip->proto != IPPROTO_SCTP && !(ip->invflags & IPT_INV_PROTO))
16944 +               return 0;
16945 +
16946 +       if !(info->invflags & ~IPT_SCTP_INV_MASK)
16947 +               return 0;
16948 +
16949 +       return 1;
16950 +}
16951 +
16952 +static struct ipt_match sctp_match = {
16953 +       .name           = "sctp",
16954 +       .match          = &match,
16955 +       .checkentry     = &checkentry,
16956 +       .me             = THIS_MODULE,
16957 +};
16958 +
16959 +static int __init init(void)
16960 +{
16961 +       return ipt_register_match(&sctp_match);
16962 +}
16963 +
16964 +static void __exit fini(void)
16965 +{
16966 +       ipt_unregister_match(&sctp_match);
16967 +}
16968 +
16969 +module_init(init);
16970 +module_exit(fini);
16971 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_state.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_state.c
16972 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_state.c       2003-11-26 21:46:07.000000000 +0100
16973 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_state.c   2003-12-10 23:13:24.664326536 +0100
16974 @@ -23,10 +23,12 @@
16975         enum ip_conntrack_info ctinfo;
16976         unsigned int statebit;
16977  
16978 -       if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16979 -               statebit = IPT_STATE_INVALID;
16980 -       else
16981 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
16982 +               statebit = IPT_STATE_UNTRACKED;
16983 +       else if (ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16984                 statebit = IPT_STATE_BIT(ctinfo);
16985 +       else
16986 +               statebit = IPT_STATE_INVALID;
16987  
16988         return (sinfo->statemask & statebit);
16989  }
16990 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_string.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_string.c
16991 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_string.c      1970-01-01 01:00:00.000000000 +0100
16992 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_string.c  2003-12-10 23:14:14.165801168 +0100
16993 @@ -0,0 +1,218 @@
16994 +/* Kernel module to match a string into a packet.
16995 + *
16996 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
16997 + * 
16998 + * ChangeLog
16999 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
17000 + *             Fixed SMP re-entrancy problem using per-cpu data areas
17001 + *             for the skip/shift tables.
17002 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
17003 + *             Fixed kernel panic, due to overrunning boyer moore string
17004 + *             tables. Also slightly tweaked heuristic for deciding what
17005 + *             search algo to use.
17006 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
17007 + *             Implemented Boyer Moore Sublinear search algorithm
17008 + *             alongside the existing linear search based on memcmp().
17009 + *             Also a quick check to decide which method to use on a per
17010 + *             packet basis.
17011 + */
17012 +
17013 +#include <linux/smp.h>
17014 +#include <linux/module.h>
17015 +#include <linux/skbuff.h>
17016 +#include <linux/file.h>
17017 +#include <net/sock.h>
17018 +
17019 +#include <linux/netfilter_ipv4/ip_tables.h>
17020 +#include <linux/netfilter_ipv4/ipt_string.h>
17021 +
17022 +MODULE_LICENSE("GPL");
17023 +
17024 +struct string_per_cpu {
17025 +       int *skip;
17026 +       int *shift;
17027 +       int *len;
17028 +};
17029 +
17030 +struct string_per_cpu *bm_string_data=NULL;
17031 +
17032 +/* Boyer Moore Sublinear string search - VERY FAST */
17033 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
17034 +{
17035 +       int M1, right_end, sk, sh;  
17036 +       int ended, j, i;
17037 +
17038 +       int *skip, *shift, *len;
17039 +       
17040 +       /* use data suitable for this CPU */
17041 +       shift=bm_string_data[smp_processor_id()].shift;
17042 +       skip=bm_string_data[smp_processor_id()].skip;
17043 +       len=bm_string_data[smp_processor_id()].len;
17044 +       
17045 +       /* Setup skip/shift tables */
17046 +       M1 = right_end = needle_len-1;
17047 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
17048 +       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
17049 +
17050 +       for (i = 1; i < needle_len; i++) {   
17051 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
17052 +               len[i] = j;  
17053 +       }  
17054 +
17055 +       shift[0] = 1;  
17056 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
17057 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
17058 +       ended = 0;  
17059 +       
17060 +       for (i = 0; i < needle_len; i++) {  
17061 +               if (len[i] == M1 - i) ended = i;  
17062 +               if (ended) shift[i] = ended;  
17063 +       }  
17064 +
17065 +       /* Do the search*/  
17066 +       while (right_end < haystack_len)
17067 +       {
17068 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
17069 +               if (i == needle_len) {
17070 +                       return haystack+(right_end - M1);
17071 +               }
17072 +               
17073 +               sk = skip[haystack[right_end - i]];  
17074 +               sh = shift[i];
17075 +               right_end = max(right_end - i + sk, right_end + sh);  
17076 +       }
17077 +
17078 +       return NULL;
17079 +}  
17080 +
17081 +/* Linear string search based on memcmp() */
17082 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
17083 +{
17084 +       char *k = haystack + (haystack_len-needle_len);
17085 +       char *t = haystack;
17086 +       
17087 +       while ( t <= k ) {
17088 +               if (memcmp(t, needle, needle_len) == 0)
17089 +                       return t;
17090 +               t++;
17091 +       }
17092 +
17093 +       return NULL;
17094 +}
17095 +
17096 +
17097 +static int
17098 +match(const struct sk_buff *skb,
17099 +      const struct net_device *in,
17100 +      const struct net_device *out,
17101 +      const void *matchinfo,
17102 +      int offset,
17103 +      const void *hdr,
17104 +      u_int16_t datalen,
17105 +      int *hotdrop)
17106 +{
17107 +       const struct ipt_string_info *info = matchinfo;
17108 +       struct iphdr *ip = skb->nh.iph;
17109 +       int hlen, nlen;
17110 +       char *needle, *haystack;
17111 +       proc_ipt_search search=search_linear;
17112 +
17113 +       if ( !ip ) return 0;
17114 +
17115 +       /* get lenghts, and validate them */
17116 +       nlen=info->len;
17117 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
17118 +       if ( nlen > hlen ) return 0;
17119 +
17120 +       needle=(char *)&info->string;
17121 +       haystack=(char *)ip+(ip->ihl*4);
17122 +
17123 +       /* The sublinear search comes in to its own
17124 +        * on the larger packets */
17125 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
17126 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
17127 +               if ( hlen < BM_MAX_HLEN ) {
17128 +                       search=search_sublinear;
17129 +               }else{
17130 +                       if (net_ratelimit())
17131 +                               printk(KERN_INFO "ipt_string: Packet too big "
17132 +                                       "to attempt sublinear string search "
17133 +                                       "(%d bytes)\n", hlen );
17134 +               }
17135 +       }
17136 +       
17137 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
17138 +}
17139 +
17140 +static int
17141 +checkentry(const char *tablename,
17142 +           const struct ipt_ip *ip,
17143 +           void *matchinfo,
17144 +           unsigned int matchsize,
17145 +           unsigned int hook_mask)
17146 +{
17147 +
17148 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
17149 +               return 0;
17150 +
17151 +       return 1;
17152 +}
17153 +
17154 +void string_freeup_data(void)
17155 +{
17156 +       int c;
17157 +       
17158 +       if ( bm_string_data ) {
17159 +               for(c=0; c<smp_num_cpus; c++) {
17160 +                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
17161 +                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
17162 +                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
17163 +               }
17164 +               kfree(bm_string_data);
17165 +       }
17166 +}
17167 +
17168 +static struct ipt_match string_match
17169 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
17170 +
17171 +static int __init init(void)
17172 +{
17173 +       int c;
17174 +       size_t tlen;
17175 +       size_t alen;
17176 +
17177 +       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
17178 +       alen=sizeof(int)*BM_MAX_HLEN;
17179 +       
17180 +       /* allocate array of structures */
17181 +       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
17182 +               return 0;
17183 +       }
17184 +       
17185 +       memset(bm_string_data, 0, tlen);
17186 +       
17187 +       /* allocate our skip/shift tables */
17188 +       for(c=0; c<smp_num_cpus; c++) {
17189 +               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
17190 +                       goto alloc_fail;
17191 +               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
17192 +                       goto alloc_fail;
17193 +               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
17194 +                       goto alloc_fail;
17195 +       }
17196 +       
17197 +       return ipt_register_match(&string_match);
17198 +
17199 +alloc_fail:
17200 +       string_freeup_data();
17201 +       return 0;
17202 +}
17203 +
17204 +static void __exit fini(void)
17205 +{
17206 +       ipt_unregister_match(&string_match);
17207 +       string_freeup_data();
17208 +}
17209 +
17210 +module_init(init);
17211 +module_exit(fini);
17212 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TARPIT.c
17213 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TARPIT.c      1970-01-01 01:00:00.000000000 +0100
17214 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TARPIT.c  2003-12-10 23:14:01.536721080 +0100
17215 @@ -0,0 +1,284 @@
17216 +/* 
17217 + * Kernel module to capture and hold incoming TCP connections using 
17218 + * no local per-connection resources.
17219 + * 
17220 + * Based on ipt_REJECT.c and offering functionality similar to 
17221 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
17222 + * 
17223 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
17224 + * 
17225 + * This program is free software; you can redistribute it and/or modify
17226 + * it under the terms of the GNU General Public License as published by
17227 + * the Free Software Foundation; either version 2 of the License, or
17228 + * (at your option) any later version.
17229 + *
17230 + * This program is distributed in the hope that it will be useful,
17231 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17232 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17233 + * GNU General Public License for more details.
17234 + *
17235 + * You should have received a copy of the GNU General Public License
17236 + * along with this program; if not, write to the Free Software
17237 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17238 + * 
17239 + * Goal:
17240 + * - Allow incoming TCP connections to be established.
17241 + * - Passing data should result in the connection being switched to the 
17242 + *   persist state (0 byte window), in which the remote side stops sending 
17243 + *   data and asks to continue every 60 seconds.
17244 + * - Attempts to shut down the connection should be ignored completely, so 
17245 + *   the remote side ends up having to time it out.
17246 + *
17247 + * This means:
17248 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
17249 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
17250 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
17251 + */
17252 +
17253 +#include <linux/config.h>
17254 +#include <linux/module.h>
17255 +#include <linux/skbuff.h>
17256 +#include <linux/ip.h>
17257 +#include <net/ip.h>
17258 +#include <net/tcp.h>
17259 +#include <net/icmp.h>
17260 +struct in_device;
17261 +#include <net/route.h>
17262 +#include <linux/random.h>
17263 +#include <linux/netfilter_ipv4/ip_tables.h>
17264 +
17265 +#if 0
17266 +#define DEBUGP printk
17267 +#else
17268 +#define DEBUGP(format, args...)
17269 +#endif
17270 +
17271 +
17272 +/* Stolen from ip_finish_output2 */
17273 +static int ip_direct_send(struct sk_buff *skb)
17274 +{
17275 +       struct dst_entry *dst = skb->dst;
17276 +       struct hh_cache *hh = dst->hh;
17277 +
17278 +       if (hh) {    
17279 +               read_lock_bh(&hh->hh_lock);
17280 +               memcpy(skb->data - 16, hh->hh_data, 16);
17281 +                read_unlock_bh(&hh->hh_lock);
17282 +                skb_push(skb, hh->hh_len);
17283 +                return hh->hh_output(skb);
17284 +        } else if (dst->neighbour)
17285 +                return dst->neighbour->output(skb);
17286 +
17287 +       if (net_ratelimit())
17288 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
17289 +        kfree_skb(skb);
17290 +        return -EINVAL;
17291 +}
17292 +
17293 +
17294 +/* Send reply */
17295 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
17296 +{
17297 +       struct sk_buff *nskb;
17298 +       struct rtable *nrt;
17299 +       struct tcphdr *otcph, *ntcph;
17300 +       unsigned int otcplen;
17301 +       u_int16_t tmp;
17302 +
17303 +       /* A truncated TCP header isn't going to be useful */
17304 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
17305 +               return;
17306 +
17307 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
17308 +                                  + oskb->nh.iph->ihl);
17309 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
17310 +
17311 +       /* No replies for RST or FIN */
17312 +       if (otcph->rst || otcph->fin)
17313 +               return;
17314 +
17315 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
17316 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
17317 +               return;
17318 +
17319 +       /* Check checksum. */
17320 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
17321 +                        oskb->nh.iph->daddr,
17322 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
17323 +               return;
17324 +
17325 +       /* Copy skb (even if skb is about to be dropped, we can't just
17326 +           clone it because there may be other things, such as tcpdump,
17327 +           interested in it) */
17328 +       nskb = skb_copy(oskb, GFP_ATOMIC);
17329 +       if (!nskb)
17330 +               return;
17331 +
17332 +       /* This packet will not be the same as the other: clear nf fields */
17333 +       nf_conntrack_put(nskb->nfct);
17334 +       nskb->nfct = NULL;
17335 +       nskb->nfcache = 0;
17336 +#ifdef CONFIG_NETFILTER_DEBUG
17337 +       nskb->nf_debug = 0;
17338 +#endif
17339 +
17340 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
17341 +
17342 +       /* Truncate to length (no data) */
17343 +       ntcph->doff = sizeof(struct tcphdr)/4;
17344 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
17345 +       nskb->nh.iph->tot_len = htons(nskb->len);
17346 +
17347 +       /* Swap source and dest */
17348 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
17349 +       tmp = ntcph->source;
17350 +       ntcph->source = ntcph->dest;
17351 +       ntcph->dest = tmp;
17352 +
17353 +       /* Use supplied sequence number or make a new one */
17354 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
17355 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
17356 +                                                       nskb->nh.iph->daddr, 
17357 +                                                       ntcph->source, 
17358 +                                                       ntcph->dest));
17359 +
17360 +       /* Our SYN-ACKs must have a >0 window */
17361 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
17362 +
17363 +       ntcph->urg_ptr = 0;
17364 +
17365 +       /* Reset flags */
17366 +       ((u_int8_t *)ntcph)[13] = 0;
17367 +
17368 +       if (otcph->syn && otcph->ack) {
17369 +               ntcph->rst = 1;
17370 +               ntcph->ack_seq = 0;
17371 +       } else {
17372 +               ntcph->syn = otcph->syn;
17373 +               ntcph->ack = 1;
17374 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
17375 +       }
17376 +
17377 +       /* Adjust TCP checksum */
17378 +       ntcph->check = 0;
17379 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
17380 +                                  nskb->nh.iph->saddr,
17381 +                                  nskb->nh.iph->daddr,
17382 +                                  csum_partial((char *)ntcph,
17383 +                                               sizeof(struct tcphdr), 0));
17384 +
17385 +       /* Adjust IP TTL */
17386 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
17387 +
17388 +       /* Set DF, id = 0 */
17389 +       nskb->nh.iph->frag_off = htons(IP_DF);
17390 +       nskb->nh.iph->id = 0;
17391 +
17392 +       /* Adjust IP checksum */
17393 +       nskb->nh.iph->check = 0;
17394 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
17395 +                                          nskb->nh.iph->ihl);
17396 +
17397 +       if (ip_route_output(&nrt, nskb->nh.iph->daddr, 
17398 +                           local ? nskb->nh.iph->saddr : 0,
17399 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN, 
17400 +                           0) != 0)
17401 +               goto free_nskb;
17402 +
17403 +       dst_release(nskb->dst);
17404 +       nskb->dst = &nrt->u.dst;
17405 +
17406 +       /* "Never happens" */
17407 +       if (nskb->len > nskb->dst->pmtu)
17408 +               goto free_nskb;
17409 +
17410 +       ip_direct_send (nskb);
17411 +
17412 +       return;
17413 +
17414 + free_nskb:
17415 +       kfree_skb(nskb);
17416 +}
17417 +
17418 +
17419 +static unsigned int tarpit(struct sk_buff **pskb,
17420 +                          unsigned int hooknum,
17421 +                          const struct net_device *in,
17422 +                          const struct net_device *out,
17423 +                          const void *targinfo,
17424 +                          void *userinfo)
17425 +{
17426 +       struct sk_buff *skb = *pskb;
17427 +       struct rtable *rt = (struct rtable*)skb->dst;
17428 +
17429 +       /* Do we have an input route cache entry? */
17430 +       if (!rt)
17431 +               return NF_DROP;
17432 +
17433 +        /* No replies to physical multicast/broadcast */
17434 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
17435 +               return NF_DROP;
17436 +
17437 +        /* Now check at the protocol level */
17438 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
17439 +                return NF_DROP;
17440 +
17441 +       /* Our naive response construction doesn't deal with IP
17442 +           options, and probably shouldn't try. */
17443 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
17444 +               return NF_DROP;
17445 +
17446 +        /* We aren't interested in fragments */
17447 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
17448 +                return NF_DROP;
17449 +
17450 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
17451 +
17452 +       return NF_DROP;
17453 +}
17454 +
17455 +
17456 +static int check(const char *tablename,
17457 +                const struct ipt_entry *e,
17458 +                void *targinfo,
17459 +                unsigned int targinfosize,
17460 +                unsigned int hook_mask)
17461 +{
17462 +       /* Only allow these for input/forward packet filtering. */
17463 +       if (strcmp(tablename, "filter") != 0) {
17464 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
17465 +               return 0;
17466 +       }
17467 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
17468 +                           | (1 << NF_IP_FORWARD))) != 0) {
17469 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
17470 +               return 0;
17471 +       }
17472 +
17473 +       /* Must specify that it's a TCP packet */
17474 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
17475 +               DEBUGP("TARPIT: not valid for non-tcp\n");
17476 +               return 0;
17477 +       }
17478 +
17479 +       return 1;
17480 +}
17481 +
17482 +static struct ipt_target ipt_tarpit_reg
17483 += { { NULL, NULL }, "TARPIT", tarpit, check, NULL, THIS_MODULE };
17484 +
17485 +static int __init init(void)
17486 +{
17487 +       if (ipt_register_target(&ipt_tarpit_reg))
17488 +               return -EINVAL;
17489 +       return 0;
17490 +}
17491 +
17492 +static void __exit fini(void)
17493 +{
17494 +       ipt_unregister_target(&ipt_tarpit_reg);
17495 +}
17496 +
17497 +module_init(init);
17498 +module_exit(fini);
17499 +MODULE_LICENSE("GPL");
17500 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TCPLAG.c
17501 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TCPLAG.c      1970-01-01 01:00:00.000000000 +0100
17502 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TCPLAG.c  2003-12-10 23:14:16.741409616 +0100
17503 @@ -0,0 +1,697 @@
17504 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
17505 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
17506 + *
17507 + * This program is free software; you can redistribute it and/or modify
17508 + * it under the terms of the GNU General Public License as published by
17509 + * the Free Software Foundation; either version 2 of the License, or
17510 + * (at your option) any later version.
17511 + *
17512 + * This program is distributed in the hope that it will be useful,
17513 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17514 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17515 + * GNU General Public License for more details.
17516 + *
17517 + * You should have received a copy of the GNU General Public License
17518 + * along with this program; if not, write to the Free Software
17519 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17520 + */
17521 +
17522 +/*
17523 + * This collects packets and attempts to make them into pairs
17524 + * based on its own knowledge of how typical network conversations
17525 + * operate. Once it has a pair, it logs the time between them.
17526 + */
17527 +#include <linux/module.h>
17528 +#include <linux/skbuff.h>
17529 +#include <linux/ip.h>
17530 +#include <linux/spinlock.h>
17531 +#include <net/icmp.h>
17532 +#include <net/udp.h>
17533 +#include <net/tcp.h>
17534 +#include <linux/netfilter_ipv4/ip_tables.h>
17535 +
17536 +#include <net/route.h>
17537 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
17538 +
17539 +#if 0
17540 +#define DEBUGP printk
17541 +#else
17542 +#define DEBUGP(format, args...)
17543 +#endif
17544 +
17545 +/*
17546 + * We need one spinlock for the hash table.
17547 + */
17548 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
17549 +
17550 +typedef struct timeval timeval_T;
17551 +
17552 +/*
17553 + * Linked lists of events in the connection,
17554 + * these store the SEQ numbers and the newest is always
17555 + * at the start of the linked list, then they get older
17556 + * down to the end of the linked list (this is not perfect
17557 + * if packets get out of order but we don't worry about fine
17558 + * details like that).
17559 + *
17560 + * Matching any event wipes out that event and also all other
17561 + * events down the chain (i.e. all older events).
17562 + * This keeps the linked list as short as possible.
17563 + */
17564 +typedef struct tcplag_event_S
17565 +{
17566 +       struct tcplag_event_S *next;
17567 +       u16 source_port;
17568 +       u16 dest_port;
17569 +       u32 expected_ACK;
17570 +       struct timeval stamp;
17571 +} tcplag_event_T;
17572 +
17573 +/*
17574 + * This stores the connection statistics
17575 + * We define connections more loosely than TCP/IP does,
17576 + * because we only consider the two hosts, not the ports
17577 + * Also, we list the host-pairs in low,high order which
17578 + * means that we don't care who originated the connection.
17579 + */
17580 +typedef struct tcplag_hash_S
17581 +{
17582 +       u32 low_ip;
17583 +       u32 high_ip;
17584 +       struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
17585 +       struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
17586 +       tcplag_event_T *h_ACK_list;     /* Try to match ACK packets coming from h in this list */
17587 +       tcplag_event_T *l_ACK_list;     /* Try to match ACK packets coming from l in this list */
17588 +       time_t stamp;                   /* When this bucket got added to the table */
17589 +       u16 count_l_SEQ_h_ACK;          /* Increment for each event */
17590 +       u16 count_h_SEQ_l_ACK;          /* Increment for each event */
17591 +} tcplag_hash_T;
17592 +
17593 +static tcplag_hash_T **hashtab = 0;
17594 +static u32 hashsize = 0;
17595 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
17596 +static u32 reaper_ix = 0;
17597 +
17598 +static void divide_down( timeval_T *T, int c )
17599 +{
17600 +       int remainder;
17601 +
17602 +       T->tv_usec /= c;
17603 +       remainder = T->tv_sec % c; /* Only works properly with positive numbers */
17604 +       remainder *= 1000000;
17605 +       T->tv_usec == remainder;
17606 +       T->tv_sec /= c;
17607 +}
17608 +
17609 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
17610 +{
17611 +       register long x;
17612 +
17613 +       x = tv1->tv_sec - tv2->tv_sec;
17614 +       if( x ) return( x );
17615 +       x = tv1->tv_usec - tv2->tv_usec;
17616 +       return( x );
17617 +}
17618 +
17619 +void sprint_timeval( char *buf, timeval_T *tv )
17620 +{
17621 +       if( tv->tv_sec )
17622 +               sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
17623 +       else
17624 +               sprintf( buf, "%lu", tv->tv_usec );
17625 +}
17626 +
17627 +/*
17628 + * This generates the log messages through printk()
17629 + *
17630 + * There is really no particular interest in the port numbers at this stage,
17631 + * they are only useful for matching up the request with the reply.
17632 + * The IP numbers are useful because some sites may be slower than others
17633 + * or may travel different routes, etc (OK, in theory changing the port number
17634 + * could also change the route but I don't like that sort of theory).
17635 + *
17636 + * The tags are:
17637 + *
17638 + * LIP=          The IP number of the side with the lowest lag
17639 + * RIP=          The IP number of the side with the highest lag
17640 + * LLAG=         The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
17641 + * RLAG=         The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
17642 + */
17643 +static void output( tcplag_hash_T *H, int level, const char *prefix )
17644 +{
17645 +       struct timeval ltm, rtm;
17646 +       u32 local_ip, remote_ip;
17647 +       char r_buf[ 20 ], l_buf[ 20 ];
17648 +/*
17649 + * We can't make sense of a connection that only passes data one way,
17650 + * In principle, at least the SYN and FIN should go both ways so we
17651 + * should get a few hits for every connection.
17652 + */
17653 +       if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
17654 +/*
17655 + * Calculate average times by dividing down
17656 + */
17657 +       divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
17658 +       divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
17659 +/*
17660 + * Sort these two by the lag so the the local is always the short lag
17661 + */
17662 +       if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
17663 +       {
17664 +               local_ip    = H->low_ip;
17665 +               remote_ip   = H->high_ip;
17666 +               rtm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
17667 +               rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
17668 +               ltm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
17669 +               ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
17670 +       }
17671 +       else
17672 +       {
17673 +               local_ip    = H->high_ip;
17674 +               remote_ip   = H->low_ip;
17675 +               ltm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
17676 +               ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
17677 +               rtm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
17678 +               rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
17679 +       }
17680 +/*
17681 + * Don't use a spinlock on the output,
17682 + * it is not guaranteed safe because some OTHER printk could
17683 + * split our log message so we want only one single printk.
17684 + *
17685 + * We use sprintf() to partially pre-digest the output
17686 + *
17687 + * Actually, neither this not the main netfilter LOG target is
17688 + * really safe from printk() overlap, basically syslog cannot
17689 + * be regarded as a guaranteed data output channel. It is good
17690 + * enough for most purposes.
17691 + */
17692 +       sprint_timeval( l_buf, &ltm );
17693 +       sprint_timeval( r_buf, &rtm );
17694 +       printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
17695 +                       level & 7, prefix,
17696 +                       NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
17697 +                       l_buf, r_buf );
17698 +}
17699 +
17700 +/*
17701 + * The reaper rolls through the hash table looking for old.
17702 + * Log entries are only generated at the reaping time
17703 + * (which means all log entries are out-of-date)
17704 + */
17705 +static void reaper( time_t now, int level, const char *prefix )
17706 +{
17707 +       int i;
17708 +
17709 +       now -= max_seconds;
17710 +       if( !hashsize ) return;
17711 +       if( !hashtab ) return;
17712 +       for( i = 0; i < 10; i++ )
17713 +       {
17714 +               if( ++reaper_ix >= hashsize ) reaper_ix = 0; 
17715 +
17716 +//             DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
17717 +
17718 +               if( hashtab[ reaper_ix ])
17719 +               {
17720 +                       tcplag_hash_T *found = 0;
17721 +
17722 +                       spin_lock_bh( &hash_lock );
17723 +                       if( hashtab[ reaper_ix ])
17724 +                       {
17725 +                               if( now > hashtab[ reaper_ix ]->stamp )
17726 +                               {
17727 +                                       DEBUGP( KERN_WARNING "reaper found expired entry\n" );
17728 +                                       found = hashtab[ reaper_ix ];
17729 +                                       hashtab[ reaper_ix ] = 0;
17730 +                               }
17731 +                       }
17732 +                       spin_unlock_bh( &hash_lock );
17733 +
17734 +                       if( found )
17735 +                       {
17736 +                               output( found, level, prefix );
17737 +                               kfree( found );
17738 +                       }
17739 +               }
17740 +       }
17741 +}
17742 +
17743 +/*
17744 + * Convert the connection characteristics into a number
17745 + * (not including the timestamp) FIXME: this is a sucky hash function
17746 + */
17747 +static u32 make_hash( tcplag_hash_T *connection )
17748 +{
17749 +       register u32 r;
17750 +
17751 +       r = connection->low_ip;
17752 +       r += connection->high_ip;
17753 +       return( r );
17754 +}
17755 +
17756 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
17757 +{
17758 +       int x;
17759 +
17760 +       x = con1->low_ip - con2->low_ip; if( x ) return( x );
17761 +       x = con1->high_ip - con2->high_ip;
17762 +       return( x );
17763 +}
17764 +
17765 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
17766 +{
17767 +       int x;
17768 +
17769 +       DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
17770 +       x = ev1->expected_ACK - ev2->expected_ACK;
17771 +       if( x ) return( x );
17772 +       DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
17773 +       x = ev1->source_port - ev2->source_port;
17774 +       if( x ) return( x );
17775 +       DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
17776 +       x = ev1->dest_port - ev2->dest_port;
17777 +       return( x );
17778 +}
17779 +
17780 +/*
17781 + * Go to the hash table and either find an existing connection that
17782 + * matches correctly or inject a new connection into the table.
17783 + * Once the connection is OK, chain the event onto the linked list.
17784 + */
17785 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17786 +{
17787 +       u32 h, i;
17788 +
17789 +       if( !event ) return; /* Just to be safe */
17790 +       if( !hashsize ) return;
17791 +       if( !hashtab ) return;
17792 +
17793 +       h = make_hash( connection );
17794 +       h %= hashsize;
17795 +
17796 +       DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
17797 +
17798 +       spin_lock_bh( &hash_lock );
17799 +       for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
17800 +       {
17801 +               tcplag_hash_T *co_new = 0;
17802 +/*
17803 + * Consider existing entry
17804 + */
17805 +               if( hashtab[ h ])
17806 +               {
17807 +                       if( compare_connections( hashtab[ h ], connection )) continue;
17808 +                       co_new = hashtab[ h ];
17809 +                       DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
17810 +                       goto add_link;
17811 +               }
17812 +/*
17813 + * Use empty slot for new entry
17814 + */
17815 +               if( !hashtab[ h ])
17816 +               {
17817 +                       co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
17818 +                       memset( co_new, 0, sizeof( tcplag_hash_T ));
17819 +                       co_new->low_ip = connection->low_ip;
17820 +                       co_new->high_ip = connection->high_ip;
17821 +                       co_new->stamp = event->stamp.tv_sec;
17822 +                       hashtab[ h ] = co_new;
17823 +                       DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
17824 + add_link:
17825 +                       {
17826 +                               tcplag_event_T *ev_new;
17827 +
17828 +                               ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
17829 +                               memcpy( ev_new, event, sizeof( tcplag_event_T ));
17830 +                               if( direction )
17831 +                               {
17832 +                                       ev_new->next = co_new->h_ACK_list;
17833 +                                       co_new->h_ACK_list = ev_new;
17834 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
17835 +                               }
17836 +                               else
17837 +                               {
17838 +                                       ev_new->next = co_new->l_ACK_list;
17839 +                                       co_new->l_ACK_list = ev_new;
17840 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
17841 +                               }
17842 +                       }
17843 +                       goto done;
17844 +               }
17845 +       }
17846 + done:
17847 +       spin_unlock_bh( &hash_lock );
17848 +}
17849 +
17850 +/*
17851 + * Search the hash table for a matching connection,
17852 + * if we can't find one of those then we are stuffed.
17853 + *
17854 + * Once a connection has been found, scan along the list for
17855 + * a matching SEQ number and if that is found then calculate
17856 + * the lag, update the counters and cut the chain at the
17857 + * point where the matching SEQ is found.
17858 + */
17859 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17860 +{
17861 +       u32 h, i;
17862 +
17863 +       if( !event ) return( 0 );
17864 +       if( !hashsize ) return( 0 );
17865 +       if( !hashtab ) return( 0 );
17866 +       h = make_hash( connection );
17867 +       h %= hashsize;
17868 +
17869 +       DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
17870 +
17871 +       for( i = 0; i < hashsize; i++ )
17872 +       {
17873 +               tcplag_hash_T *found = 0;
17874 +
17875 +               if( !hashtab[ h ]) return( 0 );
17876 +
17877 +               spin_lock_bh( &hash_lock );
17878 +               if( hashtab[ h ])
17879 +               {
17880 +                       if( !compare_connections( hashtab[ h ], connection ))
17881 +                       {
17882 +                               tcplag_event_T *ev, **evroot;
17883 +                               timeval_T *tv;
17884 +                               u16 *cn;
17885 +
17886 +                               found = hashtab[ h ];
17887 +                               if( direction )
17888 +                               {
17889 +                                       evroot = &found->h_ACK_list;
17890 +                                       tv = &found->lag_l_SEQ_h_ACK;
17891 +                                       cn = &found->count_l_SEQ_h_ACK;
17892 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
17893 +                               }
17894 +                               else
17895 +                               {
17896 +                                       evroot = &found->l_ACK_list;
17897 +                                       tv = &found->lag_h_SEQ_l_ACK;
17898 +                                       cn = &found->count_h_SEQ_l_ACK;
17899 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
17900 +                               }
17901 +                               for( ev = *evroot; ev; ev = ev->next )
17902 +                               {
17903 +                                       if( !compare_events( ev, event ))
17904 +                                       {
17905 +/*
17906 + * Calculate the lag (in two parts) and add that to the collection
17907 + */
17908 +                                               event->stamp.tv_sec -= ev->stamp.tv_sec;
17909 +                                               event->stamp.tv_usec -= ev->stamp.tv_usec;
17910 +                                               if( event->stamp.tv_usec < 0 )
17911 +                                               {
17912 +                                                       event->stamp.tv_usec += 1000000;
17913 +                                                       event->stamp.tv_sec++;
17914 +                                               }
17915 +                                               if( event->stamp.tv_sec < 0 )
17916 +                                               {
17917 +                                                       DEBUGP( KERN_WARNING "Negative lag detected\n" );
17918 +                                               }
17919 +                                               else
17920 +                                               {
17921 +                                                       tv->tv_sec += event->stamp.tv_sec;
17922 +                                                       tv->tv_usec += event->stamp.tv_usec;
17923 +                                                       ++*cn;
17924 +                                                       DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
17925 +                                                                       " (accumulator is up to %lu.%06lu, %u events)\n",
17926 +                                                                       event->stamp.tv_sec,
17927 +                                                                       event->stamp.tv_usec,
17928 +                                                                       tv->tv_sec, tv->tv_usec, *cn );
17929 +                                               }
17930 +/*
17931 + * Truncate the linked list.
17932 + *
17933 + * Visit each event in the list and return the memory to the pool.
17934 + *
17935 + * If a host is making multiple connections to the same remote host
17936 + * then this truncation will result in some requests not being
17937 + * monitored. Statistically we will still get some reasonable number
17938 + * of measurements and multiple simultaneous connections between host
17939 + * pairs don't happen all that often.
17940 + */
17941 +                                               *evroot = 0;
17942 +                                               while( ev )
17943 +                                               {
17944 +                                                       tcplag_event_T *ev_next = ev->next;
17945 +                                                       DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
17946 +                                                       kfree( ev );
17947 +                                                       ev = ev_next;
17948 +                                               }
17949 +/*
17950 + * TODO: overflow limit for *cn, force premature output() if necessary
17951 + * (and drop this connection from the hash table)
17952 + */
17953 +                                               break;
17954 +                                       }
17955 +                               }
17956 +                               goto done;
17957 +                       }
17958 +               }
17959 + done:
17960 +               spin_unlock_bh( &hash_lock );
17961 +
17962 +               if( found ) return( 1 );
17963 +               if( ++h >= hashsize ) h = 0;
17964 +       }       
17965 +       return( 0 );
17966 +}
17967 +
17968 +/*
17969 + * Here is our target data:
17970 + *
17971 + * pskb      --  The packet itself (see linux/skbuff.h for breakdown)
17972 + *
17973 + * hooknum   --
17974 + *
17975 + * in        --  The device that this packet came in on
17976 + *               (depending on the chain this may or may not exist)
17977 + *
17978 + * out       --  The device that this packet is just about to go
17979 + *               out onto (again existance depends on the chain)
17980 + *
17981 + * targinfo  --  Our private data (handed through from iptables command util)
17982 + *
17983 + * userinfo  --  Some more data
17984 + *
17985 + */
17986 +
17987 +static unsigned int target( struct sk_buff **pskb,
17988 +                                                       unsigned int hooknum,
17989 +                                                       const struct net_device *in,
17990 +                                                       const struct net_device *out,
17991 +                                                       const void *targinfo,
17992 +                                                       void *userinfo )
17993 +{
17994 +       struct iphdr *iph = ( *pskb )->nh.iph;
17995 +       const struct ipt_tcplag *el = targinfo;
17996 +       tcplag_hash_T connection;
17997 +       tcplag_event_T event;
17998 +       int direction;
17999 +/*
18000 + * We know we are dealing with IP here
18001 + * Fill in all the obvious fields
18002 + */
18003 +       if( iph->saddr > iph->daddr )
18004 +       {
18005 +               direction = 0;
18006 +               connection.high_ip = iph->saddr;
18007 +               connection.low_ip = iph->daddr;
18008 +       }
18009 +       else
18010 +       {
18011 +               direction = 1;
18012 +               connection.low_ip = iph->saddr;
18013 +               connection.high_ip = iph->daddr;
18014 +       }
18015 +       do_gettimeofday( &event.stamp );
18016 +/*
18017 + * Do a bit of cleaning
18018 + */
18019 +       reaper( event.stamp.tv_sec, el->level, el->prefix );
18020 +
18021 +       DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
18022 +                       event.stamp.tv_sec,
18023 +                       event.stamp.tv_usec,
18024 +                       in ? in->name : "none", out ? out->name : "none" );
18025 +/*
18026 + * Now start looking at the details
18027 + *
18028 + * First step is to identify this packet to see if it is 
18029 + * the sort of packet that we are interested in.
18030 + * Don't hold any locks while we are doing this because often
18031 + * we will just let the packet go without any further consideration.
18032 + */
18033 +       switch( iph->protocol )
18034 +       {
18035 +               case IPPROTO_TCP:
18036 +               {
18037 +                       struct tcphdr *tcp;
18038 +
18039 +                       if( ntohs( iph->frag_off ) & IP_OFFSET )
18040 +                       {
18041 +                               DEBUGP( KERN_WARNING "ignoring fragment\n" );
18042 +                               break;
18043 +                       }
18044 +                       tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
18045 +                       event.source_port = ntohs( tcp->source );
18046 +                       event.dest_port = ntohs( tcp->dest );
18047 +/*
18048 + * Every packet should have a valid SEQ number so use this to
18049 + * generate an ACK number. This works along the formula:
18050 + * -- Start with the SEQ number
18051 + * -- For SYN or FIN add 1 to that number
18052 + * -- For data packet, add the data length to that number
18053 + */
18054 +
18055 +/*
18056 + * Data length requires a bit of fiddling around
18057 + */
18058 +                       {
18059 +                               unsigned int data_len;
18060 +                               if( tcp->syn || tcp->fin )
18061 +                               {
18062 +                                       data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
18063 +                               }
18064 +                               else
18065 +                               {
18066 +                                       data_len = ntohs( iph->tot_len );
18067 +                                       data_len -= 4 * iph->ihl;  /* Subtract away IP header & options */
18068 +                                       data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
18069 +                               }
18070 +                               
18071 +                               DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
18072 +
18073 +                               if( data_len ) /* Only track events that demand an ACK */
18074 +                               {
18075 +                                       event.expected_ACK = ntohl( tcp->seq ) + data_len;
18076 +                                       hash_insert( &connection, &event, direction );
18077 +                               }
18078 +                               else
18079 +                               {
18080 +                                       DEBUGP( "Don't bother to insert this, ACK not required\n" );
18081 +                               }
18082 +                       }
18083 +
18084 +                       if( tcp->ack )
18085 +                       {
18086 +/*
18087 + * Now we consider the matching of an existing event.
18088 + * Reverse the port numbers and change the ACK number to the actual ACK number
18089 + * Note that the direction is reversed because the reply will be going
18090 + * the opposite way to the request.
18091 + */
18092 +                               event.expected_ACK = ntohl( tcp->ack_seq );
18093 +                               event.dest_port = ntohs( tcp->source );
18094 +                               event.source_port = ntohs( tcp->dest );
18095 +                               request_complete( &connection, &event, !direction );
18096 +                       }
18097 +                       else
18098 +                       {
18099 +                               DEBUGP( "Don't bother to check this, ACK not valid\n" );
18100 +                       }
18101 +               }
18102 +       }
18103 +       return( IPT_CONTINUE );
18104 +}
18105 +
18106 +/*
18107 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
18108 + * return( 1 ) if the entry is suitable
18109 + *
18110 + * tablename     --  
18111 + *
18112 + * e             --  
18113 + *
18114 + * targinfo      --  Our private data block (handed to us from iptables plug-in)
18115 + *
18116 + * targinfosize  --  The size of our private data block
18117 + *
18118 + * hook_mask     --  
18119 + *
18120 + *
18121 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
18122 + * all possible flag combos make sense. All we check for is correct data size.
18123 + */
18124 +static int checkentry( const char *tablename,
18125 +                                          const struct ipt_entry *e,
18126 +                                          void *targinfo,
18127 +                                          unsigned int targinfosize,
18128 +                                          unsigned int hook_mask )
18129 +{
18130 +       const struct ipt_tcplag *el = targinfo;
18131 +
18132 +       if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
18133 +       {
18134 +               DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
18135 +                               IPT_ALIGN( sizeof( struct ipt_tcplag )));
18136 +               return( 0 );
18137 +       }
18138 +       if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
18139 +       return( 1 );
18140 +}
18141 +
18142 +static struct ipt_target reg =
18143 +{
18144 +       { 0, 0 },
18145 +       "TCPLAG",
18146 +       &target,
18147 +       &checkentry,
18148 +       0,
18149 +    THIS_MODULE
18150 +};
18151 +
18152 +static int __init init( void )
18153 +{
18154 +       if( ipt_register_target( &reg )) return( -EINVAL );
18155 +       hashsize = 123; /* should be configurable */
18156 +       hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
18157 +       memset( hashtab, 0, sizeof( void * ) * hashsize );
18158 +       return( 0 );
18159 +}
18160 +
18161 +/*
18162 + * This should not need locks (in theory)
18163 + * because it can only get punted after it is no longer
18164 + * chained into any of the netfilter lists.
18165 + */
18166 +static void __exit fini( void )
18167 +{
18168 +       int i;
18169 +
18170 +       ipt_unregister_target( &reg );
18171 +/*
18172 + * Put back kernel memory
18173 + */
18174 +       for( i = 0; i < hashsize; i++ )
18175 +       {
18176 +               tcplag_hash_T *p;
18177 +
18178 +               if(( p = hashtab[ i ]))
18179 +               {
18180 +                       tcplag_event_T *ev, *evn;
18181 +
18182 +                       hashtab[ i ] = 0;
18183 +                       for( ev = p->h_ACK_list; ev; ev = evn )
18184 +                       {
18185 +                               evn = ev->next;
18186 +                               kfree( ev );
18187 +                       }
18188 +                       for( ev = p->l_ACK_list; ev; ev = evn )
18189 +                       {
18190 +                               evn = ev->next;
18191 +                               kfree( ev );
18192 +                       }
18193 +                       kfree( p );
18194 +               }
18195 +       }
18196 +       kfree( hashtab );
18197 +}
18198 +
18199 +module_init(init);
18200 +module_exit(fini);
18201 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_time.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_time.c
18202 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_time.c        1970-01-01 01:00:00.000000000 +0100
18203 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_time.c    2003-12-10 23:13:47.815806976 +0100
18204 @@ -0,0 +1,185 @@
18205 +/*
18206 +  This is a module which is used for time matching
18207 +  It is using some modified code from dietlibc (localtime() function)
18208 +  that you can find at http://www.fefe.de/dietlibc/
18209 +  This file is distributed under the terms of the GNU General Public
18210 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
18211 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
18212 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
18213 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
18214 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
18215 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
18216 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
18217 +*/
18218 +
18219 +#include <linux/module.h>
18220 +#include <linux/skbuff.h>
18221 +#include <linux/netfilter_ipv4/ip_tables.h>
18222 +#include <linux/netfilter_ipv4/ipt_time.h>
18223 +#include <linux/time.h>
18224 +
18225 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
18226 +MODULE_DESCRIPTION("Match arrival timestamp");
18227 +MODULE_LICENSE("GPL");
18228 +
18229 +struct tm
18230 +{
18231 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
18232 +       int tm_min;                   /* Minutes.     [0-59] */
18233 +       int tm_hour;                  /* Hours.       [0-23] */
18234 +       int tm_mday;                  /* Day.         [1-31] */
18235 +       int tm_mon;                   /* Month.       [0-11] */
18236 +       int tm_year;                  /* Year - 1900.  */
18237 +       int tm_wday;                  /* Day of week. [0-6] */
18238 +       int tm_yday;                  /* Days in year.[0-365] */
18239 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
18240 +
18241 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
18242 +       const char *tm_zone;          /* we don't care, we count from GMT */
18243 +};
18244 +
18245 +void
18246 +localtime(const time_t *timepr, struct tm *r);
18247 +
18248 +static int
18249 +match(const struct sk_buff *skb,
18250 +      const struct net_device *in,
18251 +      const struct net_device *out,
18252 +      const void *matchinfo,
18253 +      int offset,
18254 +      const void *hdr,
18255 +      u_int16_t datalen,
18256 +      int *hotdrop)
18257 +{
18258 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
18259 +       struct tm currenttime;                          /* time human readable */
18260 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
18261 +       u_int16_t packet_time;
18262 +       struct timeval kerneltimeval;
18263 +       time_t packet_local_time;
18264 +
18265 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
18266 +       if (info->kerneltime)
18267 +       {
18268 +               do_gettimeofday(&kerneltimeval);
18269 +               packet_local_time = kerneltimeval.tv_sec;
18270 +       }
18271 +       else
18272 +               packet_local_time = skb->stamp.tv_sec;
18273 +
18274 +       /* Transform the timestamp of the packet, in a human readable form */
18275 +       localtime(&packet_local_time, &currenttime);
18276 +
18277 +       /* check if we match this timestamp, we start by the days... */
18278 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
18279 +               return 0; /* the day doesn't match */
18280 +
18281 +       /* ... check the time now */
18282 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
18283 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
18284 +               return 0;
18285 +
18286 +       /* here we match ! */
18287 +       return 1;
18288 +}
18289 +
18290 +static int
18291 +checkentry(const char *tablename,
18292 +           const struct ipt_ip *ip,
18293 +           void *matchinfo,
18294 +           unsigned int matchsize,
18295 +           unsigned int hook_mask)
18296 +{
18297 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
18298 +
18299 +       /* First, check that we are in the correct hook */
18300 +       /* PRE_ROUTING, LOCAL_IN or FROWARD */
18301 +       if (hook_mask
18302 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
18303 +       {
18304 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
18305 +               return 0;
18306 +       }
18307 +       /* we use the kerneltime if we are in forward or output */
18308 +       info->kerneltime = 1;
18309 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
18310 +               /* if not, we use the skb time */
18311 +               info->kerneltime = 0;
18312 +
18313 +       /* Check the size */
18314 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
18315 +               return 0;
18316 +       /* Now check the coherence of the data ... */
18317 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
18318 +           (info->time_stop  > 1439))
18319 +       {
18320 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
18321 +               return 0;
18322 +       }
18323 +
18324 +       return 1;
18325 +}
18326 +
18327 +static struct ipt_match time_match
18328 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
18329 +
18330 +static int __init init(void)
18331 +{
18332 +       printk("ipt_time loading\n");
18333 +       return ipt_register_match(&time_match);
18334 +}
18335 +
18336 +static void __exit fini(void)
18337 +{
18338 +       ipt_unregister_match(&time_match);
18339 +       printk("ipt_time unloaded\n");
18340 +}
18341 +
18342 +module_init(init);
18343 +module_exit(fini);
18344 +
18345 +
18346 +/* The part below is borowed and modified from dietlibc */
18347 +
18348 +/* seconds per day */
18349 +#define SPD 24*60*60
18350 +
18351 +void
18352 +localtime(const time_t *timepr, struct tm *r) {
18353 +       time_t i;
18354 +       time_t timep;
18355 +       extern struct timezone sys_tz;
18356 +       const unsigned int __spm[12] =
18357 +               { 0,
18358 +                 (31),
18359 +                 (31+28),
18360 +                 (31+28+31),
18361 +                 (31+28+31+30),
18362 +                 (31+28+31+30+31),
18363 +                 (31+28+31+30+31+30),
18364 +                 (31+28+31+30+31+30+31),
18365 +                 (31+28+31+30+31+30+31+31),
18366 +                 (31+28+31+30+31+30+31+31+30),
18367 +                 (31+28+31+30+31+30+31+31+30+31),
18368 +                 (31+28+31+30+31+30+31+31+30+31+30),
18369 +               };
18370 +       register time_t work;
18371 +
18372 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
18373 +       work=timep%(SPD);
18374 +       r->tm_sec=work%60; work/=60;
18375 +       r->tm_min=work%60; r->tm_hour=work/60;
18376 +       work=timep/(SPD);
18377 +       r->tm_wday=(4+work)%7;
18378 +       for (i=1970; ; ++i) {
18379 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
18380 +               if (work>k)
18381 +                       work-=k;
18382 +               else
18383 +                       break;
18384 +       }
18385 +       r->tm_year=i-1900;
18386 +       for (i=11; i && __spm[i]>work; --i) ;
18387 +       r->tm_mon=i;
18388 +       r->tm_mday=work-__spm[i]+1;
18389 +}
18390 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TRACE.c
18391 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TRACE.c       1970-01-01 01:00:00.000000000 +0100
18392 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TRACE.c   2003-12-10 23:13:24.663326688 +0100
18393 @@ -0,0 +1,67 @@
18394 +/* This is a module which is used for setting 
18395 + * the NFC_TRACE flag in the nfcache field of an skb. 
18396 + */
18397 +#include <linux/module.h>
18398 +#include <linux/skbuff.h>
18399 +
18400 +#include <linux/netfilter_ipv4/ip_tables.h>
18401 +
18402 +static unsigned int
18403 +target(struct sk_buff **pskb,
18404 +       const struct net_device *in,
18405 +       const struct net_device *out,
18406 +       unsigned int hooknum,
18407 +       const void *targinfo,
18408 +       void *userinfo)
18409 +{
18410 +       (*pskb)->nfcache |= NFC_TRACE;
18411 +       return IPT_CONTINUE;
18412 +}
18413 +
18414 +static int
18415 +checkentry(const char *tablename,
18416 +          const struct ipt_entry *e,
18417 +           void *targinfo,
18418 +           unsigned int targinfosize,
18419 +           unsigned int hook_mask)
18420 +{
18421 +       if (targinfosize != 0) {
18422 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
18423 +                      targinfosize);
18424 +               return 0;
18425 +       }
18426 +
18427 +       if (strcmp(tablename, "raw") != 0) {
18428 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
18429 +               return 0;
18430 +       }
18431 +
18432 +       return 1;
18433 +}
18434 +
18435 +static struct ipt_target ipt_trace_reg = { 
18436 +       .name           = "TRACE", 
18437 +       .target         = target, 
18438 +       .checkentry     = checkentry, 
18439 +       .destroy        = NULL, 
18440 +       .me             = THIS_MODULE,
18441 +};
18442 +
18443 +static int __init init(void)
18444 +{
18445 +       if (ipt_register_target(&ipt_trace_reg))
18446 +               return -EINVAL;
18447 +
18448 +       return 0;
18449 +}
18450 +
18451 +static void __exit fini(void)
18452 +{
18453 +       ipt_unregister_target(&ipt_trace_reg);
18454 +}
18455 +
18456 +module_init(init);
18457 +module_exit(fini);
18458 +MODULE_LICENSE("GPL");
18459 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
18460 +MODULE_DESCRIPTION("IPv4 TRACE target");
18461 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_TTL.c
18462 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
18463 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TTL.c     2003-12-10 23:13:48.933637040 +0100
18464 @@ -0,0 +1,110 @@
18465 +/* TTL modification target for IP tables
18466 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
18467 + *
18468 + * Version: 1.8
18469 + *
18470 + * This software is distributed under the terms of GNU GPL
18471 + */
18472 +
18473 +#include <linux/module.h>
18474 +#include <linux/skbuff.h>
18475 +#include <linux/ip.h>
18476 +#include <net/checksum.h>
18477 +
18478 +#include <linux/netfilter_ipv4/ip_tables.h>
18479 +#include <linux/netfilter_ipv4/ipt_TTL.h>
18480 +
18481 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
18482 +MODULE_DESCRIPTION("IP tables TTL modification module");
18483 +MODULE_LICENSE("GPL");
18484 +
18485 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
18486 +               const struct net_device *in, const struct net_device *out,
18487 +               const void *targinfo, void *userinfo)
18488 +{
18489 +       struct iphdr *iph = (*pskb)->nh.iph;
18490 +       const struct ipt_TTL_info *info = targinfo;
18491 +       u_int16_t diffs[2];
18492 +       int new_ttl;
18493 +                        
18494 +       switch (info->mode) {
18495 +               case IPT_TTL_SET:
18496 +                       new_ttl = info->ttl;
18497 +                       break;
18498 +               case IPT_TTL_INC:
18499 +                       new_ttl = iph->ttl + info->ttl;
18500 +                       if (new_ttl > 255)
18501 +                               new_ttl = 255;
18502 +                       break;
18503 +               case IPT_TTL_DEC:
18504 +                       new_ttl = iph->ttl + info->ttl;
18505 +                       if (new_ttl < 0)
18506 +                               new_ttl = 0;
18507 +                       break;
18508 +               default:
18509 +                       new_ttl = iph->ttl;
18510 +                       break;
18511 +       }
18512 +
18513 +       if (new_ttl != iph->ttl) {
18514 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
18515 +               iph->ttl = new_ttl;
18516 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
18517 +               iph->check = csum_fold(csum_partial((char *)diffs,
18518 +                                                   sizeof(diffs),
18519 +                                                   iph->check^0xFFFF));
18520 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
18521 +       }
18522 +
18523 +       return IPT_CONTINUE;
18524 +}
18525 +
18526 +static int ipt_ttl_checkentry(const char *tablename,
18527 +               const struct ipt_entry *e,
18528 +               void *targinfo,
18529 +               unsigned int targinfosize,
18530 +               unsigned int hook_mask)
18531 +{
18532 +       struct ipt_TTL_info *info = targinfo;
18533 +
18534 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
18535 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
18536 +                               targinfosize,
18537 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
18538 +               return 0;       
18539 +       }       
18540 +
18541 +       if (strcmp(tablename, "mangle")) {
18542 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
18543 +               return 0;
18544 +       }
18545 +
18546 +       if (info->mode > IPT_TTL_MAXMODE) {
18547 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
18548 +                       info->mode);
18549 +               return 0;
18550 +       }
18551 +
18552 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
18553 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
18554 +               return 0;
18555 +       }
18556 +       
18557 +       return 1;
18558 +}
18559 +
18560 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL", 
18561 +       ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
18562 +
18563 +static int __init init(void)
18564 +{
18565 +       return ipt_register_target(&ipt_TTL);
18566 +}
18567 +
18568 +static void __exit fini(void)
18569 +{
18570 +       ipt_unregister_target(&ipt_TTL);
18571 +}
18572 +
18573 +module_init(init);
18574 +module_exit(fini);
18575 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_u32.c
18576 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
18577 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_u32.c     2003-12-10 23:13:50.006473944 +0100
18578 @@ -0,0 +1,211 @@
18579 +/* Kernel module to match u32 packet content. */
18580 +
18581 +/* 
18582 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
18583 +have specified values.  The specification of what to extract is general 
18584 +enough to find data at given offsets from tcp headers or payloads.
18585 +
18586 + --u32 tests
18587 + The argument amounts to a program in a small language described below.
18588 + tests := location = value |  tests && location = value
18589 + value := range | value , range
18590 + range := number | number : number
18591 +  a single number, n, is interpreted the same as n:n
18592 +  n:m is interpreted as the range of numbers >=n and <=m
18593 + location := number | location operator number
18594 + operator := & | << | >> | @
18595 +
18596 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
18597 + membership operator and the value syntax describes a set.  The @ operator
18598 + is what allows moving to the next header and is described further below.
18599 +
18600 + *** Until I can find out how to avoid it, there are some artificial limits
18601 + on the size of the tests:
18602 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
18603 + - no more than 10 ranges (and 9 commas) per value
18604 + - no more than 10 numbers (and 9 operators) per location
18605 +
18606 + To describe the meaning of location, imagine the following machine that
18607 + interprets it.  There are three registers:
18608 +  A is of type char*, initially the address of the IP header
18609 +  B and C are unsigned 32 bit integers, initially zero
18610 +
18611 +  The instructions are:
18612 +   number      B = number;
18613 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
18614 +   &number     C = C&number
18615 +   <<number    C = C<<number
18616 +   >>number    C = C>>number
18617 +   @number     A = A+C; then do the instruction number
18618 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
18619 +  Otherwise the result of the computation is the final value of C.
18620 +
18621 + Whitespace is allowed but not required in the tests.
18622 + However the characters that do occur there are likely to require
18623 + shell quoting, so it's a good idea to enclose the arguments in quotes.
18624 +
18625 +Example:
18626 + match IP packets with total length >= 256
18627 + The IP header contains a total length field in bytes 2-3.
18628 + --u32 "0&0xFFFF=0x100:0xFFFF" 
18629 + read bytes 0-3
18630 + AND that with FFFF (giving bytes 2-3),
18631 + and test whether that's in the range [0x100:0xFFFF]
18632 +
18633 +Example: (more realistic, hence more complicated)
18634 + match icmp packets with icmp type 0
18635 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
18636 + --u32 "6&0xFF=1 && ...
18637 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
18638 + Next test that it's not a fragment.
18639 +  (If so it might be part of such a packet but we can't always tell.)
18640 +  n.b. This test is generally needed if you want to match anything
18641 +  beyond the IP header.
18642 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
18643 + packet (not a fragment).  Alternatively, you can allow first fragments
18644 + by only testing the last 5 bits of byte 6.
18645 + ... 4&0x3FFF=0 && ...
18646 + Last test: the first byte past the IP header (the type) is 0
18647 + This is where we have to use the @syntax.  The length of the IP header
18648 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
18649 + IP header itself.
18650 + ... 0>>22&0x3C@0>>24=0"
18651 + The first 0 means read bytes 0-3,
18652 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
18653 +   the first byte, so only 22 bits is four times that plus a few more bits.
18654 + &3C then eliminates the two extra bits on the right and the first four 
18655 + bits of the first byte.
18656 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
18657 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
18658 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
18659 + @ means to use this number as a new offset into the packet, and read
18660 + four bytes starting from there.  This is the first 4 bytes of the icmp
18661 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
18662 + the value 24 to the right to throw out all but the first byte and compare
18663 + the result with 0.
18664 +
18665 +Example: 
18666 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
18667 + First we test that the packet is a tcp packet (similar to icmp).
18668 + --u32 "6&0xFF=6 && ...
18669 + Next, test that it's not a fragment (same as above).
18670 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
18671 + 0>>22&3C as above computes the number of bytes in the IP header.
18672 + @ makes this the new offset into the packet, which is the start of the
18673 + tcp header.  The length of the tcp header (again in 32 bit words) is
18674 + the left half of byte 12 of the tcp header.  The 12>>26&3C
18675 + computes this length in bytes (similar to the IP header before).
18676 + @ makes this the new offset, which is the start of the tcp payload.
18677 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
18678 + result is any of 1, 2, 5 or 8
18679 +*/
18680 +
18681 +#include <linux/module.h>
18682 +#include <linux/skbuff.h>
18683 +
18684 +#include <linux/netfilter_ipv4/ipt_u32.h>
18685 +#include <linux/netfilter_ipv4/ip_tables.h>
18686 +
18687 +/* #include <asm-i386/timex.h> for timing */
18688 +
18689 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
18690 +MODULE_DESCRIPTION("IP tables u32 matching module");
18691 +MODULE_LICENSE("GPL");
18692 +
18693 +static int
18694 +match(const struct sk_buff *skb,
18695 +      const struct net_device *in,
18696 +      const struct net_device *out,
18697 +      const void *matchinfo,
18698 +      int offset,
18699 +      const void *hdr,
18700 +      u_int16_t datalen,
18701 +      int *hotdrop)
18702 +{
18703 +       const struct ipt_u32 *data = matchinfo;
18704 +       int testind, i;
18705 +       unsigned char* origbase = (char*)skb->nh.iph;
18706 +       unsigned char* base = origbase;
18707 +       unsigned char* head = skb->head;
18708 +       unsigned char* end = skb->end;
18709 +       int nnums, nvals;
18710 +       u_int32_t pos, val;
18711 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
18712 +          cycles1 = get_cycles(); */
18713 +
18714 +       for (testind=0; testind < data->ntests; testind++) {
18715 +               base = origbase; /* reset for each test */
18716 +               pos = data->tests[testind].location[0].number;
18717 +               if (base+pos+3 > end || base+pos < head) 
18718 +                       return 0;
18719 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
18720 +                       (base[pos+2]<<8) + base[pos+3];
18721 +               nnums = data->tests[testind].nnums;
18722 +               for (i=1; i < nnums; i++) {
18723 +                       u_int32_t number = data->tests[testind].location[i].number;
18724 +                       switch (data->tests[testind].location[i].nextop) {
18725 +                       case IPT_U32_AND: 
18726 +                               val = val & number; 
18727 +                               break;
18728 +                       case IPT_U32_LEFTSH: 
18729 +                               val = val << number;
18730 +                               break;
18731 +                       case IPT_U32_RIGHTSH: 
18732 +                               val = val >> number; 
18733 +                               break;
18734 +                       case IPT_U32_AT:
18735 +                               base = base + val;
18736 +                               pos = number;
18737 +                               if (base+pos+3 > end || base+pos < head) 
18738 +                                       return 0;
18739 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
18740 +                                       (base[pos+2]<<8) + base[pos+3];
18741 +                               break;
18742 +                       }
18743 +               }
18744 +               nvals = data->tests[testind].nvalues;
18745 +               for (i=0; i < nvals; i++) {
18746 +                       if ((data->tests[testind].value[i].min <= val) &&
18747 +                           (val <= data->tests[testind].value[i].max)) {
18748 +                               break;
18749 +                       }
18750 +               }
18751 +               if (i >= data->tests[testind].nvalues) {
18752 +                       /* cycles2 = get_cycles(); 
18753 +                          printk("failed %d in %d cycles\n", testind, 
18754 +                                 cycles2-cycles1); */
18755 +                       return 0;
18756 +               }
18757 +       }
18758 +       /* cycles2 = get_cycles();
18759 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
18760 +       return 1;
18761 +}
18762 +
18763 +static int
18764 +checkentry(const char *tablename,
18765 +           const struct ipt_ip *ip,
18766 +           void *matchinfo,
18767 +           unsigned int matchsize,
18768 +           unsigned int hook_mask)
18769 +{
18770 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
18771 +               return 0;
18772 +       return 1;
18773 +}
18774 +
18775 +static struct ipt_match u32_match
18776 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
18777 +
18778 +static int __init init(void)
18779 +{
18780 +       return ipt_register_match(&u32_match);
18781 +}
18782 +
18783 +static void __exit fini(void)
18784 +{
18785 +       ipt_unregister_match(&u32_match);
18786 +}
18787 +
18788 +module_init(init);
18789 +module_exit(fini);
18790 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ULOG.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_ULOG.c
18791 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ULOG.c        2003-11-26 21:43:34.000000000 +0100
18792 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ULOG.c    2003-12-10 23:13:22.346678872 +0100
18793 @@ -45,6 +45,7 @@
18794  #include <linux/netlink.h>
18795  #include <linux/netdevice.h>
18796  #include <linux/mm.h>
18797 +#include <linux/netfilter.h>
18798  #include <linux/netfilter_ipv4/ip_tables.h>
18799  #include <linux/netfilter_ipv4/ipt_ULOG.h>
18800  #include <linux/netfilter_ipv4/lockhelp.h>
18801 @@ -75,6 +76,10 @@
18802  MODULE_PARM(flushtimeout, "i");
18803  MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
18804  
18805 +static unsigned int nflog = 1;
18806 +MODULE_PARM(nflog, "i");
18807 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
18808 +
18809  /* global data structures */
18810  
18811  typedef struct {
18812 @@ -152,17 +157,17 @@
18813         return skb;
18814  }
18815  
18816 -static unsigned int ipt_ulog_target(struct sk_buff **pskb,
18817 -                                   const struct net_device *in,
18818 -                                   const struct net_device *out,
18819 -                                   unsigned int hooknum,
18820 -                                   const void *targinfo, void *userinfo)
18821 +static void ipt_ulog_packet(unsigned int hooknum,
18822 +                           const struct sk_buff *skb,
18823 +                           const struct net_device *in,
18824 +                           const struct net_device *out,
18825 +                           const struct ipt_ulog_info *loginfo,
18826 +                           const char *prefix)
18827  {
18828         ulog_buff_t *ub;
18829         ulog_packet_msg_t *pm;
18830         size_t size, copy_len;
18831         struct nlmsghdr *nlh;
18832 -       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
18833  
18834         /* ffs == find first bit set, necessary because userspace
18835          * is already shifting groupnumber, but we need unshifted.
18836 @@ -171,8 +176,8 @@
18837  
18838         /* calculate the size of the skb needed */
18839         if ((loginfo->copy_range == 0) ||
18840 -           (loginfo->copy_range > (*pskb)->len)) {
18841 -               copy_len = (*pskb)->len;
18842 +           (loginfo->copy_range > skb->len)) {
18843 +               copy_len = skb->len;
18844         } else {
18845                 copy_len = loginfo->copy_range;
18846         }
18847 @@ -209,19 +214,21 @@
18848  
18849         /* copy hook, prefix, timestamp, payload, etc. */
18850         pm->data_len = copy_len;
18851 -       pm->timestamp_sec = (*pskb)->stamp.tv_sec;
18852 -       pm->timestamp_usec = (*pskb)->stamp.tv_usec;
18853 -       pm->mark = (*pskb)->nfmark;
18854 +       pm->timestamp_sec = skb->stamp.tv_sec;
18855 +       pm->timestamp_usec = skb->stamp.tv_usec;
18856 +       pm->mark = skb->nfmark;
18857         pm->hook = hooknum;
18858 -       if (loginfo->prefix[0] != '\0')
18859 +       if (prefix != NULL)
18860 +               strncpy(pm->prefix, prefix, sizeof(pm->prefix));
18861 +       else if (loginfo->prefix[0] != '\0')
18862                 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
18863         else
18864                 *(pm->prefix) = '\0';
18865  
18866         if (in && in->hard_header_len > 0
18867 -           && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
18868 +           && skb->mac.raw != (void *) skb->nh.iph
18869             && in->hard_header_len <= ULOG_MAC_LEN) {
18870 -               memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
18871 +               memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
18872                 pm->mac_len = in->hard_header_len;
18873         } else
18874                 pm->mac_len = 0;
18875 @@ -236,8 +243,8 @@
18876         else
18877                 pm->outdev_name[0] = '\0';
18878  
18879 -       /* copy_len <= (*pskb)->len, so can't fail. */
18880 -       if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0)
18881 +       /* copy_len <= skb->len, so can't fail. */
18882 +       if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
18883                 BUG();
18884         
18885         /* check if we are building multi-part messages */
18886 @@ -261,8 +268,7 @@
18887  
18888         UNLOCK_BH(&ulog_lock);
18889  
18890 -       return IPT_CONTINUE;
18891 -
18892 +       return;
18893  
18894  nlmsg_failure:
18895         PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
18896 @@ -271,8 +277,35 @@
18897         PRINTR("ipt_ULOG: Error building netlink message\n");
18898  
18899         UNLOCK_BH(&ulog_lock);
18900 +}
18901 +
18902 +static unsigned int ipt_ulog_target(struct sk_buff **pskb,
18903 +                                   const struct net_device *in,
18904 +                                   const struct net_device *out,
18905 +                                   unsigned int hooknum,
18906 +                                   const void *targinfo, void *userinfo)
18907 +{
18908 +       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
18909  
18910 -       return IPT_CONTINUE;
18911 +       ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
18912
18913 +       return IPT_CONTINUE;
18914 +}
18915
18916 +static void ipt_logfn(unsigned int hooknum,
18917 +                     const struct sk_buff *skb,
18918 +                     const struct net_device *in,
18919 +                     const struct net_device *out,
18920 +                     const char *prefix)
18921 +{
18922 +       struct ipt_ulog_info loginfo = { 
18923 +               .nl_group = NFLOG_DEFAULT_NLGROUP,
18924 +               .copy_range = 0,
18925 +               .qthreshold = NFLOG_DEFAULT_QTHRESHOLD,
18926 +               .prefix = ""
18927 +       };
18928 +
18929 +       ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
18930  }
18931  
18932  static int ipt_ulog_checkentry(const char *tablename,
18933 @@ -337,6 +370,9 @@
18934                 return -EINVAL;
18935         }
18936  
18937 +       if (nflog)
18938 +               nf_log_register(PF_INET, &ipt_logfn);
18939 +       
18940         return 0;
18941  }
18942  
18943 @@ -347,6 +383,9 @@
18944  
18945         DEBUGP("ipt_ULOG: cleanup_module\n");
18946  
18947 +       if (nflog)
18948 +               nf_log_unregister(PF_INET, &ipt_logfn);
18949 +       
18950         ipt_unregister_target(&ipt_ulog_reg);
18951         sock_release(nflognl->sk_socket);
18952  
18953 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.0-test11/net/ipv4/netfilter/ipt_XOR.c
18954 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
18955 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_XOR.c     2003-12-10 23:14:18.224184200 +0100
18956 @@ -0,0 +1,107 @@
18957 +/* XOR target for IP tables
18958 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
18959 + * Based on ipt_TTL.c
18960 + *
18961 + * Version 1.0
18962 + *
18963 + * This software is distributed under the terms of GNU GPL
18964 + */
18965 +
18966 +#include <linux/module.h>
18967 +#include <linux/skbuff.h>
18968 +#include <linux/ip.h>
18969 +#include <linux/tcp.h>
18970 +#include <linux/udp.h>
18971 +
18972 +#include <linux/netfilter_ipv4/ip_tables.h>
18973 +#include <linux/netfilter_ipv4/ipt_XOR.h>
18974 +
18975 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
18976 +MODULE_DESCRIPTION("IP tables XOR module");
18977 +MODULE_LICENSE("GPL");
18978 +
18979 +static unsigned int ipt_xor_target(struct sk_buff **pskb, unsigned int hooknum, 
18980 +               const struct net_device *in, const struct net_device *out, 
18981 +               const void *targinfo, void *userinfo)
18982 +{
18983 +       struct ipt_XOR_info *info = (void *) targinfo;
18984 +       struct iphdr *iph = (*pskb)->nh.iph;
18985 +       struct tcphdr *tcph;
18986 +       struct udphdr *udph;
18987 +       int i, j, k;
18988 +  
18989 +       if (iph->protocol == IPPROTO_TCP) {
18990 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
18991 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
18992 +                       for (k=0; k<=info->block_size; k++) {
18993 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
18994 +                                               info->key[j];
18995 +                               i++;
18996 +                       }
18997 +                       j++;
18998 +                       if (info->key[j] == 0x00)
18999 +                               j = 0;
19000 +               }
19001 +       } else if (iph->protocol == IPPROTO_UDP) {
19002 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
19003 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
19004 +                       for (k=0; k<=info->block_size; k++) {
19005 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
19006 +                                               info->key[j];
19007 +                               i++;
19008 +                       }
19009 +                       j++;
19010 +                       if (info->key[j] == 0x00)
19011 +                               j = 0;
19012 +               }
19013 +       }
19014 +  
19015 +       return IPT_CONTINUE;
19016 +}
19017 +
19018 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
19019 +               void *targinfo, unsigned int targinfosize, 
19020 +               unsigned int hook_mask)
19021 +{
19022 +       struct ipt_XOR_info *info = targinfo;
19023 +
19024 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
19025 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
19026 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
19027 +       return 0;
19028 +       }       
19029 +
19030 +       if (strcmp(tablename, "mangle")) {
19031 +               printk(KERN_WARNING "XOR: can only be called from"
19032 +                               "\"mangle\" table, not \"%s\"\n", tablename);
19033 +               return 0; 
19034 +       }
19035 +
19036 +       if (!strcmp(info->key, "")) {
19037 +               printk(KERN_WARNING "XOR: You must specify a key");
19038 +               return 0;
19039 +       }
19040 +
19041 +       if (info->block_size == 0) {
19042 +               printk(KERN_WARNING "XOR: You must specify a block-size");
19043 +               return 0;
19044 +       }
19045 +
19046 +       return 1;
19047 +}
19048 +
19049 +static struct ipt_target ipt_XOR = { { NULL, NULL }, "XOR",
19050 +       ipt_xor_target, ipt_xor_checkentry, NULL, THIS_MODULE };
19051 +
19052 +static int __init init(void)
19053 +{
19054 +       return ipt_register_target(&ipt_XOR);
19055 +}
19056 +
19057 +static void __exit fini(void)
19058 +{
19059 +       ipt_unregister_target(&ipt_XOR);
19060 +}
19061 +
19062 +module_init(init);
19063 +module_exit(fini);
19064 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig linux-2.6.0-test11/net/ipv4/netfilter/Kconfig
19065 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig   2003-11-26 21:45:21.000000000 +0100
19066 +++ linux-2.6.0-test11/net/ipv4/netfilter/Kconfig       2003-12-10 23:13:25.745162224 +0100
19067 @@ -197,6 +197,15 @@
19068  
19069           To compile it as a module, choose M here.  If unsure, say N.
19070  
19071 +config IP_NF_MATCH_SCTP
19072 +       tristate "SCTP match support"
19073 +       depends on IP_NF_IPTABLES
19074 +       help
19075 +         This match allows iptables to match on the SCTP header.
19076 +
19077 +         If you want to compile it as a module, say M here and read
19078 +         <file:Documentation/modules.txt>. If unsure, say `N'.
19079 +
19080  config IP_NF_MATCH_LENGTH
19081         tristate "LENGTH match support"
19082         depends on IP_NF_IPTABLES
19083 @@ -527,6 +536,42 @@
19084  
19085           To compile it as a module, choose M here.  If unsure, say N.
19086  
19087 +config IP_NF_RAW
19088 +       tristate "Raw table"
19089 +       depends on IP_NF_IPTABLES
19090 +       help
19091 +         This option adds a `raw' table to iptables: see the man page for
19092 +         iptables(8).  This table is the very first in the netfilter
19093 +         framework and hooks in at the PREROUTING and OUTPUT chains.
19094 +         The TRACE and NOTRACK targets can be used in this table only.
19095 +
19096 +         To compile it as a module, choose M here.  If unsure, say N.
19097 +
19098 +config IP_NF_TARGET_TRACE
19099 +       tristate "TRACE target support"
19100 +       depends on IP_NF_RAW
19101 +       help
19102 +         The TRACE target allows packets to be traced as those matches
19103 +         any subsequent rule in any table/rule. The matched rule and
19104 +         the packet is logged with the prefix
19105 +         
19106 +         TRACE: tablename/chainname/rulenum
19107 +         
19108 +         if the ipt_LOG or ipt_ULOG targets are loaded in.
19109 +
19110 +         To compile it as a module, choose M here.  If unsure, say N.
19111 +
19112 +config IP_NF_TARGET_NOTRACK
19113 +       tristate "NOTRACK target support"
19114 +       depends on IP_NF_RAW
19115 +       help
19116 +         The NOTRACK target allows a select rule to specify which
19117 +         packets *not* to enter the conntrack/NAT subsystems
19118 +         with all the consequences (no ICMP error tracking,
19119 +         no protocol helpers for the selected packets).
19120 +
19121 +         To compile it as a module, choose M here.  If unsure, say N.
19122 +
19123  config IP_NF_ARPTABLES
19124         tristate "ARP tables support"
19125  
19126 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile linux-2.6.0-test11/net/ipv4/netfilter/Makefile
19127 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile  2003-11-26 21:43:25.000000000 +0100
19128 +++ linux-2.6.0-test11/net/ipv4/netfilter/Makefile      2003-12-10 23:24:46.646649464 +0100
19129 @@ -19,37 +19,91 @@
19130  # connection tracking
19131  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
19132  
19133 +# talk protocol support
19134 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
19135 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
19136 +
19137
19138 +# H.323 support
19139 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
19140 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
19141 +
19142 +
19143  # connection tracking helpers
19144 +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
19145 +
19146 +# rtsp protocol support
19147 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
19148 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
19149 +
19150 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
19151 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
19152  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
19153  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
19154  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
19155 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
19156 +
19157 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
19158 +
19159  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
19160  
19161  # NAT helpers 
19162 +obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
19163 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
19164  obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
19165  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
19166  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
19167  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
19168 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
19169 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
19170  
19171  # generic IP tables 
19172  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
19173  
19174 -# the three instances of ip_tables
19175 +# the four instances of ip_tables
19176  obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
19177  obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
19178  obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
19179 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
19180  
19181  # matches
19182 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
19183 +
19184 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
19185  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
19186  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
19187 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
19188 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
19189  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
19190 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
19191  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
19192  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
19193  
19194  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
19195  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
19196 +
19197 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
19198 +
19199  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
19200  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
19201 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
19202 +
19203 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
19204 +
19205 +
19206 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
19207 +
19208 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
19209 +
19210 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
19211 +
19212 +
19213 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
19214 +
19215 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
19216 +
19217 +
19218 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
19219  
19220  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
19221  
19222 @@ -59,10 +113,18 @@
19223  
19224  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
19225  
19226 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
19227 +
19228 +
19229  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
19230 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
19231  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
19232 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
19233 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
19234  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
19235  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
19236 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
19237 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
19238  
19239  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
19240  
19241 @@ -72,15 +134,28 @@
19242  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
19243  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
19244  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
19245 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
19246 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
19247  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
19248  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
19249 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
19250  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
19251  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
19252  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
19253  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
19254  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
19255 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
19256 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
19257 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
19258 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
19259 +
19260 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
19261 +
19262 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
19263  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
19264  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
19265 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
19266 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
19267  
19268  # generic ARP tables
19269  obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
19270 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.0-test11/net/ipv6/netfilter/ip6table_filter.c
19271 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_filter.c 2003-11-26 21:42:56.000000000 +0100
19272 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_filter.c     2003-12-10 23:13:24.668325928 +0100
19273 @@ -52,7 +52,7 @@
19274                 0,
19275                 sizeof(struct ip6t_entry),
19276                 sizeof(struct ip6t_standard),
19277 -               0, { 0, 0 }, { } },
19278 +               0, NULL, 0, { 0, 0 }, { } },
19279               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19280                 -NF_ACCEPT - 1 } },
19281             /* FORWARD */
19282 @@ -60,7 +60,7 @@
19283                 0,
19284                 sizeof(struct ip6t_entry),
19285                 sizeof(struct ip6t_standard),
19286 -               0, { 0, 0 }, { } },
19287 +               0, NULL, 0, { 0, 0 }, { } },
19288               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19289                 -NF_ACCEPT - 1 } },
19290             /* LOCAL_OUT */
19291 @@ -68,7 +68,7 @@
19292                 0,
19293                 sizeof(struct ip6t_entry),
19294                 sizeof(struct ip6t_standard),
19295 -               0, { 0, 0 }, { } },
19296 +               0, NULL, 0, { 0, 0 }, { } },
19297               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19298                 -NF_ACCEPT - 1 } }
19299      },
19300 @@ -77,7 +77,7 @@
19301         0,
19302         sizeof(struct ip6t_entry),
19303         sizeof(struct ip6t_error),
19304 -       0, { 0, 0 }, { } },
19305 +       0, NULL, 0, { 0, 0 }, { } },
19306        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19307           { } },
19308         "ERROR"
19309 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.0-test11/net/ipv6/netfilter/ip6table_mangle.c
19310 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_mangle.c 2003-11-26 21:43:36.000000000 +0100
19311 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_mangle.c     2003-12-10 23:13:24.668325928 +0100
19312 @@ -66,7 +66,7 @@
19313                 0,
19314                 sizeof(struct ip6t_entry),
19315                 sizeof(struct ip6t_standard),
19316 -               0, { 0, 0 }, { } },
19317 +               0, NULL, 0, { 0, 0 }, { } },
19318               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19319                 -NF_ACCEPT - 1 } },
19320             /* LOCAL_IN */
19321 @@ -74,7 +74,7 @@
19322                 0,
19323                 sizeof(struct ip6t_entry),
19324                 sizeof(struct ip6t_standard),
19325 -               0, { 0, 0 }, { } },
19326 +               0, NULL, 0, { 0, 0 }, { } },
19327               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19328                 -NF_ACCEPT - 1 } },
19329             /* FORWARD */
19330 @@ -82,7 +82,7 @@
19331                 0,
19332                 sizeof(struct ip6t_entry),
19333                 sizeof(struct ip6t_standard),
19334 -               0, { 0, 0 }, { } },
19335 +               0, NULL, 0, { 0, 0 }, { } },
19336               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19337                 -NF_ACCEPT - 1 } },
19338             /* LOCAL_OUT */
19339 @@ -90,7 +90,7 @@
19340                 0,
19341                 sizeof(struct ip6t_entry),
19342                 sizeof(struct ip6t_standard),
19343 -               0, { 0, 0 }, { } },
19344 +               0, NULL, 0, { 0, 0 }, { } },
19345               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19346                 -NF_ACCEPT - 1 } },
19347             /* POST_ROUTING */
19348 @@ -98,7 +98,7 @@
19349                 0,
19350                 sizeof(struct ip6t_entry),
19351                 sizeof(struct ip6t_standard),
19352 -               0, { 0, 0 }, { } },
19353 +               0, NULL, 0, { 0, 0 }, { } },
19354               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19355                 -NF_ACCEPT - 1 } }
19356      },
19357 @@ -107,7 +107,7 @@
19358         0,
19359         sizeof(struct ip6t_entry),
19360         sizeof(struct ip6t_error),
19361 -       0, { 0, 0 }, { } },
19362 +       0, NULL, 0, { 0, 0 }, { } },
19363        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19364           { } },
19365         "ERROR"
19366 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.0-test11/net/ipv6/netfilter/ip6table_raw.c
19367 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_raw.c    1970-01-01 01:00:00.000000000 +0100
19368 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_raw.c        2003-12-10 23:13:24.668325928 +0100
19369 @@ -0,0 +1,158 @@
19370 +/*
19371 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
19372 + *
19373 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
19374 + */
19375 +#include <linux/module.h>
19376 +#include <linux/netfilter_ipv6/ip6_tables.h>
19377 +
19378 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
19379 +
19380 +#if 0
19381 +#define DEBUGP(x, args...)     printk(KERN_DEBUG x, ## args)
19382 +#else
19383 +#define DEBUGP(x, args...)
19384 +#endif
19385 +
19386 +/* Standard entry. */
19387 +struct ip6t_standard
19388 +{
19389 +       struct ip6t_entry entry;
19390 +       struct ip6t_standard_target target;
19391 +};
19392 +
19393 +struct ip6t_error_target
19394 +{
19395 +       struct ip6t_entry_target target;
19396 +       char errorname[IP6T_FUNCTION_MAXNAMELEN];
19397 +};
19398 +
19399 +struct ip6t_error
19400 +{
19401 +       struct ip6t_entry entry;
19402 +       struct ip6t_error_target target;
19403 +};
19404 +
19405 +static struct
19406 +{
19407 +       struct ip6t_replace repl;
19408 +       struct ip6t_standard entries[2];
19409 +       struct ip6t_error term;
19410 +} initial_table __initdata 
19411 += { { "raw", RAW_VALID_HOOKS, 3,
19412 +      sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
19413 +      { [NF_IP6_PRE_ROUTING]   0,
19414 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
19415 +      { [NF_IP6_PRE_ROUTING]   0,
19416 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
19417 +      0, NULL, { } },
19418 +    {
19419 +           /* PRE_ROUTING */
19420 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19421 +               0,
19422 +               sizeof(struct ip6t_entry),
19423 +               sizeof(struct ip6t_standard),
19424 +               0, NULL, 0, { 0, 0 }, { } },
19425 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19426 +               -NF_ACCEPT - 1 } },
19427 +           /* LOCAL_OUT */
19428 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19429 +               0,
19430 +               sizeof(struct ip6t_entry),
19431 +               sizeof(struct ip6t_standard),
19432 +               0, NULL, 0, { 0, 0 }, { } },
19433 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19434 +               -NF_ACCEPT - 1 } },
19435 +    },
19436 +    /* ERROR */
19437 +    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19438 +       0,
19439 +       sizeof(struct ip6t_entry),
19440 +       sizeof(struct ip6t_error),
19441 +       0, NULL, 0, { 0, 0 }, { } },
19442 +      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19443 +         { } },
19444 +       "ERROR"
19445 +      }
19446 +    }
19447 +};
19448 +
19449 +static struct ip6t_table packet_raw = { 
19450 +       .name = "raw",
19451 +       .table = &initial_table.repl,
19452 +       .valid_hooks = RAW_VALID_HOOKS,
19453 +       .lock = RW_LOCK_UNLOCKED,
19454 +       .me = THIS_MODULE
19455 +};
19456 +
19457 +/* The work comes in here from netfilter.c. */
19458 +static unsigned int
19459 +ip6t_hook(unsigned int hook,
19460 +        struct sk_buff **pskb,
19461 +        const struct net_device *in,
19462 +        const struct net_device *out,
19463 +        int (*okfn)(struct sk_buff *))
19464 +{
19465 +       return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
19466 +}
19467 +
19468 +static struct nf_hook_ops ip6t_ops[] = { 
19469 +       { /* PRE_ROUTING */
19470 +               .hook = ip6t_hook,
19471 +               .owner = THIS_MODULE,
19472 +               .pf = PF_INET6,
19473 +               .hooknum = NF_IP6_PRE_ROUTING,
19474 +               .priority = NF_IP6_PRI_FIRST,
19475 +       },
19476 +       { /* LOCAL_OUT */
19477 +               .hook = ip6t_hook, 
19478 +               .owner = THIS_MODULE,
19479 +               .pf = PF_INET6, 
19480 +               .hooknum = NF_IP6_LOCAL_OUT,
19481 +               .priority = NF_IP6_PRI_FIRST,
19482 +       },
19483 +};
19484 +
19485 +static int __init init(void)
19486 +{
19487 +       int ret;
19488 +
19489 +       /* Register table */
19490 +       ret = ip6t_register_table(&packet_raw);
19491 +       if (ret < 0)
19492 +               return ret;
19493 +
19494 +       /* Register hooks */
19495 +       ret = nf_register_hook(&ip6t_ops[0]);
19496 +       if (ret < 0)
19497 +               goto cleanup_table;
19498 +
19499 +       ret = nf_register_hook(&ip6t_ops[1]);
19500 +       if (ret < 0)
19501 +               goto cleanup_hook0;
19502 +
19503 +       return ret;
19504 +
19505 + cleanup_hook0:
19506 +       nf_unregister_hook(&ip6t_ops[0]);
19507 + cleanup_table:
19508 +       ip6t_unregister_table(&packet_raw);
19509 +
19510 +       return ret;
19511 +}
19512 +
19513 +static void __exit fini(void)
19514 +{
19515 +       unsigned int i;
19516 +
19517 +       for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
19518 +               nf_unregister_hook(&ip6t_ops[i]);
19519 +
19520 +       ip6t_unregister_table(&packet_raw);
19521 +}
19522 +
19523 +module_init(init);
19524 +module_exit(fini);
19525 +MODULE_LICENSE("GPL");
19526 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19527 +MODULE_DESCRIPTION("IPv6 raw table");
19528 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.0-test11/net/ipv6/netfilter/ip6_tables.c
19529 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6_tables.c      2003-11-26 21:45:30.000000000 +0100
19530 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6_tables.c  2003-12-10 23:13:24.667326080 +0100
19531 @@ -12,6 +12,7 @@
19532   */
19533  #include <linux/config.h>
19534  #include <linux/skbuff.h>
19535 +#include <linux/socket.h>
19536  #include <linux/kmod.h>
19537  #include <linux/vmalloc.h>
19538  #include <linux/netdevice.h>
19539 @@ -24,8 +25,17 @@
19540  #include <asm/semaphore.h>
19541  #include <linux/proc_fs.h>
19542  
19543 +#include <linux/netfilter.h>
19544  #include <linux/netfilter_ipv6/ip6_tables.h>
19545  
19546 +static const char *hook6names[] = { 
19547 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
19548 +       [NF_IP6_LOCAL_IN] "INPUT",
19549 +       [NF_IP6_FORWARD] "FORWARD",
19550 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
19551 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
19552 +};
19553 +
19554  MODULE_LICENSE("GPL");
19555  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19556  MODULE_DESCRIPTION("IPv6 packet filter");
19557 @@ -403,6 +413,12 @@
19558  
19559                         t = ip6t_get_target(e);
19560                         IP_NF_ASSERT(t->u.kernel.target);
19561 +
19562 +                       /* The packet traced and the rule isn't an unconditional return/END. */
19563 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
19564 +                               nf_log_packet(AF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
19565 +                                                 table->name, e->chainname, e->rulenum);
19566 +                       }
19567                         /* Standard target? */
19568                         if (!t->u.kernel.target->target) {
19569                                 int v;
19570 @@ -556,6 +572,29 @@
19571         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
19572  }
19573  
19574 +static inline int
19575 +find_error_target(struct ip6t_entry *s, 
19576 +                 struct ip6t_entry *e,
19577 +                 char **chainname)
19578 +{
19579 +       struct ip6t_entry_target *t;
19580 +       static struct ip6t_entry *found = NULL;
19581 +
19582 +       if (s == e) {
19583 +               if (!found)
19584 +                       return 0;
19585 +               t = ip6t_get_target(found);
19586 +               if (strcmp(t->u.user.name, 
19587 +                          IP6T_ERROR_TARGET) == 0) {
19588 +                       *chainname = t->data;
19589 +                       return 1;
19590 +               }
19591 +       } else
19592 +               found = s;
19593 +       
19594 +       return 0;
19595 +}
19596 +
19597  /* All zeroes == unconditional rule. */
19598  static inline int
19599  unconditional(const struct ip6t_ip6 *ipv6)
19600 @@ -575,6 +614,8 @@
19601  mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
19602  {
19603         unsigned int hook;
19604 +       char *chainname = NULL;
19605 +       u_int32_t rulenum;
19606  
19607         /* No recursion; use packet counter to save back ptrs (reset
19608            to 0 as we leave), and comefrom to save source hook bitmask */
19609 @@ -588,6 +629,8 @@
19610  
19611                 /* Set initial back pointer. */
19612                 e->counters.pcnt = pos;
19613 +               rulenum = 1;
19614 +               chainname = (char *) hook6names[hook];
19615  
19616                 for (;;) {
19617                         struct ip6t_standard_target *t
19618 @@ -600,6 +643,8 @@
19619                         }
19620                         e->comefrom
19621                                 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
19622 +                       e->rulenum = rulenum++;
19623 +                       e->chainname = chainname;
19624  
19625                         /* Unconditional return/END. */
19626                         if (e->target_offset == sizeof(struct ip6t_entry)
19627 @@ -609,6 +654,10 @@
19628                             && unconditional(&e->ipv6)) {
19629                                 unsigned int oldpos, size;
19630  
19631 +                               /* Set unconditional rulenum to zero. */
19632 +                               e->rulenum = 0;
19633 +                               e->counters.bcnt = 0;
19634 +
19635                                 /* Return: backtrack through the last
19636                                    big jump. */
19637                                 do {
19638 @@ -634,6 +683,11 @@
19639                                                 (newinfo->entries + pos);
19640                                 } while (oldpos == pos + e->next_offset);
19641  
19642 +                               /* Restore chainname, rulenum. */
19643 +                               chainname = e->chainname;
19644 +                               rulenum = e->counters.bcnt;
19645 +                               e->counters.bcnt = 0;
19646 +
19647                                 /* Move along one */
19648                                 size = e->next_offset;
19649                                 e = (struct ip6t_entry *)
19650 @@ -649,6 +703,17 @@
19651                                         /* This a jump; chase it. */
19652                                         duprintf("Jump rule %u -> %u\n",
19653                                                  pos, newpos);
19654 +                                       e->counters.bcnt = rulenum++;
19655 +                                       rulenum = 1;
19656 +                                       e = (struct ip6t_entry *)
19657 +                                               (newinfo->entries + newpos);
19658 +                                       if (IP6T_ENTRY_ITERATE(newinfo->entries,
19659 +                                                              newinfo->size,
19660 +                                                              find_error_target,
19661 +                                                              e, &chainname) == 0) {
19662 +                                               printk("ip6_tables: table screwed up!\n");
19663 +                                               return 0;
19664 +                                       }
19665                                 } else {
19666                                         /* ... this is a fallthru */
19667                                         newpos = pos + e->next_offset;
19668 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_condition.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_condition.c
19669 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_condition.c  1970-01-01 01:00:00.000000000 +0100
19670 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_condition.c      2003-12-10 23:13:52.256131944 +0100
19671 @@ -0,0 +1,254 @@
19672 +/*-------------------------------------------*\
19673 +|    Netfilter Condition Module for IPv6      |
19674 +|                                             |
19675 +|  Description: This module allows firewall   |
19676 +|    rules to match using condition variables |
19677 +|    stored in /proc files.                   |
19678 +|                                             |
19679 +|  Author: Stephane Ouellette     2003-02-10  |
19680 +|          <ouellettes@videotron.ca>          |
19681 +|                                             |
19682 +|  This software is distributed under the     |
19683 +|  terms of the GNU GPL.                      |
19684 +\*-------------------------------------------*/
19685 +
19686 +#include<linux/module.h>
19687 +#include<linux/proc_fs.h>
19688 +#include<linux/spinlock.h>
19689 +#include<linux/string.h>
19690 +#include<asm/atomic.h>
19691 +#include<linux/netfilter_ipv6/ip6_tables.h>
19692 +#include<linux/netfilter_ipv6/ip6t_condition.h>
19693 +
19694 +
19695 +#ifndef CONFIG_PROC_FS
19696 +#error  "Proc file system support is required for this module"
19697 +#endif
19698 +
19699 +
19700 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
19701 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
19702 +MODULE_LICENSE("GPL");
19703 +
19704 +
19705 +struct condition_variable {
19706 +       struct condition_variable *next;
19707 +       struct proc_dir_entry *status_proc;
19708 +       atomic_t refcount;
19709 +        int enabled; /* TRUE == 1, FALSE == 0 */
19710 +};
19711 +
19712 +
19713 +static rwlock_t list_lock;
19714 +static struct condition_variable *head = NULL;
19715 +static struct proc_dir_entry *proc_net_condition = NULL;
19716 +
19717 +
19718 +static int
19719 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
19720 +                       int length, int *eof, void *data)
19721 +{
19722 +       struct condition_variable *var =
19723 +           (struct condition_variable *) data;
19724 +
19725 +       if (offset == 0) {
19726 +               *start = buffer;
19727 +               buffer[0] = (var->enabled) ? '1' : '0';
19728 +               buffer[1] = '\n';
19729 +               return 2;
19730 +       }
19731 +
19732 +       *eof = 1;
19733 +       return 0;
19734 +}
19735 +
19736 +
19737 +static int
19738 +ipt_condition_write_info(struct file *file, const char *buffer,
19739 +                        unsigned long length, void *data)
19740 +{
19741 +       struct condition_variable *var =
19742 +           (struct condition_variable *) data;
19743 +
19744 +       if (length) {
19745 +               /* Match only on the first character */
19746 +               switch (buffer[0]) {
19747 +               case '0':
19748 +                       var->enabled = 0;
19749 +                       break;
19750 +               case '1':
19751 +                       var->enabled = 1;
19752 +               }
19753 +       }
19754 +
19755 +       return (int) length;
19756 +}
19757 +
19758 +
19759 +static int
19760 +match(const struct sk_buff *skb, const struct net_device *in,
19761 +      const struct net_device *out, const void *matchinfo, int offset,
19762 +      const void *hdr, u_int16_t datalen, int *hotdrop)
19763 +{
19764 +       const struct condition6_info *info =
19765 +           (const struct condition6_info *) matchinfo;
19766 +       struct condition_variable *var;
19767 +       int condition_status = 0;
19768 +
19769 +       read_lock(&list_lock);
19770 +
19771 +       for (var = head; var; var = var->next) {
19772 +               if (strcmp(info->name, var->status_proc->name) == 0) {
19773 +                       condition_status = var->enabled;
19774 +                       break;
19775 +               }
19776 +       }
19777 +
19778 +       read_unlock(&list_lock);
19779 +
19780 +       return condition_status ^ info->invert;
19781 +}
19782 +
19783 +
19784 +
19785 +static int
19786 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
19787 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
19788 +{
19789 +       struct condition6_info *info =
19790 +           (struct condition6_info *) matchinfo;
19791 +       struct condition_variable *var, *newvar;
19792 +
19793 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19794 +               return 0;
19795 +
19796 +       /* The first step is to check if the condition variable already exists. */
19797 +       /* Here, a read lock is sufficient because we won't change the list */
19798 +       read_lock(&list_lock);
19799 +
19800 +       for (var = head; var; var = var->next) {
19801 +               if (strcmp(info->name, var->status_proc->name) == 0) {
19802 +                       atomic_inc(&var->refcount);
19803 +                       read_unlock(&list_lock);
19804 +                       return 1;
19805 +               }
19806 +       }
19807 +
19808 +       read_unlock(&list_lock);
19809 +
19810 +       /* At this point, we need to allocate a new condition variable */
19811 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
19812 +
19813 +       if (!newvar)
19814 +               return -ENOMEM;
19815 +
19816 +       /* Create the condition variable's proc file entry */
19817 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
19818 +
19819 +       if (!newvar->status_proc) {
19820 +         /*
19821 +          * There are two possibilities:
19822 +          *  1- Another condition variable with the same name has been created, which is valid.
19823 +          *  2- There was a memory allocation error.
19824 +          */
19825 +               kfree(newvar);
19826 +               read_lock(&list_lock);
19827 +
19828 +               for (var = head; var; var = var->next) {
19829 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
19830 +                               atomic_inc(&var->refcount);
19831 +                               read_unlock(&list_lock);
19832 +                               return 1;
19833 +                       }
19834 +               }
19835 +
19836 +               read_unlock(&list_lock);
19837 +               return -ENOMEM;
19838 +       }
19839 +
19840 +       atomic_set(&newvar->refcount, 1);
19841 +       newvar->enabled = 0;
19842 +       newvar->status_proc->owner = THIS_MODULE;
19843 +       newvar->status_proc->data = newvar;
19844 +       wmb();
19845 +       newvar->status_proc->read_proc = ipt_condition_read_info;
19846 +       newvar->status_proc->write_proc = ipt_condition_write_info;
19847 +
19848 +       write_lock(&list_lock);
19849 +
19850 +       newvar->next = head;
19851 +       head = newvar;
19852 +
19853 +       write_unlock(&list_lock);
19854 +
19855 +       return 1;
19856 +}
19857 +
19858 +
19859 +static void
19860 +destroy(void *matchinfo, unsigned int matchsize)
19861 +{
19862 +       struct condition6_info *info =
19863 +           (struct condition6_info *) matchinfo;
19864 +       struct condition_variable *var, *prev = NULL;
19865 +
19866 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19867 +               return;
19868 +
19869 +       write_lock(&list_lock);
19870 +
19871 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
19872 +            prev = var, var = var->next);
19873 +
19874 +       if (var && atomic_dec_and_test(&var->refcount)) {
19875 +               if (prev)
19876 +                       prev->next = var->next;
19877 +               else
19878 +                       head = var->next;
19879 +
19880 +               write_unlock(&list_lock);
19881 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
19882 +               kfree(var);
19883 +       } else
19884 +               write_unlock(&list_lock);
19885 +}
19886 +
19887 +
19888 +static struct ip6t_match condition_match = {
19889 +       .name = "condition",
19890 +       .match = &match,
19891 +       .checkentry = &checkentry,
19892 +       .destroy = &destroy,
19893 +       .me = THIS_MODULE
19894 +};
19895 +
19896 +
19897 +static int __init
19898 +init(void)
19899 +{
19900 +       int errorcode;
19901 +
19902 +       rwlock_init(&list_lock);
19903 +       proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
19904 +
19905 +       if (proc_net_condition) {
19906 +               errorcode = ipt_register_match(&condition_match);
19907 +
19908 +               if (errorcode)
19909 +                       remove_proc_entry("ip6t_condition", proc_net);
19910 +       } else
19911 +               errorcode = -EACCES;
19912 +
19913 +       return errorcode;
19914 +}
19915 +
19916 +
19917 +static void __exit
19918 +fini(void)
19919 +{
19920 +       ipt_unregister_match(&condition_match);
19921 +       remove_proc_entry("ip6t_condition", proc_net);
19922 +}
19923 +
19924 +module_init(init);
19925 +module_exit(fini);
19926 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_fuzzy.c
19927 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_fuzzy.c      1970-01-01 01:00:00.000000000 +0100
19928 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_fuzzy.c  2003-12-10 23:13:28.963672936 +0100
19929 @@ -0,0 +1,189 @@
19930 +/*
19931 + * This module implements a simple TSK FLC
19932 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
19933 + * to limit , in an adaptive and flexible way , the packet rate crossing
19934 + * a given stream . It serves as an initial and very simple (but effective)
19935 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
19936 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
19937 + * into our code in a precise , adaptive and efficient manner.
19938 + *  The goal is very similar to that of "limit" match , but using techniques of
19939 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
19940 + * avoiding over and undershoots - and stuff like that .
19941 + *
19942 + *
19943 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
19944 + * 2002-08-17  : Changed to eliminate floating point operations .
19945 + * 2002-08-23  : Coding style changes .
19946 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
19947 + */
19948 +
19949 +#include <linux/module.h>
19950 +#include <linux/skbuff.h>
19951 +#include <linux/ipv6.h>
19952 +#include <linux/random.h>
19953 +#include <net/tcp.h>
19954 +#include <linux/spinlock.h>
19955 +#include <linux/netfilter_ipv6/ip6_tables.h>
19956 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
19957 +
19958 +/*
19959 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
19960 + Expressed in percentage
19961 +*/
19962 +
19963 +#define PAR_LOW                1/100
19964 +#define PAR_HIGH       1
19965 +
19966 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
19967 +
19968 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
19969 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
19970 +MODULE_LICENSE("GPL");
19971 +
19972 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19973 +{
19974 +       if (tx >= maxi) return 100;
19975 +
19976 +       if (tx <= mini) return 0;
19977 +
19978 +       return ((100 * (tx-mini)) / (maxi-mini));
19979 +}
19980 +
19981 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19982 +{
19983 +       if (tx <= mini) return 100;
19984 +
19985 +       if (tx >= maxi) return 0;
19986 +
19987 +       return ((100 * (maxi - tx)) / (maxi - mini));
19988 +
19989 +}
19990 +
19991 +static int
19992 +ip6t_fuzzy_match(const struct sk_buff *pskb,
19993 +              const struct net_device *in,
19994 +              const struct net_device *out,
19995 +              const void *matchinfo,
19996 +              int offset,
19997 +              const void *hdr,
19998 +              u_int16_t datalen,
19999 +              int *hotdrop)
20000 +{
20001 +       /* From userspace */
20002 +
20003 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
20004 +
20005 +       u_int8_t random_number;
20006 +       unsigned long amount;
20007 +       u_int8_t howhigh, howlow;
20008 +
20009 +
20010 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
20011 +
20012 +       info->bytes_total += pskb->len;
20013 +       info->packets_total++;
20014 +
20015 +       info->present_time = jiffies;
20016 +
20017 +       if (info->present_time >= info->previous_time)
20018 +               amount = info->present_time - info->previous_time;
20019 +       else {
20020 +               /* There was a transition : I choose to re-sample
20021 +                  and keep the old acceptance rate...
20022 +               */
20023 +
20024 +               amount = 0;
20025 +               info->previous_time = info->present_time;
20026 +               info->bytes_total = info->packets_total = 0;
20027 +            };
20028 +
20029 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
20030 +
20031 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
20032 +                                       / amount);
20033 +
20034 +               info->previous_time = info->present_time;
20035 +               info->bytes_total = info->packets_total = 0;
20036 +
20037 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
20038 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
20039 +
20040 +               info->acceptance_rate = (u_int8_t) \
20041 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
20042 +
20043 +       /* In fact, the above defuzzification would require a denominator
20044 +        * proportional to (howhigh+howlow) but, in this particular case,
20045 +        * that expression is constant.
20046 +        * An imediate consequence is that it is not necessary to call
20047 +        * both mf_high and mf_low - but to keep things understandable,
20048 +        * I did so.
20049 +        */
20050 +
20051 +       }
20052 +
20053 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
20054 +
20055 +
20056 +       if (info->acceptance_rate < 100)
20057 +       {
20058 +               get_random_bytes((void *)(&random_number), 1);
20059 +
20060 +               /*  If within the acceptance , it can pass => don't match */
20061 +               if (random_number <= (255 * info->acceptance_rate) / 100)
20062 +                       return 0;
20063 +               else
20064 +                       return 1; /* It can't pass (It matches) */
20065 +       };
20066 +
20067 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
20068 +
20069 +}
20070 +
20071 +static int
20072 +ip6t_fuzzy_checkentry(const char *tablename,
20073 +                  const struct ip6t_ip6 *ip,
20074 +                  void *matchinfo,
20075 +                  unsigned int matchsize,
20076 +                  unsigned int hook_mask)
20077 +{
20078 +
20079 +       const struct ip6t_fuzzy_info *info = matchinfo;
20080 +
20081 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
20082 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
20083 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
20084 +               return 0;
20085 +       }
20086 +
20087 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
20088 +        || (info->minimum_rate >= info->maximum_rate)) {
20089 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
20090 +               return 0;
20091 +       }
20092 +
20093 +       return 1;
20094 +}
20095 +
20096 +static struct ip6t_match ip6t_fuzzy_reg = {
20097 +       {NULL, NULL},
20098 +       "fuzzy",
20099 +       ip6t_fuzzy_match,
20100 +       ip6t_fuzzy_checkentry,
20101 +       NULL,
20102 +       THIS_MODULE };
20103 +
20104 +static int __init init(void)
20105 +{
20106 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
20107 +               return -EINVAL;
20108 +
20109 +       return 0;
20110 +}
20111 +
20112 +static void __exit fini(void)
20113 +{
20114 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
20115 +}
20116 +
20117 +module_init(init);
20118 +module_exit(fini);
20119 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_HL.c
20120 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
20121 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_HL.c     2003-12-10 23:13:31.108346896 +0100
20122 @@ -0,0 +1,105 @@
20123 +/* 
20124 + * Hop Limit modification target for ip6tables
20125 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
20126 + * Based on HW's TTL module
20127 + *
20128 + * This software is distributed under the terms of GNU GPL
20129 + */
20130 +
20131 +#include <linux/module.h>
20132 +#include <linux/skbuff.h>
20133 +#include <linux/ip.h>
20134 +
20135 +#include <linux/netfilter_ipv6/ip6_tables.h>
20136 +#include <linux/netfilter_ipv6/ip6t_HL.h>
20137 +
20138 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
20139 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
20140 +MODULE_LICENSE("GPL");
20141 +
20142 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
20143 +               const struct net_device *in, const struct net_device *out,
20144 +               const void *targinfo, void *userinfo)
20145 +{
20146 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
20147 +       const struct ip6t_HL_info *info = targinfo;
20148 +       u_int16_t diffs[2];
20149 +       int new_hl;
20150 +                        
20151 +       switch (info->mode) {
20152 +               case IP6T_HL_SET:
20153 +                       new_hl = info->hop_limit;
20154 +                       break;
20155 +               case IP6T_HL_INC:
20156 +                       new_hl = ip6h->hop_limit + info->hop_limit;
20157 +                       if (new_hl > 255)
20158 +                               new_hl = 255;
20159 +                       break;
20160 +               case IP6T_HL_DEC:
20161 +                       new_hl = ip6h->hop_limit + info->hop_limit;
20162 +                       if (new_hl < 0)
20163 +                               new_hl = 0;
20164 +                       break;
20165 +               default:
20166 +                       new_hl = ip6h->hop_limit;
20167 +                       break;
20168 +       }
20169 +
20170 +       if (new_hl != ip6h->hop_limit) {
20171 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
20172 +               ip6h->hop_limit = new_hl;
20173 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
20174 +       }
20175 +
20176 +       return IP6T_CONTINUE;
20177 +}
20178 +
20179 +static int ip6t_hl_checkentry(const char *tablename,
20180 +               const struct ip6t_entry *e,
20181 +               void *targinfo,
20182 +               unsigned int targinfosize,
20183 +               unsigned int hook_mask)
20184 +{
20185 +       struct ip6t_HL_info *info = targinfo;
20186 +
20187 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
20188 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
20189 +                               targinfosize,
20190 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
20191 +               return 0;       
20192 +       }       
20193 +
20194 +       if (strcmp(tablename, "mangle")) {
20195 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
20196 +               return 0;
20197 +       }
20198 +
20199 +       if (info->mode > IP6T_HL_MAXMODE) {
20200 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
20201 +                       info->mode);
20202 +               return 0;
20203 +       }
20204 +
20205 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
20206 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
20207 +               return 0;
20208 +       }
20209 +       
20210 +       return 1;
20211 +}
20212 +
20213 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
20214 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
20215 +
20216 +static int __init init(void)
20217 +{
20218 +       return ip6t_register_target(&ip6t_HL);
20219 +}
20220 +
20221 +static void __exit fini(void)
20222 +{
20223 +       ip6t_unregister_target(&ip6t_HL);
20224 +}
20225 +
20226 +module_init(init);
20227 +module_exit(fini);
20228 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_LOG.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_LOG.c
20229 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_LOG.c        2003-11-26 21:43:30.000000000 +0100
20230 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_LOG.c    2003-12-10 23:13:22.347678720 +0100
20231 @@ -3,18 +3,24 @@
20232   */
20233  #include <linux/module.h>
20234  #include <linux/skbuff.h>
20235 +#include <linux/socket.h>
20236  #include <linux/ip.h>
20237  #include <linux/spinlock.h>
20238  #include <linux/icmpv6.h>
20239  #include <net/udp.h>
20240  #include <net/tcp.h>
20241  #include <net/ipv6.h>
20242 +#include <linux/netfilter.h>
20243  #include <linux/netfilter_ipv6/ip6_tables.h>
20244  
20245  MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
20246  MODULE_DESCRIPTION("IP6 tables LOG target module");
20247  MODULE_LICENSE("GPL");
20248  
20249 +static unsigned int nflog = 1;
20250 +MODULE_PARM(nflog, "i");
20251 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
20252 +
20253  struct in_device;
20254  #include <net/route.h>
20255  #include <linux/netfilter_ipv6/ip6t_LOG.h>
20256 @@ -256,40 +262,38 @@
20257         }
20258  }
20259  
20260 -static unsigned int
20261 -ip6t_log_target(struct sk_buff **pskb,
20262 -               unsigned int hooknum,
20263 -               const struct net_device *in,
20264 -               const struct net_device *out,
20265 -               const void *targinfo,
20266 -               void *userinfo)
20267 +static void
20268 +ip6t_log_packet(unsigned int hooknum,
20269 +               const struct sk_buff *skb,
20270 +               const struct net_device *in,
20271 +               const struct net_device *out,
20272 +               const struct ip6t_log_info *loginfo,
20273 +               const char *level_string,
20274 +               const char *prefix)
20275  {
20276 -       struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
20277 -       const struct ip6t_log_info *loginfo = targinfo;
20278 -       char level_string[4] = "< >";
20279 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
20280  
20281 -       level_string[1] = '0' + (loginfo->level % 8);
20282         spin_lock_bh(&log_lock);
20283         printk(level_string);
20284         printk("%sIN=%s OUT=%s ",
20285 -               loginfo->prefix,
20286 +               prefix == NULL ? loginfo->prefix : prefix,
20287                 in ? in->name : "",
20288                 out ? out->name : "");
20289         if (in && !out) {
20290                 /* MAC logging for input chain only. */
20291                 printk("MAC=");
20292 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
20293 -                       if ((*pskb)->dev->type != ARPHRD_SIT){
20294 +               if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
20295 +                       if (skb->dev->type != ARPHRD_SIT){
20296                           int i;
20297 -                         unsigned char *p = (*pskb)->mac.raw;
20298 -                         for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
20299 +                         unsigned char *p = skb->mac.raw;
20300 +                         for (i = 0; i < skb->dev->hard_header_len; i++,p++)
20301                                 printk("%02x%c", *p,
20302 -                                       i==(*pskb)->dev->hard_header_len - 1
20303 +                                       i==skb->dev->hard_header_len - 1
20304                                         ? ' ':':');
20305                         } else {
20306                           int i;
20307 -                         unsigned char *p = (*pskb)->mac.raw;
20308 -                         if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
20309 +                         unsigned char *p = skb->mac.raw;
20310 +                         if ( p - (ETH_ALEN*2+2) > skb->head ){
20311                             p -= (ETH_ALEN+2);
20312                             for (i = 0; i < (ETH_ALEN); i++,p++)
20313                                 printk("%02x%s", *p,
20314 @@ -300,10 +304,10 @@
20315                                         i == ETH_ALEN-1 ? ' ' : ':');
20316                           }
20317                           
20318 -                         if (((*pskb)->dev->addr_len == 4) &&
20319 -                             (*pskb)->dev->hard_header_len > 20){
20320 +                         if ((skb->dev->addr_len == 4) &&
20321 +                             skb->dev->hard_header_len > 20){
20322                             printk("TUNNEL=");
20323 -                           p = (*pskb)->mac.raw + 12;
20324 +                           p = skb->mac.raw + 12;
20325                             for (i = 0; i < 4; i++,p++)
20326                                 printk("%3d%s", *p,
20327                                         i == 3 ? "->" : ".");
20328 @@ -319,10 +323,41 @@
20329         dump_packet(loginfo, ipv6h, 1);
20330         printk("\n");
20331         spin_unlock_bh(&log_lock);
20332 +}
20333 +
20334 +static unsigned int
20335 +ip6t_log_target(struct sk_buff **pskb,
20336 +               unsigned int hooknum,
20337 +               const struct net_device *in,
20338 +               const struct net_device *out,
20339 +               const void *targinfo,
20340 +               void *userinfo)
20341 +{
20342 +       const struct ip6t_log_info *loginfo = targinfo;
20343 +       char level_string[4] = "< >";
20344 +
20345 +       level_string[1] = '0' + (loginfo->level % 8);
20346 +       ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
20347  
20348         return IP6T_CONTINUE;
20349  }
20350  
20351 +static void
20352 +ip6t_logfn(unsigned int hooknum,
20353 +          const struct sk_buff *skb,
20354 +          const struct net_device *in,
20355 +          const struct net_device *out,
20356 +          const char *prefix)
20357 +{
20358 +       struct ip6t_log_info loginfo = { 
20359 +               .level = 0, 
20360 +               .logflags = IP6T_LOG_MASK, 
20361 +               .prefix = "" 
20362 +       };
20363 +
20364 +       ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
20365 +}
20366 +
20367  static int ip6t_log_checkentry(const char *tablename,
20368                                const struct ip6t_entry *e,
20369                                void *targinfo,
20370 @@ -359,12 +394,17 @@
20371  {
20372         if (ip6t_register_target(&ip6t_log_reg))
20373                 return -EINVAL;
20374 +       if (nflog)
20375 +               nf_log_register(PF_INET6, &ip6t_logfn);
20376  
20377         return 0;
20378  }
20379  
20380  static void __exit fini(void)
20381  {
20382 +       if (nflog)
20383 +               nf_log_register(PF_INET6, &ip6t_logfn);
20384 +
20385         ip6t_unregister_target(&ip6t_log_reg);
20386  }
20387  
20388 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_nth.c
20389 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_nth.c        1970-01-01 01:00:00.000000000 +0100
20390 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_nth.c    2003-12-10 23:13:36.623508464 +0100
20391 @@ -0,0 +1,173 @@
20392 +/*
20393 +  This is a module which is used for match support for every Nth packet
20394 +  This file is distributed under the terms of the GNU General Public
20395 +  License (GPL). Copies of the GPL can be obtained from:
20396 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
20397 +
20398 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20399 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
20400 +        * added support for multiple counters
20401 +        * added support for matching on individual packets
20402 +          in the counter cycle
20403 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20404 +
20405 +*/
20406 +
20407 +#include <linux/module.h>
20408 +#include <linux/skbuff.h>
20409 +#include <linux/ip.h>
20410 +#include <net/tcp.h>
20411 +#include <linux/spinlock.h>
20412 +#include <linux/netfilter_ipv6/ip6_tables.h>
20413 +#include <linux/netfilter_ipv6/ip6t_nth.h>
20414 +
20415 +MODULE_LICENSE("GPL");
20416 +
20417 +/*
20418 + * State information.
20419 + */
20420 +struct state {
20421 +       spinlock_t lock;
20422 +       u_int16_t number;
20423 +};
20424 +
20425 +static struct state states[IP6T_NTH_NUM_COUNTERS];
20426 +
20427 +static int
20428 +ip6t_nth_match(const struct sk_buff *pskb,
20429 +             const struct net_device *in,
20430 +             const struct net_device *out,
20431 +             const void *matchinfo,
20432 +             int offset,
20433 +             const void *hdr,
20434 +             u_int16_t datalen,
20435 +             int *hotdrop)
20436 +{
20437 +       /* Parameters from userspace */
20438 +       const struct ip6t_nth_info *info = matchinfo;
20439 +        unsigned counter = info->counter;
20440 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
20441 +       {
20442 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20443 +               return 0;
20444 +        };
20445 +
20446 +        spin_lock(&states[counter].lock);
20447 +
20448 +        /* Are we matching every nth packet?*/
20449 +        if (info->packet == 0xFF)
20450 +        {
20451 +               /* We're matching every nth packet and only every nth packet*/
20452 +               /* Do we match or invert match? */
20453 +               if (info->not == 0)
20454 +               {
20455 +                       if (states[counter].number == 0)
20456 +                       {
20457 +                               ++states[counter].number;
20458 +                               goto match;
20459 +                       }
20460 +                       if (states[counter].number >= info->every)
20461 +                               states[counter].number = 0; /* reset the counter */
20462 +                       else
20463 +                               ++states[counter].number;
20464 +                       goto dontmatch;
20465 +               }
20466 +               else
20467 +               {
20468 +                       if (states[counter].number == 0)
20469 +                       {
20470 +                               ++states[counter].number;
20471 +                               goto dontmatch;
20472 +                       }
20473 +                       if (states[counter].number >= info->every)
20474 +                               states[counter].number = 0;
20475 +                       else
20476 +                               ++states[counter].number;
20477 +                       goto match;
20478 +               }
20479 +        }
20480 +        else
20481 +        {
20482 +               /* We're using the --packet, so there must be a rule for every value */
20483 +               if (states[counter].number == info->packet)
20484 +               {
20485 +                       /* only increment the counter when a match happens */
20486 +                       if (states[counter].number >= info->every)
20487 +                               states[counter].number = 0; /* reset the counter */
20488 +                       else
20489 +                               ++states[counter].number;
20490 +                       goto match;
20491 +               }
20492 +               else
20493 +                       goto dontmatch;
20494 +       }
20495 +
20496 + dontmatch:
20497 +       /* don't match */
20498 +       spin_unlock(&states[counter].lock);
20499 +       return 0;
20500 +
20501 + match:
20502 +       spin_unlock(&states[counter].lock);
20503 +       return 1;
20504 +}
20505 +
20506 +static int
20507 +ip6t_nth_checkentry(const char *tablename,
20508 +                  const struct ip6t_ip6 *e,
20509 +                  void *matchinfo,
20510 +                  unsigned int matchsize,
20511 +                  unsigned int hook_mask)
20512 +{
20513 +       /* Parameters from userspace */
20514 +       const struct ip6t_nth_info *info = matchinfo;
20515 +        unsigned counter = info->counter;
20516 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
20517 +       {
20518 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20519 +                       return 0;
20520 +               };
20521 +
20522 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
20523 +               printk("nth: matchsize %u != %u\n", matchsize,
20524 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
20525 +               return 0;
20526 +       }
20527 +
20528 +       states[counter].number = info->startat;
20529 +
20530 +       return 1;
20531 +}
20532 +
20533 +static struct ip6t_match ip6t_nth_reg = { 
20534 +       {NULL, NULL},
20535 +       "nth",
20536 +       ip6t_nth_match,
20537 +       ip6t_nth_checkentry,
20538 +       NULL,
20539 +       THIS_MODULE };
20540 +
20541 +static int __init init(void)
20542 +{
20543 +       unsigned counter;
20544 +        memset(&states, 0, sizeof(states));
20545 +       if (ip6t_register_match(&ip6t_nth_reg))
20546 +               return -EINVAL;
20547 +
20548 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
20549 +       {
20550 +               spin_lock_init(&(states[counter].lock));
20551 +        };
20552 +
20553 +       printk("ip6t_nth match loaded\n");
20554 +       return 0;
20555 +}
20556 +
20557 +static void __exit fini(void)
20558 +{
20559 +       ip6t_unregister_match(&ip6t_nth_reg);
20560 +       printk("ip6t_nth match unloaded\n");
20561 +}
20562 +
20563 +module_init(init);
20564 +module_exit(fini);
20565 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_owner.c
20566 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_owner.c      2003-11-26 21:45:19.000000000 +0100
20567 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_owner.c  2003-12-10 23:14:05.029190144 +0100
20568 @@ -16,6 +16,38 @@
20569  MODULE_LICENSE("GPL");
20570  
20571  static int
20572 +match_comm(const struct sk_buff *skb, const char *comm)
20573 +{
20574 +       struct task_struct *p;
20575 +       struct files_struct *files;
20576 +       int i;
20577 +
20578 +       read_lock(&tasklist_lock);
20579 +       for_each_task(p) {
20580 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
20581 +                       continue;
20582 +
20583 +               task_lock(p);
20584 +               files = p->files;
20585 +               if(files) {
20586 +                       read_lock(&files->file_lock);
20587 +                       for (i=0; i < files->max_fds; i++) {
20588 +                               if (fcheck_files(files, i) == skb->sk->socket->file) {
20589 +                                       read_unlock(&files->file_lock);
20590 +                                       task_unlock(p);
20591 +                                       read_unlock(&tasklist_lock);
20592 +                                       return 1;
20593 +                               }
20594 +                       }
20595 +                       read_unlock(&files->file_lock);
20596 +               }
20597 +               task_unlock(p);
20598 +       }
20599 +       read_unlock(&tasklist_lock);
20600 +       return 0;
20601 +}
20602 +
20603 +static int
20604  match_pid(const struct sk_buff *skb, pid_t pid)
20605  {
20606         struct task_struct *p;
20607 @@ -120,6 +152,12 @@
20608                         return 0;
20609         }
20610  
20611 +       if(info->match & IP6T_OWNER_COMM) {
20612 +               if (!match_comm(skb, info->comm) ^
20613 +                   !!(info->invert & IP6T_OWNER_COMM))
20614 +                       return 0;
20615 +       }
20616 +
20617         return 1;
20618  }
20619  
20620 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_random.c
20621 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_random.c     1970-01-01 01:00:00.000000000 +0100
20622 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_random.c 2003-12-10 23:13:43.304492800 +0100
20623 @@ -0,0 +1,97 @@
20624 +/*
20625 +  This is a module which is used for a "random" match support.
20626 +  This file is distributed under the terms of the GNU General Public
20627 +  License (GPL). Copies of the GPL can be obtained from:
20628 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
20629 +
20630 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20631 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20632 +*/
20633 +
20634 +#include <linux/module.h>
20635 +#include <linux/skbuff.h>
20636 +#include <linux/ip.h>
20637 +#include <linux/random.h>
20638 +#include <net/tcp.h>
20639 +#include <linux/spinlock.h>
20640 +#include <linux/netfilter_ipv6/ip6_tables.h>
20641 +#include <linux/netfilter_ipv6/ip6t_random.h>
20642 +
20643 +MODULE_LICENSE("GPL");
20644 +
20645 +static int
20646 +ip6t_rand_match(const struct sk_buff *pskb,
20647 +              const struct net_device *in,
20648 +              const struct net_device *out,
20649 +              const void *matchinfo,
20650 +              int offset,
20651 +              const void *hdr,
20652 +              u_int16_t datalen,
20653 +              int *hotdrop)
20654 +{
20655 +       /* Parameters from userspace */
20656 +       const struct ip6t_rand_info *info = matchinfo;
20657 +       u_int8_t random_number;
20658 +
20659 +       /* get 1 random number from the kernel random number generation routine */
20660 +       get_random_bytes((void *)(&random_number), 1);
20661 +
20662 +       /* Do we match ? */
20663 +       if (random_number <= info->average)
20664 +               return 1;
20665 +       else
20666 +               return 0;
20667 +}
20668 +
20669 +static int
20670 +ip6t_rand_checkentry(const char *tablename,
20671 +                  const struct ip6t_ip6 *e,
20672 +                  void *matchinfo,
20673 +                  unsigned int matchsize,
20674 +                  unsigned int hook_mask)
20675 +{
20676 +       /* Parameters from userspace */
20677 +       const struct ip6t_rand_info *info = matchinfo;
20678 +
20679 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
20680 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
20681 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
20682 +               return 0;
20683 +       }
20684 +
20685 +       /* must be  1 <= average % <= 99 */
20686 +       /* 1  x 2.55 = 2   */
20687 +       /* 99 x 2.55 = 252 */
20688 +       if ((info->average < 2) || (info->average > 252)) {
20689 +               printk("ip6t_random:  invalid average %u\n", info->average);
20690 +               return 0;
20691 +       }
20692 +
20693 +       return 1;
20694 +}
20695 +
20696 +static struct ip6t_match ip6t_rand_reg = { 
20697 +       {NULL, NULL},
20698 +       "random",
20699 +       ip6t_rand_match,
20700 +       ip6t_rand_checkentry,
20701 +       NULL,
20702 +       THIS_MODULE };
20703 +
20704 +static int __init init(void)
20705 +{
20706 +       if (ip6t_register_match(&ip6t_rand_reg))
20707 +               return -EINVAL;
20708 +
20709 +       printk("ip6t_random match loaded\n");
20710 +       return 0;
20711 +}
20712 +
20713 +static void __exit fini(void)
20714 +{
20715 +       ip6t_unregister_match(&ip6t_rand_reg);
20716 +       printk("ip6t_random match unloaded\n");
20717 +}
20718 +
20719 +module_init(init);
20720 +module_exit(fini);
20721 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_REJECT.c
20722 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_REJECT.c     1970-01-01 01:00:00.000000000 +0100
20723 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_REJECT.c 2003-12-10 23:13:46.680979496 +0100
20724 @@ -0,0 +1,274 @@
20725 +/*
20726 + * This is a module which is used for rejecting packets.
20727 + *     Added support for customized reject packets (Jozsef Kadlecsik).
20728 + * Sun 12 Nov 2000
20729 + *     Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
20730 + */
20731 +#include <linux/config.h>
20732 +#include <linux/module.h>
20733 +#include <linux/skbuff.h>
20734 +#include <linux/icmpv6.h>
20735 +#include <net/tcp.h>
20736 +#include <linux/netfilter_ipv6/ip6_tables.h>
20737 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
20738 +
20739 +#if 1
20740 +#define DEBUGP printk
20741 +#else
20742 +#define DEBUGP(format, args...)
20743 +#endif
20744 +
20745 +#if 0
20746 +/* Send RST reply */
20747 +static void send_reset(struct sk_buff *oldskb)
20748 +{
20749 +       struct sk_buff *nskb;
20750 +       struct tcphdr *otcph, *tcph;
20751 +       struct rtable *rt;
20752 +       unsigned int otcplen;
20753 +       int needs_ack;
20754 +
20755 +       /* IP header checks: fragment, too short. */
20756 +       if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
20757 +           || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
20758 +               return;
20759 +
20760 +       otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
20761 +       otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
20762 +
20763 +       /* No RST for RST. */
20764 +       if (otcph->rst)
20765 +               return;
20766 +
20767 +       /* Check checksum. */
20768 +       if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
20769 +                        oldskb->nh.iph->daddr,
20770 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
20771 +               return;
20772 +
20773 +       /* Copy skb (even if skb is about to be dropped, we can't just
20774 +           clone it because there may be other things, such as tcpdump,
20775 +           interested in it) */
20776 +       nskb = skb_copy(oldskb, GFP_ATOMIC);
20777 +       if (!nskb)
20778 +               return;
20779 +
20780 +       /* This packet will not be the same as the other: clear nf fields */
20781 +       nf_conntrack_put(nskb->nfct);
20782 +       nskb->nfct = NULL;
20783 +       nskb->nfcache = 0;
20784 +#ifdef CONFIG_NETFILTER_DEBUG
20785 +       nskb->nf_debug = 0;
20786 +#endif
20787 +
20788 +       tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
20789 +
20790 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
20791 +       tcph->source = xchg(&tcph->dest, tcph->source);
20792 +
20793 +       /* Truncate to length (no data) */
20794 +       tcph->doff = sizeof(struct tcphdr)/4;
20795 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
20796 +       nskb->nh.iph->tot_len = htons(nskb->len);
20797 +
20798 +       if (tcph->ack) {
20799 +               needs_ack = 0;
20800 +               tcph->seq = otcph->ack_seq;
20801 +               tcph->ack_seq = 0;
20802 +       } else {
20803 +               needs_ack = 1;
20804 +               tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
20805 +                                     + otcplen - (otcph->doff<<2));
20806 +               tcph->seq = 0;
20807 +       }
20808 +
20809 +       /* Reset flags */
20810 +       ((u_int8_t *)tcph)[13] = 0;
20811 +       tcph->rst = 1;
20812 +       tcph->ack = needs_ack;
20813 +
20814 +       tcph->window = 0;
20815 +       tcph->urg_ptr = 0;
20816 +
20817 +       /* Adjust TCP checksum */
20818 +       tcph->check = 0;
20819 +       tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
20820 +                                  nskb->nh.iph->saddr,
20821 +                                  nskb->nh.iph->daddr,
20822 +                                  csum_partial((char *)tcph,
20823 +                                               sizeof(struct tcphdr), 0));
20824 +
20825 +       /* Adjust IP TTL, DF */
20826 +       nskb->nh.iph->ttl = MAXTTL;
20827 +       /* Set DF, id = 0 */
20828 +       nskb->nh.iph->frag_off = htons(IP_DF);
20829 +       nskb->nh.iph->id = 0;
20830 +
20831 +       /* Adjust IP checksum */
20832 +       nskb->nh.iph->check = 0;
20833 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
20834 +                                          nskb->nh.iph->ihl);
20835 +
20836 +       /* Routing */
20837 +       if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
20838 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
20839 +                           0) != 0)
20840 +               goto free_nskb;
20841 +
20842 +       dst_release(nskb->dst);
20843 +       nskb->dst = &rt->u.dst;
20844 +
20845 +       /* "Never happens" */
20846 +       if (nskb->len > nskb->dst->pmtu)
20847 +               goto free_nskb;
20848 +
20849 +       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
20850 +               ip_finish_output);
20851 +       return;
20852 +
20853 + free_nskb:
20854 +       kfree_skb(nskb);
20855 +}
20856 +#endif
20857 +
20858 +static unsigned int reject6_target(struct sk_buff **pskb,
20859 +                          unsigned int hooknum,
20860 +                          const struct net_device *in,
20861 +                          const struct net_device *out,
20862 +                          const void *targinfo,
20863 +                          void *userinfo)
20864 +{
20865 +       const struct ip6t_reject_info *reject = targinfo;
20866 +
20867 +       /* WARNING: This code causes reentry within ip6tables.
20868 +          This means that the ip6tables jump stack is now crap.  We
20869 +          must return an absolute verdict. --RR */
20870 +       DEBUGP("REJECTv6: calling icmpv6_send\n");
20871 +       switch (reject->with) {
20872 +       case IP6T_ICMP6_NO_ROUTE:
20873 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
20874 +               break;
20875 +       case IP6T_ICMP6_ADM_PROHIBITED:
20876 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
20877 +               break;
20878 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
20879 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
20880 +               break;
20881 +       case IP6T_ICMP6_ADDR_UNREACH:
20882 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
20883 +               break;
20884 +       case IP6T_ICMP6_PORT_UNREACH:
20885 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
20886 +               break;
20887 +#if 0
20888 +       case IPT_ICMP_ECHOREPLY: {
20889 +               struct icmp6hdr *icmph  = (struct icmphdr *)
20890 +                       ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
20891 +               unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
20892 +
20893 +               /* Not non-head frags, or truncated */
20894 +               if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
20895 +                   && datalen >= 4) {
20896 +                       /* Usually I don't like cut & pasting code,
20897 +                           but dammit, my party is starting in 45
20898 +                           mins! --RR */
20899 +                       struct icmp_bxm icmp_param;
20900 +
20901 +                       icmp_param.icmph=*icmph;
20902 +                       icmp_param.icmph.type=ICMP_ECHOREPLY;
20903 +                       icmp_param.data_ptr=(icmph+1);
20904 +                       icmp_param.data_len=datalen;
20905 +                       icmp_reply(&icmp_param, *pskb);
20906 +               }
20907 +       }
20908 +       break;
20909 +       case IPT_TCP_RESET:
20910 +               send_reset(*pskb);
20911 +               break;
20912 +#endif
20913 +       default:
20914 +               printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
20915 +               break;
20916 +       }
20917 +
20918 +       return NF_DROP;
20919 +}
20920 +
20921 +static inline int find_ping_match(const struct ip6t_entry_match *m)
20922 +{
20923 +       const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
20924 +
20925 +       if (strcmp(m->u.kernel.match->name, "icmp6") == 0
20926 +           && icmpinfo->type == ICMPV6_ECHO_REQUEST
20927 +           && !(icmpinfo->invflags & IP6T_ICMP_INV))
20928 +               return 1;
20929 +
20930 +       return 0;
20931 +}
20932 +
20933 +static int check(const char *tablename,
20934 +                const struct ip6t_entry *e,
20935 +                void *targinfo,
20936 +                unsigned int targinfosize,
20937 +                unsigned int hook_mask)
20938 +{
20939 +       const struct ip6t_reject_info *rejinfo = targinfo;
20940 +
20941 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
20942 +               DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
20943 +               return 0;
20944 +       }
20945 +
20946 +       /* Only allow these for packet filtering. */
20947 +       if (strcmp(tablename, "filter") != 0) {
20948 +               DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
20949 +               return 0;
20950 +       }
20951 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
20952 +                          | (1 << NF_IP6_FORWARD)
20953 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
20954 +               DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
20955 +               return 0;
20956 +       }
20957 +
20958 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
20959 +               /* Must specify that it's an ICMP ping packet. */
20960 +               if (e->ipv6.proto != IPPROTO_ICMPV6
20961 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20962 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
20963 +                       return 0;
20964 +               }
20965 +               /* Must contain ICMP match. */
20966 +               if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
20967 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
20968 +                       return 0;
20969 +               }
20970 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
20971 +               /* Must specify that it's a TCP packet */
20972 +               if (e->ipv6.proto != IPPROTO_TCP
20973 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20974 +                       DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
20975 +                       return 0;
20976 +               }
20977 +       }
20978 +
20979 +       return 1;
20980 +}
20981 +
20982 +static struct ip6t_target ip6t_reject_reg
20983 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
20984 +
20985 +static int __init init(void)
20986 +{
20987 +       if (ip6t_register_target(&ip6t_reject_reg))
20988 +               return -EINVAL;
20989 +       return 0;
20990 +}
20991 +
20992 +static void __exit fini(void)
20993 +{
20994 +       ip6t_unregister_target(&ip6t_reject_reg);
20995 +}
20996 +
20997 +module_init(init);
20998 +module_exit(fini);
20999 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_ROUTE.c
21000 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_ROUTE.c      1970-01-01 01:00:00.000000000 +0100
21001 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_ROUTE.c  2003-12-10 23:14:08.745625160 +0100
21002 @@ -0,0 +1,289 @@
21003 +/*
21004 + * This implements the ROUTE v6 target, which enables you to setup unusual
21005 + * routes not supported by the standard kernel routing table.
21006 + *
21007 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
21008 + *
21009 + * v 1.0 2003/08/05
21010 + *
21011 + * This software is distributed under GNU GPL v2, 1991
21012 + */
21013 +
21014 +#include <linux/module.h>
21015 +#include <linux/skbuff.h>
21016 +#include <linux/ipv6.h>
21017 +#include <linux/netfilter_ipv6/ip6_tables.h>
21018 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
21019 +#include <linux/netdevice.h>
21020 +#include <net/ipv6.h>
21021 +#include <net/ndisc.h>
21022 +#include <net/ip6_route.h>
21023 +#include <linux/icmpv6.h>
21024 +
21025 +#if 1
21026 +#define DEBUGP printk
21027 +#else
21028 +#define DEBUGP(format, args...)
21029 +#endif
21030 +
21031 +#define NIP6(addr) \
21032 +       ntohs((addr).s6_addr16[0]), \
21033 +       ntohs((addr).s6_addr16[1]), \
21034 +       ntohs((addr).s6_addr16[2]), \
21035 +       ntohs((addr).s6_addr16[3]), \
21036 +       ntohs((addr).s6_addr16[4]), \
21037 +       ntohs((addr).s6_addr16[5]), \
21038 +       ntohs((addr).s6_addr16[6]), \
21039 +       ntohs((addr).s6_addr16[7])
21040 +
21041 +/* Route the packet according to the routing keys specified in
21042 + * route_info. Keys are :
21043 + *  - ifindex : 
21044 + *      0 if no oif preferred, 
21045 + *      otherwise set to the index of the desired oif
21046 + *  - route_info->gw :
21047 + *      0 if no gateway specified,
21048 + *      otherwise set to the next host to which the pkt must be routed
21049 + * If success, skb->dev is the output device to which the packet must 
21050 + * be sent and skb->dst is not NULL
21051 + *
21052 + * RETURN:  1 if the packet was succesfully routed to the 
21053 + *            destination desired
21054 + *          0 if the kernel routing table could not route the packet
21055 + *            according to the keys specified
21056 + */
21057 +static int 
21058 +route6(struct sk_buff *skb,
21059 +       unsigned int ifindex,
21060 +       const struct ip6t_route_target_info *route_info)
21061 +{
21062 +       struct rt6_info *rt = NULL;
21063 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
21064 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
21065 +
21066 +       DEBUGP("ip6t_ROUTE: called with: ");
21067 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
21068 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
21069 +       DEBUGP("OUT=%s\n", route_info->oif);
21070 +       
21071 +       if (ipv6_addr_any(gw))
21072 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
21073 +       else
21074 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
21075 +
21076 +       if (!rt)
21077 +               goto no_route;
21078 +
21079 +       DEBUGP("ip6t_ROUTE: routing gives: ");
21080 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
21081 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
21082 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
21083 +
21084 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
21085 +               goto wrong_route;
21086 +       
21087 +       if (!rt->rt6i_nexthop) {
21088 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
21089 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
21090 +       }
21091 +
21092 +       /* Drop old route. */
21093 +       dst_release(skb->dst);
21094 +       skb->dst = &rt->u.dst;
21095 +       skb->dev = rt->rt6i_dev;
21096 +       return 1;
21097 +
21098 + wrong_route:
21099 +       dst_release(&rt->u.dst);
21100 + no_route:
21101 +       if (!net_ratelimit())
21102 +               return 0;
21103 +
21104 +       printk("ip6t_ROUTE: no explicit route found ");
21105 +       if (ifindex)
21106 +               printk("via interface %s ", route_info->oif);
21107 +       if (!ipv6_addr_any(gw))
21108 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
21109 +       printk("\n");
21110 +       return 0;
21111 +}
21112 +
21113 +
21114 +/* Stolen from ip6_output_finish
21115 + * PRE : skb->dev is set to the device we are leaving by
21116 + *       skb->dst is not NULL
21117 + * POST: the packet is sent with the link layer header pushed
21118 + *       the packet is destroyed
21119 + */
21120 +static void ip_direct_send(struct sk_buff *skb)
21121 +{
21122 +       struct dst_entry *dst = skb->dst;
21123 +       struct hh_cache *hh = dst->hh;
21124 +
21125 +       if (hh) {
21126 +               read_lock_bh(&hh->hh_lock);
21127 +               memcpy(skb->data - 16, hh->hh_data, 16);
21128 +               read_unlock_bh(&hh->hh_lock);
21129 +               skb_push(skb, hh->hh_len);
21130 +               hh->hh_output(skb);
21131 +       } else if (dst->neighbour)
21132 +               dst->neighbour->output(skb);
21133 +       else {
21134 +               if (net_ratelimit())
21135 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
21136 +               kfree_skb(skb);
21137 +       }
21138 +}
21139 +
21140 +
21141 +static unsigned int 
21142 +route6_oif(const struct ip6t_route_target_info *route_info,
21143 +          struct sk_buff *skb) 
21144 +{
21145 +       unsigned int ifindex = 0;
21146 +       struct net_device *dev_out = NULL;
21147 +
21148 +       /* The user set the interface name to use.
21149 +        * Getting the current interface index.
21150 +        */
21151 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
21152 +               ifindex = dev_out->ifindex;
21153 +       } else {
21154 +               /* Unknown interface name : packet dropped */
21155 +               if (net_ratelimit()) 
21156 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
21157 +
21158 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
21159 +                       return IP6T_CONTINUE;
21160 +               else
21161 +                       return NF_DROP;
21162 +       }
21163 +
21164 +       /* Trying the standard way of routing packets */
21165 +       if (route6(skb, ifindex, route_info)) {
21166 +               dev_put(dev_out);
21167 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
21168 +                       return IP6T_CONTINUE;
21169 +               
21170 +               ip_direct_send(skb);
21171 +               return NF_STOLEN;
21172 +       } else 
21173 +               return NF_DROP;
21174 +}
21175 +
21176 +
21177 +static unsigned int 
21178 +route6_gw(const struct ip6t_route_target_info *route_info,
21179 +         struct sk_buff *skb) 
21180 +{
21181 +       if (route6(skb, 0, route_info)) {
21182 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
21183 +                       return IP6T_CONTINUE;
21184 +
21185 +               ip_direct_send(skb);
21186 +               return NF_STOLEN;
21187 +       } else
21188 +               return NF_DROP;
21189 +}
21190 +
21191 +
21192 +static unsigned int 
21193 +ip6t_route_target(struct sk_buff **pskb,
21194 +                 unsigned int hooknum,
21195 +                 const struct net_device *in,
21196 +                 const struct net_device *out,
21197 +                 const void *targinfo,
21198 +                 void *userinfo)
21199 +{
21200 +       const struct ip6t_route_target_info *route_info = targinfo;
21201 +       struct sk_buff *skb = *pskb;
21202 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
21203 +
21204 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
21205 +               goto do_it;
21206 +
21207 +       /* If we are at PREROUTING or INPUT hook
21208 +        * the TTL isn't decreased by the IP stack
21209 +        */
21210 +       if (hooknum == NF_IP6_PRE_ROUTING ||
21211 +           hooknum == NF_IP6_LOCAL_IN) {
21212 +
21213 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
21214 +
21215 +               if (ipv6h->hop_limit <= 1) {
21216 +                       /* Force OUTPUT device used as source address */
21217 +                       skb->dev = skb->dst->dev;
21218 +
21219 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
21220 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
21221 +
21222 +                       return NF_DROP;
21223 +               }
21224 +
21225 +               ipv6h->hop_limit--;
21226 +       }
21227 +
21228 +
21229 + do_it:
21230 +       if (route_info->oif[0]) 
21231 +               return route6_oif(route_info, *pskb);
21232 +       
21233 +       if (!ipv6_addr_any(gw))
21234 +               return route6_gw(route_info, *pskb);
21235 +
21236 +       if (net_ratelimit()) 
21237 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
21238 +
21239 +       return IP6T_CONTINUE;
21240 +}
21241 +
21242 +
21243 +static int 
21244 +ip6t_route_checkentry(const char *tablename,
21245 +                     const struct ip6t_entry *e,
21246 +                     void *targinfo,
21247 +                     unsigned int targinfosize,
21248 +                     unsigned int hook_mask)
21249 +{
21250 +       if (strcmp(tablename, "mangle") != 0) {
21251 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
21252 +               return 0;
21253 +       }
21254 +
21255 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
21256 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
21257 +                      targinfosize,
21258 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
21259 +               return 0;
21260 +       }
21261 +
21262 +       return 1;
21263 +}
21264 +
21265 +
21266 +static struct ip6t_target ip6t_route_reg = {
21267 +       .name       = "ROUTE",
21268 +       .target     = ip6t_route_target,
21269 +       .checkentry = ip6t_route_checkentry,
21270 +       .me         = THIS_MODULE
21271 +};
21272 +
21273 +
21274 +static int __init init(void)
21275 +{
21276 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
21277 +       if (ip6t_register_target(&ip6t_route_reg))
21278 +               return -EINVAL;
21279 +
21280 +       return 0;
21281 +}
21282 +
21283 +
21284 +static void __exit fini(void)
21285 +{
21286 +       ip6t_unregister_target(&ip6t_route_reg);
21287 +}
21288 +
21289 +module_init(init);
21290 +module_exit(fini);
21291 +MODULE_LICENSE("GPL");
21292 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.0-test11/net/ipv6/netfilter/ip6t_TRACE.c
21293 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_TRACE.c      1970-01-01 01:00:00.000000000 +0100
21294 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_TRACE.c  2003-12-10 23:13:24.667326080 +0100
21295 @@ -0,0 +1,69 @@
21296 +/* This is a module which is used for setting
21297 + * the NFC_TRACE flag in the nfcache field of an skb. 
21298 + */
21299 +#include <linux/module.h>
21300 +#include <linux/skbuff.h>
21301 +
21302 +#include <linux/netfilter_ipv6/ip6_tables.h>
21303 +
21304 +static unsigned int
21305 +target(struct sk_buff **pskb,
21306 +       unsigned int hooknum,
21307 +       const struct net_device *in,
21308 +       const struct net_device *out,
21309 +       const void *targinfo,
21310 +       void *userinfo)
21311 +{
21312 +       (*pskb)->nfcache |= NFC_TRACE;
21313 +       return IP6T_CONTINUE;
21314 +}
21315 +
21316 +static int 
21317 +checkentry(const char *tablename,
21318 +                  const struct ip6t_entry *e,
21319 +           void *targinfo,
21320 +           unsigned int targinfosize,
21321 +           unsigned int hook_mask)
21322 +{
21323 +       if (targinfosize != 0) {
21324 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
21325 +                      targinfosize);
21326 +               return 0;
21327 +       }
21328 +
21329 +       if (strcmp(tablename, "raw") != 0) {
21330 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
21331 +               return 0;
21332 +       }
21333 +
21334 +       return 1;
21335 +}
21336 +
21337 +static struct ip6t_target ip6t_trace_reg = {
21338 +       .name = "TRACE",
21339 +       .target = target,
21340 +       .checkentry = checkentry,
21341 +       .destroy = NULL,
21342 +       .me = THIS_MODULE,
21343 +};
21344 +
21345 +static int __init init(void)
21346 +{
21347 +       if (ip6t_register_target(&ip6t_trace_reg))
21348 +               return -EINVAL;
21349 +
21350 +       return 0;
21351 +}
21352 +
21353 +static void __exit fini(void)
21354 +{
21355 +       ip6t_unregister_target(&ip6t_trace_reg);
21356 +}
21357 +
21358 +module_init(init);
21359 +module_exit(fini);
21360 +
21361 +MODULE_LICENSE("GPL");
21362 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
21363 +MODULE_DESCRIPTION("IPv6 TRACE target");
21364
21365 \ Brak znaku nowej linii na koƱcu pliku
21366 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig linux-2.6.0-test11/net/ipv6/netfilter/Kconfig
21367 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig   2003-11-26 21:45:28.000000000 +0100
21368 +++ linux-2.6.0-test11/net/ipv6/netfilter/Kconfig       2003-12-10 23:13:24.665326384 +0100
21369 @@ -217,6 +217,31 @@
21370  
21371           To compile it as a module, choose M here.  If unsure, say N.
21372  
21373 +config IP6_NF_RAW
21374 +       tristate "Raw table"
21375 +       depends on IP6_NF_IPTABLES
21376 +       help
21377 +         This option adds a `raw' table to iptables: see the man page for
21378 +         iptables(8).  This table is the very first in the netfilter
21379 +         framework and hooks in at the PREROUTING and OUTPUT chains.
21380 +         The TRACE target can be used in this table only.
21381 +
21382 +         To compile it as a module, choose M here.  If unsure, say N.
21383 +
21384 +config IP6_NF_TARGET_TRACE
21385 +       tristate "TRACE target support"
21386 +       depends on IP6_NF_RAW
21387 +       help
21388 +         The TRACE target allows packets to be traced as those matches
21389 +         any subsequent rule in any IPv6 netfilter table/rule. The matched 
21390 +         rule and the packet is logged with the prefix
21391 +         
21392 +         TRACE: tablename/chainname/rulenum
21393 +         
21394 +         if the ip6t_LOG target is loaded in.
21395 +
21396 +         To compile it as a module, choose M here.  If unsure, say N.
21397 +
21398  #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
21399  endmenu
21400  
21401 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile linux-2.6.0-test11/net/ipv6/netfilter/Makefile
21402 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile  2003-11-26 21:44:26.000000000 +0100
21403 +++ linux-2.6.0-test11/net/ipv6/netfilter/Makefile      2003-12-10 23:14:08.816614368 +0100
21404 @@ -6,8 +6,10 @@
21405  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
21406  obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
21407  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
21408 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
21409  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
21410  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
21411 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
21412  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
21413  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
21414  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
21415 @@ -18,7 +20,16 @@
21416  obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
21417  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
21418  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
21419 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
21420  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
21421 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
21422 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
21423  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
21424  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
21425 +
21426 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
21427 +
21428 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
21429 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
21430 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
21431  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
21432 diff -Nur linux-2.6.0-test11.org/netfilter-patch-o-matic/patches linux-2.6.0-test11/netfilter-patch-o-matic/patches
21433 --- linux-2.6.0-test11.org/netfilter-patch-o-matic/patches      1970-01-01 01:00:00.000000000 +0100
21434 +++ linux-2.6.0-test11/netfilter-patch-o-matic/patches  2003-12-10 23:38:25.000000000 +0100
21435 @@ -0,0 +1,86 @@
21436 +./base/01_sctp_match.patch
21437 +./base/connlimit.patch
21438 +./base/dstlimit.patch
21439 +./base/fuzzy6.patch.ipv6
21440 +./base/fuzzy.patch
21441 +./base/HL.patch.ipv6
21442 +./base/iprange.patch
21443 +./base/ipv4options.patch
21444 +./base/IPV4OPTSSTRIP.patch
21445 +./base/mport.patch
21446 +./base/NETLINK.patch
21447 +./base/nth6.patch.ipv6
21448 +./base/nth.patch
21449 +./base/osf.patch
21450 +./base/pool.patch
21451 +./base/psd.patch
21452 +./base/quota.patch
21453 +./base/random6.patch.ipv6
21454 +./base/random.patch
21455 +./base/realm.patch
21456 +./base/REJECT.patch.ipv6
21457 +./base/SAME.patch
21458 +./base/time.patch
21459 +./base/TTL.patch
21460 +./base/u32.patch
21461 +./extra/addrtype.patch
21462 +./extra/CLASSIFY.patch
21463 +./extra/condition6.patch.ipv6
21464 +./extra/condition.patch
21465 +./extra/CONNMARK.patch
21466 +./extra/cuseeme-nat.patch
21467 +./extra/eggdrop-conntrack.patch
21468 +./extra/h323-conntrack-nat.patch
21469 +./extra/IPMARK.patch
21470 +./extra/iptables-loopcheck-speedup.patch
21471 +./extra/ipt_TARPIT.patch                       manual change .makefile
21472 +./extra/mms-conntrack-nat.patch
21473 +./extra/netfilter-docbook.patch                        manual change
21474 +./extra/ownercmd.patch.ipv6
21475 +./extra/pptp-conntrack-nat.patch
21476 +./extra/quake3-conntrack.patch
21477 +./extra/ROUTE.patch
21478 +./extra/ROUTE.patch.ipv6
21479 +./extra/rpc.patch
21480 +./extra/rsh.patch
21481 +./extra/rtsp-conntrack.patch
21482 +./extra/string.patch                           manual change .makefile
21483 +./extra/talk-conntrack-nat.patch
21484 +./extra/TCPLAG.patch
21485 +./extra/TRACE.patch
21486 +./extra/TRACE.patch.ipv6
21487 +./extra/XOR.patch
21488 +./optimizations/ip_ct_refresh_optimization.patch
21489 +./optimizations/ip_ct_refresh_optimization_pptp.patch
21490 +./pending/23_REJECT-headroom-tcprst.patch
21491 +./pending/24_rcu.patch
21492 +./pending/25-err-ptr.patch
21493 +./pending/26-memsets.patch
21494 +./pending/40_nf-log.patch
21495 +./pending/70_expect-evict-order.patch
21496 +./pending/71_raw.patch
21497 +./submited/02_REJECT-headroom-tcprst.patch
21498 +./submited/03_260t4-mirror-remove.patch
21499 +./submited/03_physdev_bridged.patch
21500 +./submited/04_260t4-unclean-remove.patch
21501 +./submited/05_260t4-unexperimental.patch
21502 +./submited/06_260t4-cosmetic.patch
21503 +./submited/07_260t4-newmodules_iprange_SAME_NETMAP_CLASSIFY.patch
21504 +./submited/07_nonlinear_skb.patch
21505 +./submited/08_260t4_ipt-helper-kconfig.patch
21506 +./submited/09_260t4-cosmetic-physdev-author.patch
21507 +./submited/75_nathelper-udp-csum.patch
21508 +./submited/76_mangle_udp-sizecheck.patch
21509 +./submited/77_destroy-conntrack.patch
21510 +./submited/78_reject-localout.patch
21511 +./submited/80_ip_conntrack-proc.patch
21512 +./submited/82_irc-conntrack-mirc-serverlookup.patch
21513 +./submited/83_nolocalout.patch
21514 +./submited/84_local-nullbinding.patch
21515 +./submited/85_ipv6header.patch
21516 +./submited/86_getorigdst-tuple-zero.patch
21517 +./submited/87_compat-nat_setup_info.patch
21518 +./submited/89_ip_queue-maxlen.patch
21519 +./userspace/ip_queue_vwmark.patch
21520 +./userspace/ipt_REJECT-fake-source.patch
21521 +./userspace/mark-bitwise-ops.patch
This page took 1.796561 seconds and 3 git commands to generate.