]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.0-t11-netfilter-20031210.patch
- moving config-* fixed.
[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-11 10:23:17.221319936 +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-11 10:24:06.854774504 +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-11 10:23:48.969493480 +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-11 10:24:15.984386592 +0100
251 @@ -51,19 +51,29 @@
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 gre;
261         struct ip_ct_tcp tcp;
262         struct ip_ct_icmp icmp;
263  };
264  
265  union ip_conntrack_expect_proto {
266         /* insert expect proto private data here */
267 +       struct ip_ct_gre_expect gre;
268  };
269  
270  /* Add protocol helper include file here */
271 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
272 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
273 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
274 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
275 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
276 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
277 +
278  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
279  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
280  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
281 @@ -71,6 +81,13 @@
282  /* per expectation: application helper private data */
283  union ip_conntrack_expect_help {
284         /* insert conntrack helper private data (expect) here */
285 +       struct ip_ct_talk_expect exp_talk_info;
286 +       struct ip_ct_rtsp_master ct_rtsp_info;
287 +       struct ip_ct_rtsp_expect exp_rtsp_info;
288 +       struct ip_ct_rsh_expect exp_rsh_info;
289 +       struct ip_ct_pptp_expect exp_pptp_info;
290 +       struct ip_ct_mms_expect exp_mms_info;
291 +       struct ip_ct_h225_expect exp_h225_info;
292         struct ip_ct_amanda_expect exp_amanda_info;
293         struct ip_ct_ftp_expect exp_ftp_info;
294         struct ip_ct_irc_expect exp_irc_info;
295 @@ -85,16 +102,23 @@
296  /* per conntrack: application helper private data */
297  union ip_conntrack_help {
298         /* insert conntrack helper private data (master) here */
299 +       struct ip_ct_talk_master ct_talk_info;
300 +       struct ip_ct_rsh_master ct_rsh_info;
301 +       struct ip_ct_pptp_master ct_pptp_info;
302 +       struct ip_ct_mms_master ct_mms_info;
303 +       struct ip_ct_h225_master ct_h225_info;
304         struct ip_ct_ftp_master ct_ftp_info;
305         struct ip_ct_irc_master ct_irc_info;
306  };
307  
308  #ifdef CONFIG_IP_NF_NAT_NEEDED
309  #include <linux/netfilter_ipv4/ip_nat.h>
310 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
311  
312  /* per conntrack: nat application helper private data */
313  union ip_conntrack_nat_help {
314         /* insert nat helper private data here */
315 +       struct ip_nat_pptp nat_pptp_info;
316  };
317  #endif
318  
319 @@ -206,6 +230,9 @@
320         } nat;
321  #endif /* CONFIG_IP_NF_NAT_NEEDED */
322  
323 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
324 +       unsigned long mark;
325 +#endif
326  };
327  
328  /* get master conntrack via master expectation */
329 @@ -247,6 +274,9 @@
330  extern void ip_ct_refresh(struct ip_conntrack *ct,
331                           unsigned long extra_jiffies);
332  
333 +/* Kill conntrack */
334 +extern void ip_ct_death_by_timeout(unsigned long ul_conntrack);
335 +
336  /* These are for NAT.  Icky. */
337  /* Call me when a conntrack is destroyed. */
338  extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
339 @@ -268,6 +298,9 @@
340  
341  extern unsigned int ip_conntrack_htable_size;
342  
343 +/* A fake conntrack entry which never vanishes. */
344 +extern struct ip_conntrack ip_conntrack_untracked;
345 +
346  /* eg. PROVIDES_CONNTRACK(ftp); */
347  #define PROVIDES_CONNTRACK(name)                        \
348          int needs_ip_conntrack_##name;                  \
349 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
350 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h     1970-01-01 01:00:00.000000000 +0100
351 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_h323.h 2003-12-11 10:23:51.334134000 +0100
352 @@ -0,0 +1,30 @@
353 +#ifndef _IP_CONNTRACK_H323_H
354 +#define _IP_CONNTRACK_H323_H
355 +/* H.323 connection tracking. */
356 +
357 +#ifdef __KERNEL__
358 +/* Protects H.323 related data */
359 +DECLARE_LOCK_EXTERN(ip_h323_lock);
360 +#endif
361 +
362 +/* Default H.225 port */
363 +#define H225_PORT      1720
364 +
365 +/* This structure is per expected connection */
366 +struct ip_ct_h225_expect {
367 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
368 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
369 +       unsigned int offset;            /* offset of the address in the payload */
370 +};
371 +
372 +/* This structure exists only once per master */
373 +struct ip_ct_h225_master {
374 +       int is_h225;                            /* H.225 or H.245 connection */
375 +#ifdef CONFIG_IP_NF_NAT_NEEDED
376 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
377 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
378 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
379 +#endif
380 +};
381 +
382 +#endif /* _IP_CONNTRACK_H323_H */
383 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
384 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h      1970-01-01 01:00:00.000000000 +0100
385 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_mms.h  2003-12-11 10:23:55.932434952 +0100
386 @@ -0,0 +1,31 @@
387 +#ifndef _IP_CONNTRACK_MMS_H
388 +#define _IP_CONNTRACK_MMS_H
389 +/* MMS tracking. */
390 +
391 +#ifdef __KERNEL__
392 +#include <linux/netfilter_ipv4/lockhelp.h>
393 +
394 +DECLARE_LOCK_EXTERN(ip_mms_lock);
395 +
396 +#define MMS_PORT                         1755
397 +#define MMS_SRV_MSG_ID                   196610
398 +
399 +#define MMS_SRV_MSG_OFFSET               36
400 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
401 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
402 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
403 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
404 +#endif
405 +
406 +/* This structure is per expected connection */
407 +struct ip_ct_mms_expect {
408 +       u_int32_t len;
409 +       u_int32_t padding;
410 +       u_int16_t port;
411 +};
412 +
413 +/* This structure exists only once per master */
414 +struct ip_ct_mms_master {
415 +};
416 +
417 +#endif /* _IP_CONNTRACK_MMS_H */
418 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
419 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h     1970-01-01 01:00:00.000000000 +0100
420 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_pptp.h 2003-11-17 09:09:34.000000000 +0100
421 @@ -0,0 +1,313 @@
422 +/* PPTP constants and structs */
423 +#ifndef _CONNTRACK_PPTP_H
424 +#define _CONNTRACK_PPTP_H
425 +
426 +/* state of the control session */
427 +enum pptp_ctrlsess_state {
428 +       PPTP_SESSION_NONE,                      /* no session present */
429 +       PPTP_SESSION_ERROR,                     /* some session error */
430 +       PPTP_SESSION_STOPREQ,                   /* stop_sess request seen */
431 +       PPTP_SESSION_REQUESTED,                 /* start_sess request seen */
432 +       PPTP_SESSION_CONFIRMED,                 /* session established */
433 +};
434 +
435 +/* state of the call inside the control session */
436 +enum pptp_ctrlcall_state {
437 +       PPTP_CALL_NONE,
438 +       PPTP_CALL_ERROR,
439 +       PPTP_CALL_OUT_REQ,
440 +       PPTP_CALL_OUT_CONF,
441 +       PPTP_CALL_IN_REQ,
442 +       PPTP_CALL_IN_REP,
443 +       PPTP_CALL_IN_CONF,
444 +       PPTP_CALL_CLEAR_REQ,
445 +};
446 +
447 +
448 +/* conntrack private data */
449 +struct ip_ct_pptp_master {
450 +       enum pptp_ctrlsess_state sstate;        /* session state */
451 +
452 +       /* everything below is going to be per-expectation in newnat,
453 +        * since there could be more than one call within one session */
454 +       enum pptp_ctrlcall_state cstate;        /* call state */
455 +       u_int16_t pac_call_id;                  /* call id of PAC, host byte order */
456 +       u_int16_t pns_call_id;                  /* call id of PNS, host byte order */
457 +};
458 +
459 +/* conntrack_expect private member */
460 +struct ip_ct_pptp_expect {
461 +       enum pptp_ctrlcall_state cstate;        /* call state */
462 +       u_int16_t pac_call_id;                  /* call id of PAC */
463 +       u_int16_t pns_call_id;                  /* call id of PNS */
464 +};
465 +
466 +
467 +#ifdef __KERNEL__
468 +
469 +#include <linux/netfilter_ipv4/lockhelp.h>
470 +DECLARE_LOCK_EXTERN(ip_pptp_lock);
471 +
472 +#define IP_CONNTR_PPTP         PPTP_CONTROL_PORT
473 +
474 +union pptp_ctrl_union {
475 +                void                           *rawreq;
476 +               struct PptpStartSessionRequest  *sreq;
477 +               struct PptpStartSessionReply    *srep;
478 +               struct PptpStopSessionReqest    *streq;
479 +               struct PptpStopSessionReply     *strep;
480 +                struct PptpOutCallRequest       *ocreq;
481 +                struct PptpOutCallReply         *ocack;
482 +                struct PptpInCallRequest        *icreq;
483 +                struct PptpInCallReply          *icack;
484 +                struct PptpInCallConnected      *iccon;
485 +               struct PptpClearCallRequest     *clrreq;
486 +                struct PptpCallDisconnectNotify *disc;
487 +                struct PptpWanErrorNotify       *wanerr;
488 +                struct PptpSetLinkInfo          *setlink;
489 +};
490 +
491 +
492 +
493 +#define PPTP_CONTROL_PORT      1723
494 +
495 +#define PPTP_PACKET_CONTROL    1
496 +#define PPTP_PACKET_MGMT       2
497 +
498 +#define PPTP_MAGIC_COOKIE      0x1a2b3c4d
499 +
500 +struct pptp_pkt_hdr {
501 +       __u16   packetLength;
502 +       __u16   packetType;
503 +       __u32   magicCookie;
504 +};
505 +
506 +/* PptpControlMessageType values */
507 +#define PPTP_START_SESSION_REQUEST     1
508 +#define PPTP_START_SESSION_REPLY       2
509 +#define PPTP_STOP_SESSION_REQUEST      3
510 +#define PPTP_STOP_SESSION_REPLY                4
511 +#define PPTP_ECHO_REQUEST              5
512 +#define PPTP_ECHO_REPLY                        6
513 +#define PPTP_OUT_CALL_REQUEST          7
514 +#define PPTP_OUT_CALL_REPLY            8
515 +#define PPTP_IN_CALL_REQUEST           9
516 +#define PPTP_IN_CALL_REPLY             10
517 +#define PPTP_IN_CALL_CONNECT           11
518 +#define PPTP_CALL_CLEAR_REQUEST                12
519 +#define PPTP_CALL_DISCONNECT_NOTIFY    13
520 +#define PPTP_WAN_ERROR_NOTIFY          14
521 +#define PPTP_SET_LINK_INFO             15
522 +
523 +#define PPTP_MSG_MAX                   15
524 +
525 +/* PptpGeneralError values */
526 +#define PPTP_ERROR_CODE_NONE           0
527 +#define PPTP_NOT_CONNECTED             1
528 +#define PPTP_BAD_FORMAT                        2
529 +#define PPTP_BAD_VALUE                 3
530 +#define PPTP_NO_RESOURCE               4
531 +#define PPTP_BAD_CALLID                        5
532 +#define PPTP_REMOVE_DEVICE_ERROR       6
533 +
534 +struct PptpControlHeader {
535 +       __u16   messageType;
536 +       __u16   reserved;
537 +};
538 +
539 +/* FramingCapability Bitmap Values */
540 +#define PPTP_FRAME_CAP_ASYNC           0x1
541 +#define PPTP_FRAME_CAP_SYNC            0x2
542 +
543 +/* BearerCapability Bitmap Values */
544 +#define PPTP_BEARER_CAP_ANALOG         0x1
545 +#define PPTP_BEARER_CAP_DIGITAL                0x2
546 +
547 +struct PptpStartSessionRequest {
548 +       __u16   protocolVersion;
549 +       __u8    reserved1;
550 +       __u8    reserved2;
551 +       __u32   framingCapability;
552 +       __u32   bearerCapability;
553 +       __u16   maxChannels;
554 +       __u16   firmwareRevision;
555 +       __u8    hostName[64];
556 +       __u8    vendorString[64];
557 +};
558 +
559 +/* PptpStartSessionResultCode Values */
560 +#define PPTP_START_OK                  1
561 +#define PPTP_START_GENERAL_ERROR       2
562 +#define PPTP_START_ALREADY_CONNECTED   3
563 +#define PPTP_START_NOT_AUTHORIZED      4
564 +#define PPTP_START_UNKNOWN_PROTOCOL    5
565 +
566 +struct PptpStartSessionReply {
567 +       __u16   protocolVersion;
568 +       __u8    resultCode;
569 +       __u8    generalErrorCode;
570 +       __u32   framingCapability;
571 +       __u32   bearerCapability;
572 +       __u16   maxChannels;
573 +       __u16   firmwareRevision;
574 +       __u8    hostName[64];
575 +       __u8    vendorString[64];
576 +};
577 +
578 +/* PptpStopReasons */
579 +#define PPTP_STOP_NONE                 1
580 +#define PPTP_STOP_PROTOCOL             2
581 +#define PPTP_STOP_LOCAL_SHUTDOWN       3
582 +
583 +struct PptpStopSessionRequest {
584 +       __u8    reason;
585 +};
586 +
587 +/* PptpStopSessionResultCode */
588 +#define PPTP_STOP_OK                   1
589 +#define PPTP_STOP_GENERAL_ERROR                2
590 +
591 +struct PptpStopSessionReply {
592 +       __u8    resultCode;
593 +       __u8    generalErrorCode;
594 +};
595 +
596 +struct PptpEchoRequest {
597 +       __u32 identNumber;
598 +};
599 +
600 +/* PptpEchoReplyResultCode */
601 +#define PPTP_ECHO_OK                   1
602 +#define PPTP_ECHO_GENERAL_ERROR                2
603 +
604 +struct PptpEchoReply {
605 +       __u32   identNumber;
606 +       __u8    resultCode;
607 +       __u8    generalErrorCode;
608 +       __u16   reserved;
609 +};
610 +
611 +/* PptpFramingType */
612 +#define PPTP_ASYNC_FRAMING             1
613 +#define PPTP_SYNC_FRAMING              2
614 +#define PPTP_DONT_CARE_FRAMING         3
615 +
616 +/* PptpCallBearerType */
617 +#define PPTP_ANALOG_TYPE               1
618 +#define PPTP_DIGITAL_TYPE              2
619 +#define PPTP_DONT_CARE_BEARER_TYPE     3
620 +
621 +struct PptpOutCallRequest {
622 +       __u16   callID;
623 +       __u16   callSerialNumber;
624 +       __u32   minBPS;
625 +       __u32   maxBPS;
626 +       __u32   bearerType;
627 +       __u32   framingType;
628 +       __u16   packetWindow;
629 +       __u16   packetProcDelay;
630 +       __u16   reserved1;
631 +       __u16   phoneNumberLength;
632 +       __u16   reserved2;
633 +       __u8    phoneNumber[64];
634 +       __u8    subAddress[64];
635 +};
636 +
637 +/* PptpCallResultCode */
638 +#define PPTP_OUTCALL_CONNECT           1
639 +#define PPTP_OUTCALL_GENERAL_ERROR     2
640 +#define PPTP_OUTCALL_NO_CARRIER                3
641 +#define PPTP_OUTCALL_BUSY              4
642 +#define PPTP_OUTCALL_NO_DIAL_TONE      5
643 +#define PPTP_OUTCALL_TIMEOUT           6
644 +#define PPTP_OUTCALL_DONT_ACCEPT       7
645 +
646 +struct PptpOutCallReply {
647 +       __u16   callID;
648 +       __u16   peersCallID;
649 +       __u8    resultCode;
650 +       __u8    generalErrorCode;
651 +       __u16   causeCode;
652 +       __u32   connectSpeed;
653 +       __u16   packetWindow;
654 +       __u16   packetProcDelay;
655 +       __u32   physChannelID;
656 +};
657 +
658 +struct PptpInCallRequest {
659 +       __u16   callID;
660 +       __u16   callSerialNumber;
661 +       __u32   callBearerType;
662 +       __u32   physChannelID;
663 +       __u16   dialedNumberLength;
664 +       __u16   dialingNumberLength;
665 +       __u8    dialedNumber[64];
666 +       __u8    dialingNumber[64];
667 +       __u8    subAddress[64];
668 +};
669 +
670 +/* PptpInCallResultCode */
671 +#define PPTP_INCALL_ACCEPT             1
672 +#define PPTP_INCALL_GENERAL_ERROR      2
673 +#define PPTP_INCALL_DONT_ACCEPT                3
674 +
675 +struct PptpInCallReply {
676 +       __u16   callID;
677 +       __u16   peersCallID;
678 +       __u8    resultCode;
679 +       __u8    generalErrorCode;
680 +       __u16   packetWindow;
681 +       __u16   packetProcDelay;
682 +       __u16   reserved;
683 +};
684 +
685 +struct PptpInCallConnected {
686 +       __u16   peersCallID;
687 +       __u16   reserved;
688 +       __u32   connectSpeed;
689 +       __u16   packetWindow;
690 +       __u16   packetProcDelay;
691 +       __u32   callFramingType;
692 +};
693 +
694 +struct PptpClearCallRequest {
695 +       __u16   callID;
696 +       __u16   reserved;
697 +};
698 +
699 +struct PptpCallDisconnectNotify {
700 +       __u16   callID;
701 +       __u8    resultCode;
702 +       __u8    generalErrorCode;
703 +       __u16   causeCode;
704 +       __u16   reserved;
705 +       __u8    callStatistics[128];
706 +};
707 +
708 +struct PptpWanErrorNotify {
709 +       __u16   peersCallID;
710 +       __u16   reserved;
711 +       __u32   crcErrors;
712 +       __u32   framingErrors;
713 +       __u32   hardwareOverRuns;
714 +       __u32   bufferOverRuns;
715 +       __u32   timeoutErrors;
716 +       __u32   alignmentErrors;
717 +};
718 +
719 +struct PptpSetLinkInfo {
720 +       __u16   peersCallID;
721 +       __u16   reserved;
722 +       __u32   sendAccm;
723 +       __u32   recvAccm;
724 +};
725 +
726 +
727 +struct pptp_priv_data {
728 +       __u16   call_id;
729 +       __u16   mcall_id;
730 +       __u16   pcall_id;
731 +};
732 +
733 +#endif /* __KERNEL__ */
734 +#endif /* _CONNTRACK_PPTP_H */
735 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
736 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h        1970-01-01 01:00:00.000000000 +0100
737 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h    2003-11-17 09:09:34.000000000 +0100
738 @@ -0,0 +1,123 @@
739 +#ifndef _CONNTRACK_PROTO_GRE_H
740 +#define _CONNTRACK_PROTO_GRE_H
741 +#include <asm/byteorder.h>
742 +
743 +/* GRE PROTOCOL HEADER */
744 +
745 +/* GRE Version field */
746 +#define GRE_VERSION_1701       0x0
747 +#define GRE_VERSION_PPTP       0x1
748 +
749 +/* GRE Protocol field */
750 +#define GRE_PROTOCOL_PPTP      0x880B
751 +
752 +/* GRE Flags */
753 +#define GRE_FLAG_C             0x80
754 +#define GRE_FLAG_R             0x40
755 +#define GRE_FLAG_K             0x20
756 +#define GRE_FLAG_S             0x10
757 +#define GRE_FLAG_A             0x80
758 +
759 +#define GRE_IS_C(f)    ((f)&GRE_FLAG_C)
760 +#define GRE_IS_R(f)    ((f)&GRE_FLAG_R)
761 +#define GRE_IS_K(f)    ((f)&GRE_FLAG_K)
762 +#define GRE_IS_S(f)    ((f)&GRE_FLAG_S)
763 +#define GRE_IS_A(f)    ((f)&GRE_FLAG_A)
764 +
765 +/* GRE is a mess: Four different standards */
766 +struct gre_hdr {
767 +#if defined(__LITTLE_ENDIAN_BITFIELD)
768 +       __u16   rec:3,
769 +               srr:1,
770 +               seq:1,
771 +               key:1,
772 +               routing:1,
773 +               csum:1,
774 +               version:3,
775 +               reserved:4,
776 +               ack:1;
777 +#elif defined(__BIG_ENDIAN_BITFIELD)
778 +       __u16   csum:1,
779 +               routing:1,
780 +               key:1,
781 +               seq:1,
782 +               srr:1,
783 +               rec:3,
784 +               ack:1,
785 +               reserved:4,
786 +               version:3;
787 +#else
788 +#error "Adjust your <asm/byteorder.h> defines"
789 +#endif
790 +       __u16   protocol;
791 +};
792 +
793 +/* modified GRE header for PPTP */
794 +struct gre_hdr_pptp {
795 +       __u8  flags;            /* bitfield */
796 +       __u8  version;          /* should be GRE_VERSION_PPTP */
797 +       __u16 protocol;         /* should be GRE_PROTOCOL_PPTP */
798 +       __u16 payload_len;      /* size of ppp payload, not inc. gre header */
799 +       __u16 call_id;          /* peer's call_id for this session */
800 +       __u32 seq;              /* sequence number.  Present if S==1 */
801 +       __u32 ack;              /* seq number of highest packet recieved by */
802 +                               /*  sender in this session */
803 +};
804 +
805 +
806 +/* this is part of ip_conntrack */
807 +struct ip_ct_gre {
808 +       unsigned int stream_timeout;
809 +       unsigned int timeout;
810 +};
811 +
812 +/* this is part of ip_conntrack_expect */
813 +struct ip_ct_gre_expect {
814 +       struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
815 +};
816 +
817 +#ifdef __KERNEL__
818 +struct ip_conntrack_expect;
819 +
820 +/* structure for original <-> reply keymap */
821 +struct ip_ct_gre_keymap {
822 +       struct list_head list;
823 +
824 +       struct ip_conntrack_tuple tuple;
825 +};
826 +
827 +
828 +/* add new tuple->key_reply pair to keymap */
829 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
830 +                        struct ip_conntrack_tuple *t,
831 +                        int reply);
832 +
833 +/* change an existing keymap entry */
834 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
835 +                            struct ip_conntrack_tuple *t);
836 +
837 +/* delete keymap entries */
838 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
839 +
840 +
841 +/* get pointer to gre key, if present */
842 +static inline u_int32_t *gre_key(struct gre_hdr *greh)
843 +{
844 +       if (!greh->key)
845 +               return NULL;
846 +       if (greh->csum || greh->routing)
847 +               return (u_int32_t *) (greh+sizeof(*greh)+4);
848 +       return (u_int32_t *) (greh+sizeof(*greh));
849 +}
850 +
851 +/* get pointer ot gre csum, if present */
852 +static inline u_int16_t *gre_csum(struct gre_hdr *greh)
853 +{
854 +       if (!greh->csum)
855 +               return NULL;
856 +       return (u_int16_t *) (greh+sizeof(*greh));
857 +}
858 +
859 +#endif /* __KERNEL__ */
860 +
861 +#endif /* _CONNTRACK_PROTO_GRE_H */
862 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
863 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h   1970-01-01 01:00:00.000000000 +0100
864 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_quake3.h       2003-12-11 10:24:00.844688176 +0100
865 @@ -0,0 +1,21 @@
866 +#ifndef _IP_CT_QUAKE3
867 +#define _IP_CT_QUAKE3
868 +
869 +/* Don't confuse with 27960, often used as the Server Port */
870 +#define QUAKE3_MASTER_PORT 27950
871 +
872 +struct quake3_search {
873 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
874 +       const char *pattern;
875 +       size_t plen;
876 +}; 
877 +
878 +/* This structure is per expected connection */
879 +struct ip_ct_quake3_expect {
880 +};
881 +
882 +/* This structure exists only once per master */
883 +struct ip_ct_quake3_master {
884 +};
885 +
886 +#endif /* _IP_CT_QUAKE3 */
887 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
888 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h      1970-01-01 01:00:00.000000000 +0100
889 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rpc.h  2003-12-11 10:24:04.354154656 +0100
890 @@ -0,0 +1,68 @@
891 +/* RPC extension for IP connection tracking, Version 2.2
892 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
893 + *     - original rpc tracking module
894 + *     - "recent" connection handling for kernel 2.3+ netfilter
895 + *
896 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
897 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
898 + *
899 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
900 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
901 + *     - extended matching to support filtering on procedures
902 + *
903 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
904 + *
905 + *     This program is free software; you can redistribute it and/or
906 + *     modify it under the terms of the GNU General Public License
907 + *     as published by the Free Software Foundation; either version
908 + *     2 of the License, or (at your option) any later version.
909 + **
910 + */
911 +
912 +#include <asm/param.h>
913 +#include <linux/sched.h>
914 +#include <linux/timer.h>
915 +#include <linux/stddef.h>
916 +#include <linux/list.h>
917 +
918 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
919 +
920 +#ifndef _IP_CONNTRACK_RPC_H
921 +#define _IP_CONNTRACK_RPC_H
922 +
923 +#define RPC_PORT       111
924 +
925 +
926 +/* Datum in RPC packets are encoded in XDR */
927 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
928 +
929 +/* Fast timeout, to deny DoS atacks */
930 +#define EXP (60 * HZ)
931 +
932 +/* Normal timeouts */
933 +#define EXPIRES (180 * HZ)
934 +
935 +/* For future conections RPC, using client's cache bindings
936 + * I'll use ip_conntrack_lock to lock these lists      */
937 +
938 +/* This identifies each request and stores protocol */
939 +struct request_p {
940 +       struct list_head list;
941 +
942 +       u_int32_t xid;   
943 +       u_int32_t ip;
944 +       u_int16_t port;
945 +       
946 +       /* Protocol */
947 +       u_int16_t proto;
948 +
949 +       struct timer_list timeout;
950 +};
951 +
952 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
953 +                               u_int32_t ip, u_int32_t port) {
954 +       return (p->xid == xid && p->ip == ip && p->port);
955 +
956 +}
957 +
958 +#endif /* _IP_CONNTRACK_RPC_H */
959 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
960 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h      1970-01-01 01:00:00.000000000 +0100
961 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rsh.h  2003-12-11 10:24:05.586967240 +0100
962 @@ -0,0 +1,35 @@
963 +/* RSH extension for IP connection tracking, Version 1.0
964 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
965 + * based on HW's ip_conntrack_irc.c     
966 + *
967 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
968 + *
969 + *      This program is free software; you can redistribute it and/or
970 + *      modify it under the terms of the GNU General Public License
971 + *      as published by the Free Software Foundation; either version
972 + *      2 of the License, or (at your option) any later version.
973 + */
974 +#ifndef _IP_CONNTRACK_RSH_H
975 +#define _IP_CONNTRACK_RSH_H
976 +
977 +#ifdef __KERNEL__
978 +#include <linux/netfilter_ipv4/lockhelp.h>
979 +
980 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
981 +#endif
982 +
983 +
984 +#define RSH_PORT       514
985 +
986 +/* This structure is per expected connection */
987 +struct ip_ct_rsh_expect
988 +{
989 +       u_int16_t port;
990 +};
991 +
992 +/* This structure exists only once per master */
993 +struct ip_ct_rsh_master {
994 +};
995 +
996 +#endif /* _IP_CONNTRACK_RSH_H */
997 +
998 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
999 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h     1970-01-01 01:00:00.000000000 +0100
1000 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h 2003-12-11 10:24:06.854774504 +0100
1001 @@ -0,0 +1,68 @@
1002 +/*
1003 + * RTSP extension for IP connection tracking.
1004 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
1005 + * based on ip_conntrack_irc.h
1006 + *
1007 + *      This program is free software; you can redistribute it and/or
1008 + *      modify it under the terms of the GNU General Public License
1009 + *      as published by the Free Software Foundation; either version
1010 + *      2 of the License, or (at your option) any later version.
1011 + */
1012 +#ifndef _IP_CONNTRACK_RTSP_H
1013 +#define _IP_CONNTRACK_RTSP_H
1014 +
1015 +/* #define IP_NF_RTSP_DEBUG */
1016 +#define IP_NF_RTSP_VERSION "0.01"
1017 +
1018 +/* port block types */
1019 +typedef enum {
1020 +    pb_single,  /* client_port=x */
1021 +    pb_range,   /* client_port=x-y */
1022 +    pb_discon   /* client_port=x/y (rtspbis) */
1023 +} portblock_t;
1024 +
1025 +/* We record seq number and length of rtsp headers here, all in host order. */
1026 +
1027 +/*
1028 + * This structure is per expected connection.  It is a member of struct
1029 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
1030 + * there and we are expected to only store the length of the data which
1031 + * needs replaced.  If a packet contains multiple RTSP messages, we create
1032 + * one expected connection per message.
1033 + *
1034 + * We use these variables to mark the entire header block.  This may seem
1035 + * like overkill, but the nature of RTSP requires it.  A header may appear
1036 + * multiple times in a message.  We must treat two Transport headers the
1037 + * same as one Transport header with two entries.
1038 + */
1039 +struct ip_ct_rtsp_expect
1040 +{
1041 +    u_int32_t   len;        /* length of header block */
1042 +    portblock_t pbtype;     /* Type of port block that was requested */
1043 +    u_int16_t   loport;     /* Port that was requested, low or first */
1044 +    u_int16_t   hiport;     /* Port that was requested, high or second */
1045 +#if 0
1046 +    uint        method;     /* RTSP method */
1047 +    uint        cseq;       /* CSeq from request */
1048 +#endif
1049 +};
1050 +
1051 +/* This structure exists only once per master */
1052 +struct ip_ct_rtsp_master
1053 +{
1054 +    /* Empty (?) */
1055 +};
1056 +
1057 +
1058 +#ifdef __KERNEL__
1059 +
1060 +#include <linux/netfilter_ipv4/lockhelp.h>
1061 +
1062 +#define RTSP_PORT   554
1063 +
1064 +/* Protects rtsp part of conntracks */
1065 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
1066 +
1067 +#endif /* __KERNEL__ */
1068 +
1069 +#endif /* _IP_CONNTRACK_RTSP_H */
1070 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
1071 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h     1970-01-01 01:00:00.000000000 +0100
1072 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_talk.h 2003-12-11 10:24:09.248410616 +0100
1073 @@ -0,0 +1,152 @@
1074 +#ifndef _IP_CONNTRACK_TALK_H
1075 +#define _IP_CONNTRACK_TALK_H
1076 +/* TALK tracking. */
1077 +
1078 +#ifdef __KERNEL__
1079 +#include <linux/in.h>
1080 +#include <linux/netfilter_ipv4/lockhelp.h>
1081 +
1082 +/* Protects talk part of conntracks */
1083 +DECLARE_LOCK_EXTERN(ip_talk_lock);
1084 +#endif
1085 +
1086 +
1087 +#define TALK_PORT      517
1088 +#define NTALK_PORT     518
1089 +
1090 +/* talk structures and constants from <protocols/talkd.h> */
1091 +
1092 +/*
1093 + * 4.3BSD struct sockaddr
1094 + */
1095 +struct talk_addr {
1096 +       u_int16_t ta_family;
1097 +       u_int16_t ta_port;
1098 +       u_int32_t ta_addr;
1099 +       u_int32_t ta_junk1;
1100 +       u_int32_t ta_junk2;
1101 +};
1102 +
1103 +#define        TALK_OLD_NSIZE  9
1104 +#define        TALK_NSIZE      12
1105 +#define        TALK_TTY_NSIZE  16
1106 +
1107 +/*
1108 + * Client->server request message formats.
1109 + */
1110 +struct talk_msg {
1111 +       u_char  type;           /* request type, see below */
1112 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
1113 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
1114 +       u_char  pad;
1115 +       u_int32_t id_num;       /* message id */
1116 +       int32_t pid;            /* caller's process id */
1117 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1118 +       struct  talk_addr addr;         /* old (4.3) style */
1119 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
1120 +};
1121 +
1122 +struct ntalk_msg {
1123 +       u_char  vers;           /* protocol version */
1124 +       u_char  type;           /* request type, see below */
1125 +       u_char  answer;         /* not used */
1126 +       u_char  pad;
1127 +       u_int32_t id_num;       /* message id */
1128 +       struct  talk_addr addr;         /* old (4.3) style */
1129 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
1130 +       int32_t pid;            /* caller's process id */
1131 +       char    l_name[TALK_NSIZE];/* caller's name */
1132 +       char    r_name[TALK_NSIZE];/* callee's name */
1133 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
1134 +};
1135 +
1136 +struct ntalk2_msg {
1137 +       u_char  vers;           /* talk protocol version    */
1138 +       u_char  type;           /* request type             */
1139 +       u_char  answer;         /*  */
1140 +       u_char  extended;       /* !0 if additional parts   */
1141 +       u_int32_t id_num;       /* message id number (dels) */
1142 +       struct  talk_addr addr;         /* target address   */
1143 +       struct  talk_addr ctl_addr;     /* reply to address */
1144 +       int32_t pid;            /* caller's process id */
1145 +       char    l_name[TALK_NSIZE];  /* caller's name */
1146 +       char    r_name[TALK_NSIZE];  /* callee's name */
1147 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
1148 +};
1149 +
1150 +/*
1151 + * Server->client response message formats.
1152 + */
1153 +struct talk_response {
1154 +       u_char  type;           /* type of request message, see below */
1155 +       u_char  answer;         /* response to request message, see below */
1156 +       u_char  pad[2];
1157 +       u_int32_t id_num;       /* message id */
1158 +       struct  talk_addr addr; /* address for establishing conversation */
1159 +};
1160 +
1161 +struct ntalk_response {
1162 +       u_char  vers;           /* protocol version */
1163 +       u_char  type;           /* type of request message, see below */
1164 +       u_char  answer;         /* response to request message, see below */
1165 +       u_char  pad;
1166 +       u_int32_t id_num;       /* message id */
1167 +       struct  talk_addr addr; /* address for establishing conversation */
1168 +};
1169 +
1170 +struct ntalk2_response {
1171 +       u_char  vers;           /* protocol version         */
1172 +       u_char  type;           /* type of request message  */
1173 +       u_char  answer;         /* response to request      */
1174 +       u_char  rvers;          /* Version of answering vers*/
1175 +       u_int32_t id_num;       /* message id number        */
1176 +       struct  talk_addr addr; /* address for connection   */
1177 +       /* This is at the end to compatiblize this with NTALK version.   */
1178 +       char    r_name[TALK_NSIZE]; /* callee's name            */
1179 +};
1180 +
1181 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
1182 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
1183 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
1184 +
1185 +#define        TALK_VERSION    0               /* protocol versions */
1186 +#define        NTALK_VERSION   1
1187 +#define        NTALK2_VERSION  2
1188 +
1189 +/* message type values */
1190 +#define LEAVE_INVITE   0       /* leave invitation with server */
1191 +#define LOOK_UP                1       /* check for invitation by callee */
1192 +#define DELETE         2       /* delete invitation by caller */
1193 +#define ANNOUNCE       3       /* announce invitation by caller */
1194 +/* NTALK2 */
1195 +#define REPLY_QUERY    4       /* request reply data from local daemon */
1196 +
1197 +/* answer values */
1198 +#define SUCCESS                0       /* operation completed properly */
1199 +#define NOT_HERE       1       /* callee not logged in */
1200 +#define FAILED         2       /* operation failed for unexplained reason */
1201 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
1202 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
1203 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
1204 +#define        BADVERSION      6       /* request has invalid protocol version */
1205 +#define        BADADDR         7       /* request has invalid addr value */
1206 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
1207 +/* NTALK2 */
1208 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
1209 +#define TRY_HERE       10      /* Not on this machine, try this      */
1210 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
1211 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
1212 +
1213 +/* We don't really need much for talk */
1214 +struct ip_ct_talk_expect
1215 +{
1216 +       /* Port that was to be used */
1217 +       u_int16_t port;
1218 +};
1219 +
1220 +/* This structure exists only once per master */
1221 +struct ip_ct_talk_master
1222 +{
1223 +};
1224 +
1225 +#endif /* _IP_CONNTRACK_TALK_H */
1226 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
1227 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h    2003-11-26 21:44:58.000000000 +0100
1228 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_conntrack_tuple.h        2003-12-11 10:23:59.480895504 +0100
1229 @@ -14,7 +14,7 @@
1230  union ip_conntrack_manip_proto
1231  {
1232         /* Add other protocols here. */
1233 -       u_int16_t all;
1234 +       u_int32_t all;
1235  
1236         struct {
1237                 u_int16_t port;
1238 @@ -25,6 +25,9 @@
1239         struct {
1240                 u_int16_t id;
1241         } icmp;
1242 +       struct {
1243 +               u_int32_t key;
1244 +       } gre;
1245  };
1246  
1247  /* The manipulable part of the tuple. */
1248 @@ -44,7 +47,7 @@
1249                 u_int32_t ip;
1250                 union {
1251                         /* Add other protocols here. */
1252 -                       u_int16_t all;
1253 +                       u_int64_t all;
1254  
1255                         struct {
1256                                 u_int16_t port;
1257 @@ -55,6 +58,11 @@
1258                         struct {
1259                                 u_int8_t type, code;
1260                         } icmp;
1261 +                       struct {
1262 +                               u_int16_t protocol;
1263 +                               u_int8_t version;
1264 +                               u_int32_t key;
1265 +                       } gre;
1266                 } u;
1267  
1268                 /* The protocol. */
1269 @@ -80,10 +88,16 @@
1270  #ifdef __KERNEL__
1271  
1272  #define DUMP_TUPLE(tp)                                         \
1273 -DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n",    \
1274 +DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",      \
1275         (tp), (tp)->dst.protonum,                               \
1276 -       NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all),          \
1277 -       NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
1278 +       NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all),          \
1279 +       NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all))
1280 +
1281 +#define DUMP_TUPLE_RAW(x)                                              \
1282 +       DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\
1283 +       (x), (x)->dst.protonum,                                         \
1284 +       NIPQUAD((x)->src.ip), ntohl((x)->src.u.all),                    \
1285 +       NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all))
1286  
1287  #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
1288  
1289 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
1290 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_nat_pptp.h   1970-01-01 01:00:00.000000000 +0100
1291 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_nat_pptp.h       2003-11-17 09:09:34.000000000 +0100
1292 @@ -0,0 +1,11 @@
1293 +/* PPTP constants and structs */
1294 +#ifndef _NAT_PPTP_H
1295 +#define _NAT_PPTP_H
1296 +
1297 +/* conntrack private data */
1298 +struct ip_nat_pptp {
1299 +       u_int16_t pns_call_id;          /* NAT'ed PNS call id */
1300 +       u_int16_t pac_call_id;          /* NAT'ed PAC call id */
1301 +};
1302 +
1303 +#endif /* _NAT_PPTP_H */
1304 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
1305 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_pool.h       1970-01-01 01:00:00.000000000 +0100
1306 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_pool.h   2003-12-11 10:23:32.943929736 +0100
1307 @@ -0,0 +1,64 @@
1308 +#ifndef _IP_POOL_H
1309 +#define _IP_POOL_H
1310 +
1311 +/***************************************************************************/
1312 +/*  This program is free software; you can redistribute it and/or modify   */
1313 +/*  it under the terms of the GNU General Public License as published by   */
1314 +/*  the Free Software Foundation; either version 2 of the License, or     */
1315 +/*  (at your option) any later version.                                           */
1316 +/*                                                                        */
1317 +/*  This program is distributed in the hope that it will be useful,       */
1318 +/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
1319 +/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
1320 +/*  GNU General Public License for more details.                          */
1321 +/*                                                                        */
1322 +/*  You should have received a copy of the GNU General Public License     */
1323 +/*  along with this program; if not, write to the Free Software                   */
1324 +/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
1325 +/***************************************************************************/
1326 +
1327 +/* A sockopt of such quality has hardly ever been seen before on the open
1328 + * market!  This little beauty, hardly ever used: above 64, so it's
1329 + * traditionally used for firewalling, not touched (even once!) by the
1330 + * 2.0, 2.2 and 2.4 kernels!
1331 + *
1332 + * Comes with its own certificate of authenticity, valid anywhere in the
1333 + * Free world!
1334 + *
1335 + * Rusty, 19.4.2000
1336 + */
1337 +#define SO_IP_POOL 81
1338 +
1339 +typedef int ip_pool_t;                 /* pool index */
1340 +#define IP_POOL_NONE   ((ip_pool_t)-1)
1341 +
1342 +struct ip_pool_request {
1343 +       int op;
1344 +       ip_pool_t index;
1345 +       u_int32_t addr;
1346 +       u_int32_t addr2;
1347 +};
1348 +
1349 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
1350 +
1351 +#define IP_POOL_BAD001         0x00000010
1352 +
1353 +#define IP_POOL_FLUSH          0x00000011      /* req.index, no arguments */
1354 +#define IP_POOL_INIT           0x00000012      /* from addr to addr2 incl. */
1355 +#define IP_POOL_DESTROY                0x00000013      /* req.index, no arguments */
1356 +#define IP_POOL_ADD_ADDR       0x00000014      /* add addr to pool */
1357 +#define IP_POOL_DEL_ADDR       0x00000015      /* del addr from pool */
1358 +#define IP_POOL_HIGH_NR                0x00000016      /* result in req.index */
1359 +#define IP_POOL_LOOKUP         0x00000017      /* result in addr and addr2 */
1360 +#define IP_POOL_USAGE          0x00000018      /* result in addr */
1361 +#define IP_POOL_TEST_ADDR      0x00000019      /* result (0/1) returned */
1362 +
1363 +#ifdef __KERNEL__
1364 +
1365 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
1366 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
1367 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
1368 +
1369 +#endif
1370 +
1371 +#endif /*_IP_POOL_H*/
1372 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
1373 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_queue.h      2003-11-26 21:45:32.000000000 +0100
1374 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_queue.h  2003-12-11 10:24:12.844863872 +0100
1375 @@ -47,10 +47,20 @@
1376         unsigned char payload[0];       /* Optional replacement packet */
1377  } ipq_verdict_msg_t;
1378  
1379 +typedef struct ipq_vwmark_msg {
1380 +       unsigned int value;             /* Verdict to hand to netfilter */
1381 +       unsigned long id;               /* Packet ID for this verdict */
1382 +       size_t data_len;                /* Length of replacement data */
1383 +       unsigned char payload[0];       /* Optional replacement packet */
1384 +       unsigned long nfmark;           /* Mark for the Packet */
1385 +} ipq_vwmark_msg_t;
1386 +
1387 +
1388  typedef struct ipq_peer_msg {
1389         union {
1390                 ipq_verdict_msg_t verdict;
1391                 ipq_mode_msg_t mode;
1392 +                ipq_vwmark_msg_t vwmark;
1393         } msg;
1394  } ipq_peer_msg_t;
1395  
1396 @@ -67,6 +77,7 @@
1397  #define IPQM_MODE      (IPQM_BASE + 1)         /* Mode request from peer */
1398  #define IPQM_VERDICT   (IPQM_BASE + 2)         /* Verdict from peer */ 
1399  #define IPQM_PACKET    (IPQM_BASE + 3)         /* Packet from kernel */
1400 -#define IPQM_MAX       (IPQM_BASE + 4)
1401 +#define IPQM_VWMARK    (IPQM_BASE + 4)         /* Verdict and mark from peer */
1402 +#define IPQM_MAX       (IPQM_BASE + 5)
1403  
1404  #endif /*_IP_QUEUE_H*/
1405 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
1406 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ip_tables.h     2003-11-26 21:44:17.000000000 +0100
1407 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ip_tables.h 2003-12-11 10:23:17.222319784 +0100
1408 @@ -134,6 +134,12 @@
1409         /* Back pointer */
1410         unsigned int comefrom;
1411  
1412 +       /* Name of the chain */
1413 +       char *chainname;
1414 +       
1415 +       /* Rule number in the chain. */
1416 +       u_int32_t rulenum;
1417 +
1418         /* Packet and byte counters. */
1419         struct ipt_counters counters;
1420  
1421 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
1422 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_addrtype.h  1970-01-01 01:00:00.000000000 +0100
1423 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_addrtype.h      2003-12-11 10:23:44.236213048 +0100
1424 @@ -0,0 +1,11 @@
1425 +#ifndef _IPT_ADDRTYPE_H
1426 +#define _IPT_ADDRTYPE_H
1427 +
1428 +struct ipt_addrtype_info {
1429 +       u_int16_t       source;         /* source-type mask */
1430 +       u_int16_t       dest;           /* dest-type mask */
1431 +       int             invert_source;
1432 +       int             invert_dest;
1433 +};
1434 +
1435 +#endif
1436 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
1437 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_condition.h 1970-01-01 01:00:00.000000000 +0100
1438 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_condition.h     2003-12-11 10:23:46.621850376 +0100
1439 @@ -0,0 +1,11 @@
1440 +#ifndef __IPT_CONDITION_MATCH__
1441 +#define __IPT_CONDITION_MATCH__
1442 +
1443 +#define CONDITION_NAME_LEN  32
1444 +
1445 +struct condition_info {
1446 +       char name[CONDITION_NAME_LEN];
1447 +       int  invert;
1448 +};
1449 +
1450 +#endif
1451 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
1452 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
1453 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connlimit.h     2003-12-11 10:23:19.417985992 +0100
1454 @@ -0,0 +1,12 @@
1455 +#ifndef _IPT_CONNLIMIT_H
1456 +#define _IPT_CONNLIMIT_H
1457 +
1458 +struct ipt_connlimit_data;
1459 +
1460 +struct ipt_connlimit_info {
1461 +       int limit;
1462 +       int inverse;
1463 +       u_int32_t mask;
1464 +       struct ipt_connlimit_data *data;
1465 +};
1466 +#endif /* _IPT_CONNLIMIT_H */
1467 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
1468 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_connmark.h  1970-01-01 01:00:00.000000000 +0100
1469 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_connmark.h      2003-12-11 10:23:47.827667064 +0100
1470 @@ -0,0 +1,9 @@
1471 +#ifndef _IPT_CONNMARK_H
1472 +#define _IPT_CONNMARK_H
1473 +
1474 +struct ipt_connmark_info {
1475 +       unsigned long mark, mask;
1476 +       u_int8_t invert;
1477 +};
1478 +
1479 +#endif /*_IPT_CONNMARK_H*/
1480 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
1481 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h  1970-01-01 01:00:00.000000000 +0100
1482 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_CONNMARK.h      2003-12-11 10:23:47.828666912 +0100
1483 @@ -0,0 +1,15 @@
1484 +#ifndef _IPT_CONNMARK_H_target
1485 +#define _IPT_CONNMARK_H_target
1486 +
1487 +enum {
1488 +    IPT_CONNMARK_SET = 0,
1489 +    IPT_CONNMARK_SAVE,
1490 +    IPT_CONNMARK_RESTORE
1491 +};
1492 +
1493 +struct ipt_connmark_target_info {
1494 +       unsigned long mark;
1495 +       u_int8_t mode;
1496 +};
1497 +
1498 +#endif /*_IPT_CONNMARK_H_target*/
1499 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
1500 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_conntrack.h 2003-11-26 21:45:07.000000000 +0100
1501 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_conntrack.h     2003-12-11 10:23:17.222319784 +0100
1502 @@ -10,6 +10,7 @@
1503  
1504  #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
1505  #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
1506 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
1507  
1508  /* flags, invflags: */
1509  #define IPT_CONNTRACK_STATE    0x01
1510 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
1511 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_dstlimit.h  1970-01-01 01:00:00.000000000 +0100
1512 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_dstlimit.h      2003-12-11 10:23:20.526817424 +0100
1513 @@ -0,0 +1,36 @@
1514 +#ifndef _IPT_DSTLIMIT_H
1515 +#define _IPT_DSTLIMIT_H
1516 +
1517 +/* timings are in milliseconds. */
1518 +#define IPT_DSTLIMIT_SCALE 10000
1519 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
1520 +   seconds, or one every 59 hours. */
1521 +
1522 +/* details of this structure hidden by the implementation */
1523 +struct ipt_dstlimit_htable;
1524 +
1525 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
1526 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
1527 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
1528 +
1529 +struct ipt_dstlimit_info {
1530 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
1531 +       u_int32_t avg;    /* Average secs between packets * scale */
1532 +       u_int32_t burst;  /* Period multiplier for upper limit. */
1533 +
1534 +       /* user specified */
1535 +       unsigned int size;              /* how many buckets */
1536 +       unsigned int max;               /* max number of entries */
1537 +       unsigned int gc_interval;       /* gc interval */
1538 +       unsigned int expire;            /* when do entries expire? */
1539 +       char name [IFNAMSIZ];           /* name */
1540 +
1541 +       struct ipt_dstlimit_htable *hinfo;
1542 +
1543 +       /* Used internally by the kernel */
1544 +       union {
1545 +               void *ptr;
1546 +               struct ipt_dstlimit_info *master;
1547 +       } u;
1548 +};
1549 +#endif /*_IPT_DSTLIMIT_H*/
1550 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
1551 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_fuzzy.h     1970-01-01 01:00:00.000000000 +0100
1552 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_fuzzy.h 2003-12-11 10:23:22.734481808 +0100
1553 @@ -0,0 +1,21 @@
1554 +#ifndef _IPT_FUZZY_H
1555 +#define _IPT_FUZZY_H
1556 +
1557 +#include <linux/param.h>
1558 +#include <linux/types.h>
1559 +
1560 +#define MAXFUZZYRATE 10000000
1561 +#define MINFUZZYRATE 3
1562 +
1563 +struct ipt_fuzzy_info {
1564 +       u_int32_t minimum_rate;
1565 +       u_int32_t maximum_rate;
1566 +       u_int32_t packets_total;
1567 +       u_int32_t bytes_total;
1568 +       u_int32_t previous_time;
1569 +       u_int32_t present_time;
1570 +       u_int32_t mean_rate;
1571 +       u_int8_t acceptance_rate;
1572 +};
1573 +
1574 +#endif /*_IPT_FUZZY_H*/
1575 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
1576 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_IPMARK.h    1970-01-01 01:00:00.000000000 +0100
1577 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_IPMARK.h        2003-12-11 10:23:52.557947952 +0100
1578 @@ -0,0 +1,13 @@
1579 +#ifndef _IPT_IPMARK_H_target
1580 +#define _IPT_IPMARK_H_target
1581 +
1582 +struct ipt_ipmark_target_info {
1583 +       unsigned long andmask;
1584 +       unsigned long ormask;
1585 +       unsigned int addr;
1586 +};
1587 +
1588 +#define IPT_IPMARK_SRC    0
1589 +#define IPT_IPMARK_DST    1
1590 +
1591 +#endif /*_IPT_IPMARK_H_target*/
1592 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
1593 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ipv4options.h       1970-01-01 01:00:00.000000000 +0100
1594 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ipv4options.h   2003-12-11 10:23:25.055129016 +0100
1595 @@ -0,0 +1,21 @@
1596 +#ifndef __ipt_ipv4options_h_included__
1597 +#define __ipt_ipv4options_h_included__
1598 +
1599 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
1600 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
1601 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
1602 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
1603 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
1604 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
1605 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
1606 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
1607 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1608 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
1609 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
1610 +
1611 +struct ipt_ipv4options_info {
1612 +       u_int16_t options;
1613 +};
1614 +
1615 +
1616 +#endif /* __ipt_ipv4options_h_included__ */
1617 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
1618 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mark.h      2003-11-26 21:45:46.000000000 +0100
1619 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mark.h  2003-12-11 10:24:14.940545280 +0100
1620 @@ -1,9 +1,16 @@
1621  #ifndef _IPT_MARK_H
1622  #define _IPT_MARK_H
1623  
1624 +enum {
1625 +        IPT_MARK_BIT_OP_NONE,
1626 +        IPT_MARK_BIT_OP_AND,
1627 +        IPT_MARK_BIT_OP_OR
1628 +};
1629 +
1630  struct ipt_mark_info {
1631      unsigned long mark, mask;
1632      u_int8_t invert;
1633 +    u_int8_t bit_op;
1634  };
1635  
1636  #endif /*_IPT_MARK_H*/
1637 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
1638 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_mport.h     1970-01-01 01:00:00.000000000 +0100
1639 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_mport.h 2003-12-11 10:23:27.304787016 +0100
1640 @@ -0,0 +1,24 @@
1641 +#ifndef _IPT_MPORT_H
1642 +#define _IPT_MPORT_H
1643 +#include <linux/netfilter_ipv4/ip_tables.h>
1644 +
1645 +#define IPT_MPORT_SOURCE (1<<0)
1646 +#define IPT_MPORT_DESTINATION (1<<1)
1647 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1648 +
1649 +#define IPT_MULTI_PORTS        15
1650 +
1651 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1652 +/* every entry in ports[] except for the last one has one bit in pflags
1653 + * associated with it. If this bit is set, the port is the first port of
1654 + * a portrange, with the next entry being the last.
1655 + * End of list is marked with pflags bit set and port=65535.
1656 + * If 14 ports are used (last one does not have a pflag), the last port
1657 + * is repeated to fill the last entry in ports[] */
1658 +struct ipt_mport
1659 +{
1660 +       u_int8_t flags:2;                       /* Type of comparison */
1661 +       u_int16_t pflags:14;                    /* Port flags */
1662 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
1663 +};
1664 +#endif /*_IPT_MPORT_H*/
1665 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
1666 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_NETLINK.h   1970-01-01 01:00:00.000000000 +0100
1667 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_NETLINK.h       2003-12-11 10:23:28.409619056 +0100
1668 @@ -0,0 +1,27 @@
1669 +#ifndef _IPT_FWMON_H
1670 +#define _IPT_FWMON_H
1671 +
1672 +/* Bitmask macros */
1673 +#define MASK(x,y) (x & y)
1674 +#define MASK_SET(x,y) x |= y
1675 +#define MASK_UNSET(x,y) x &= ~y
1676 +
1677 +#define USE_MARK       0x00000001
1678 +#define USE_DROP       0x00000002
1679 +#define USE_SIZE       0x00000004
1680 +
1681 +struct ipt_nldata
1682 +{      
1683 +       unsigned int flags;
1684 +       unsigned int mark;
1685 +       unsigned int size;
1686 +};
1687 +
1688 +/* Old header */
1689 +struct netlink_t {
1690 +       unsigned int len;
1691 +       unsigned int mark;
1692 +       char iface[IFNAMSIZ];
1693 +};
1694 +
1695 +#endif /*_IPT_FWMON_H*/
1696 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
1697 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_nth.h       1970-01-01 01:00:00.000000000 +0100
1698 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_nth.h   2003-12-11 10:23:30.639280096 +0100
1699 @@ -0,0 +1,19 @@
1700 +#ifndef _IPT_NTH_H
1701 +#define _IPT_NTH_H
1702 +
1703 +#include <linux/param.h>
1704 +#include <linux/types.h>
1705 +
1706 +#ifndef IPT_NTH_NUM_COUNTERS
1707 +#define IPT_NTH_NUM_COUNTERS 16
1708 +#endif
1709 +
1710 +struct ipt_nth_info {
1711 +       u_int8_t every;
1712 +       u_int8_t not;
1713 +       u_int8_t startat;
1714 +       u_int8_t counter;
1715 +       u_int8_t packet;
1716 +};
1717 +
1718 +#endif /*_IPT_NTH_H*/
1719 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
1720 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_osf.h       1970-01-01 01:00:00.000000000 +0100
1721 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_osf.h   2003-12-11 10:23:31.785105904 +0100
1722 @@ -0,0 +1,121 @@
1723 +/*
1724 + * ipt_osf.h
1725 + *
1726 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1727 + *
1728 + *
1729 + * This program is free software; you can redistribute it and/or modify
1730 + * it under the terms of the GNU General Public License as published by
1731 + * the Free Software Foundation; either version 2 of the License, or
1732 + * (at your option) any later version.
1733 + *
1734 + * This program is distributed in the hope that it will be useful,
1735 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1736 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1737 + * GNU General Public License for more details.
1738 + *
1739 + * You should have received a copy of the GNU General Public License
1740 + * along with this program; if not, write to the Free Software
1741 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1742 + */
1743 +
1744 +#ifndef _IPT_OSF_H
1745 +#define _IPT_OSF_H
1746 +
1747 +#define MAXGENRELEN            32
1748 +#define MAXDETLEN              64
1749 +
1750 +#include <linux/list.h>
1751 +
1752 +struct ipt_osf_info
1753 +{
1754 +       char                    genre[MAXGENRELEN];
1755 +       int                     len;
1756 +       int                     invert; /* UNSUPPORTED */
1757 +};
1758 +
1759 +struct osf_wc
1760 +{
1761 +       char                    wc;
1762 +       unsigned long           val;
1763 +};
1764 +
1765 +/* This struct represents IANA options
1766 + * http://www.iana.org/assignments/tcp-parameters
1767 + */
1768 +struct osf_opt
1769 +{
1770 +       unsigned char           kind;
1771 +       unsigned char           length;
1772 +       struct osf_wc           wc;
1773 +};
1774 +
1775 +#ifdef __KERNEL__
1776 +
1777 +struct osf_finger
1778 +{
1779 +       struct list_head        flist;
1780 +       struct osf_wc           wss;
1781 +       unsigned char           ttl;
1782 +       unsigned char           df;
1783 +       unsigned long           ss;
1784 +       char                    genre[MAXGENRELEN];
1785 +       char                    version[MAXGENRELEN], subtype[MAXGENRELEN];
1786 +       
1787 +       /* Not needed, but for consistency with original table from Michal Zalewski */
1788 +       char                    details[MAXDETLEN]; 
1789 +
1790 +       int                     opt_num;
1791 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1792 +
1793 +};
1794 +
1795 +/* Defines for IANA option kinds */
1796 +
1797 +#define OSFOPT_EOL             0       /* End of options */
1798 +#define OSFOPT_NOP             1       /* NOP */
1799 +#define OSFOPT_MSS             2       /* Maximum segment size */
1800 +#define OSFOPT_WSO             3       /* Window scale option */
1801 +#define OSFOPT_SACKP           4       /* SACK permitted */
1802 +#define OSFOPT_SACK            5       /* SACK */
1803 +#define OSFOPT_ECHO            6       
1804 +#define OSFOPT_ECHOREPLY       7
1805 +#define OSFOPT_TS              8       /* Timestamp option */
1806 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
1807 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
1808 +/* Others are not used in current OSF */
1809 +
1810 +static struct osf_opt IANA_opts[] = 
1811 +{
1812 +       {0, 1,},
1813 +       {1, 1,},
1814 +       {2, 4,},
1815 +       {3, 3,},
1816 +       {4, 2,},
1817 +       {5, 1 ,}, /* SACK length is not defined */
1818 +       {6, 6,},
1819 +       {7, 6,},
1820 +       {8, 10,},
1821 +       {9, 2,},
1822 +       {10, 3,},
1823 +       {11, 1,}, /* CC: Suppose 1 */
1824 +       {12, 1,}, /* the same */
1825 +       {13, 1,}, /* and here too */
1826 +       {14, 3,},
1827 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1828 +       {16, 1,},
1829 +       {17, 1,},
1830 +       {18, 3,},
1831 +       {19, 18,},
1832 +       {20, 1,},
1833 +       {21, 1,},
1834 +       {22, 1,},
1835 +       {23, 1,},
1836 +       {24, 1,},
1837 +       {25, 1,},
1838 +       {26, 1,},
1839 +};
1840 +
1841 +#endif /* __KERNEL__ */
1842 +
1843 +#endif /* _IPT_OSF_H */
1844 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
1845 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_pool.h      1970-01-01 01:00:00.000000000 +0100
1846 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_pool.h  2003-12-11 10:23:32.943929736 +0100
1847 @@ -0,0 +1,25 @@
1848 +#ifndef _IPT_POOL_H
1849 +#define _IPT_POOL_H
1850 +
1851 +#include <linux/netfilter_ipv4/ip_pool.h>
1852 +
1853 +#define IPT_POOL_INV_SRC       0x00000001
1854 +#define IPT_POOL_INV_DST       0x00000002
1855 +#define IPT_POOL_DEL_SRC       0x00000004
1856 +#define IPT_POOL_DEL_DST       0x00000008
1857 +#define IPT_POOL_INV_MOD_SRC   0x00000010
1858 +#define IPT_POOL_INV_MOD_DST   0x00000020
1859 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
1860 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
1861 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
1862 +#define IPT_POOL_MOD_DST_DROP  0x00000200
1863 +
1864 +/* match info */
1865 +struct ipt_pool_info
1866 +{
1867 +       ip_pool_t src;
1868 +       ip_pool_t dst;
1869 +       unsigned flags;
1870 +};
1871 +
1872 +#endif /*_IPT_POOL_H*/
1873 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
1874 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_psd.h       1970-01-01 01:00:00.000000000 +0100
1875 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_psd.h   2003-12-11 10:23:34.085756152 +0100
1876 @@ -0,0 +1,40 @@
1877 +#ifndef _IPT_PSD_H
1878 +#define _IPT_PSD_H
1879 +
1880 +#include <linux/param.h>
1881 +#include <linux/types.h>
1882 +
1883 +/*
1884 + * High port numbers have a lower weight to reduce the frequency of false
1885 + * positives, such as from passive mode FTP transfers.
1886 + */
1887 +#define PORT_WEIGHT_PRIV               3
1888 +#define PORT_WEIGHT_HIGH               1
1889 +
1890 +/*
1891 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1892 + * from the same source, with no longer than DELAY ticks between ports.
1893 + */
1894 +#define SCAN_MIN_COUNT                 7
1895 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1896 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
1897 +#define SCAN_DELAY_THRESHOLD           (HZ * 3)
1898 +
1899 +/*
1900 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1901 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1902 + * HASH_MAX source addresses per the same hash value.
1903 + */
1904 +#define LIST_SIZE                      0x100
1905 +#define HASH_LOG                       9
1906 +#define HASH_SIZE                      (1 << HASH_LOG)
1907 +#define HASH_MAX                       0x10
1908 +
1909 +struct ipt_psd_info {
1910 +       unsigned int weight_threshold;
1911 +       unsigned int delay_threshold;
1912 +       unsigned short lo_ports_weight;
1913 +       unsigned short hi_ports_weight;
1914 +};
1915 +
1916 +#endif /*_IPT_PSD_H*/
1917 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
1918 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_quota.h     1970-01-01 01:00:00.000000000 +0100
1919 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_quota.h 2003-12-11 10:23:35.183589256 +0100
1920 @@ -0,0 +1,11 @@
1921 +#ifndef _IPT_QUOTA_H
1922 +#define _IPT_QUOTA_H
1923 +
1924 +/* print debug info in both kernel/netfilter module & iptable library */
1925 +//#define DEBUG_IPT_QUOTA
1926 +
1927 +struct ipt_quota_info {
1928 +        u_int64_t quota;
1929 +};
1930 +
1931 +#endif /*_IPT_QUOTA_H*/
1932 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
1933 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_random.h    1970-01-01 01:00:00.000000000 +0100
1934 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_random.h        2003-12-11 10:23:37.415249992 +0100
1935 @@ -0,0 +1,11 @@
1936 +#ifndef _IPT_RAND_H
1937 +#define _IPT_RAND_H
1938 +
1939 +#include <linux/param.h>
1940 +#include <linux/types.h>
1941 +
1942 +struct ipt_rand_info {
1943 +       u_int8_t average;
1944 +};
1945 +
1946 +#endif /*_IPT_RAND_H*/
1947 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
1948 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_realm.h     1970-01-01 01:00:00.000000000 +0100
1949 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_realm.h 2003-12-11 10:23:38.552077168 +0100
1950 @@ -0,0 +1,9 @@
1951 +#ifndef _IPT_REALM_H
1952 +#define _IPT_REALM_H
1953 +
1954 +struct ipt_realm_info {
1955 +       u_int32_t id;
1956 +       u_int32_t mask;
1957 +       u_int8_t invert;
1958 +};
1959 +#endif /*_IPT_REALM_H*/
1960 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
1961 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_REJECT.h    2003-11-26 21:45:21.000000000 +0100
1962 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_REJECT.h        2003-12-11 10:24:13.907702296 +0100
1963 @@ -15,6 +15,7 @@
1964  
1965  struct ipt_reject_info {
1966         enum ipt_reject_with with;      /* reject type */
1967 +       u_int8_t fake_source_address;  /* 1: fake src addr with original packet dest, 0: no fake */
1968  };
1969  
1970 -#endif /*_IPT_REJECT_H*/
1971 +#endif /* _IPT_REJECT_H */
1972 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
1973 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ROUTE.h     1970-01-01 01:00:00.000000000 +0100
1974 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ROUTE.h 2003-12-11 10:24:02.013510488 +0100
1975 @@ -0,0 +1,22 @@
1976 +/* Header file for iptables ipt_ROUTE target
1977 + *
1978 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
1979 + *
1980 + * This software is distributed under GNU GPL v2, 1991
1981 + */
1982 +#ifndef _IPT_ROUTE_H_target
1983 +#define _IPT_ROUTE_H_target
1984 +
1985 +#define IPT_ROUTE_IFNAMSIZ 16
1986 +
1987 +struct ipt_route_target_info {
1988 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
1989 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
1990 +       u_int32_t gw;                           /* IP address of gateway */
1991 +       u_int8_t  flags;
1992 +};
1993 +
1994 +/* Values for "flags" field */
1995 +#define IPT_ROUTE_CONTINUE        0x01
1996 +
1997 +#endif /*_IPT_ROUTE_H_target*/
1998 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
1999 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_rpc.h       1970-01-01 01:00:00.000000000 +0100
2000 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_rpc.h   2003-12-11 10:24:04.354154656 +0100
2001 @@ -0,0 +1,35 @@
2002 +/* RPC extension for IP netfilter matching, Version 2.2
2003 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2004 + *     - original rpc tracking module
2005 + *     - "recent" connection handling for kernel 2.3+ netfilter
2006 + *
2007 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2008 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2009 + *
2010 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2011 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
2012 + *     - extended matching to support filtering on procedures
2013 + *
2014 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
2015 + *
2016 + *     This program is free software; you can redistribute it and/or
2017 + *     modify it under the terms of the GNU General Public License
2018 + *     as published by the Free Software Foundation; either version
2019 + *     2 of the License, or (at your option) any later version.
2020 + **
2021 + */
2022 +
2023 +#ifndef _IPT_RPC_H
2024 +#define _IPT_RPC_H
2025 +
2026 +struct ipt_rpc_data;
2027 +
2028 +struct ipt_rpc_info {
2029 +       int inverse;
2030 +       int strict;
2031 +       const char c_procs[1408];
2032 +       int i_procs;
2033 +       struct ipt_rpc_data *data;
2034 +};
2035 +
2036 +#endif /* _IPT_RPC_H */
2037 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
2038 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_sctp.h      1970-01-01 01:00:00.000000000 +0100
2039 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_sctp.h  2003-12-11 10:23:18.302155624 +0100
2040 @@ -0,0 +1,25 @@
2041 +/* iptables module for matching the SCTP header
2042 + *
2043 + * (C) 2003 Harald Welte <laforge@gnumonks.org>
2044 + *
2045 + * This software is distributed under GNU GPL v2, 1991
2046 + *
2047 + * $Id$
2048 + */
2049 +#ifndef _IPT_SCTP_H
2050 +#define _IPT_SCTP_H
2051 +
2052 +struct ipt_sctp_info {
2053 +       u_int16_t spts[2];                      /* Souce port range */
2054 +       u_int16_t dpts[2];                      /* Destination port range */
2055 +       u_int32_t chunks;                       /* chunks to be matched */
2056 +       u_int32_t chunk_mask;                   /* chunk mask to be matched */
2057 +       u_int8_t invflags;                      /* Inverse flags */
2058 +};
2059 +
2060 +#define IPT_SCTP_INV_SRCPT     0x01    /* Invert the sense of source ports */
2061 +#define IPT_SCTP_INV_DSTPT     0x02    /* Invert the sense of dest ports */
2062 +#define IPT_SCTP_INV_CHUNKS    0x03    /* Invert the sense of chunks */
2063 +#define IPT_SCTP_INV_MASK      0x03    /* All possible flags */
2064 +
2065 +#endif /* _IPT_SCTP_H */
2066 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
2067 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_state.h     2003-11-26 21:45:27.000000000 +0100
2068 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_state.h 2003-12-11 10:23:17.223319632 +0100
2069 @@ -4,6 +4,8 @@
2070  #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
2071  #define IPT_STATE_INVALID (1 << 0)
2072  
2073 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
2074 +
2075  struct ipt_state_info
2076  {
2077         unsigned int statemask;
2078 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
2079 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_string.h    1970-01-01 01:00:00.000000000 +0100
2080 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_string.h        2003-12-11 10:24:08.051592560 +0100
2081 @@ -0,0 +1,21 @@
2082 +#ifndef _IPT_STRING_H
2083 +#define _IPT_STRING_H
2084 +
2085 +/* *** PERFORMANCE TWEAK ***
2086 + * Packet size and search string threshold,
2087 + * above which sublinear searches is used. */
2088 +#define IPT_STRING_HAYSTACK_THRESH     100
2089 +#define IPT_STRING_NEEDLE_THRESH       20
2090 +
2091 +#define BM_MAX_NLEN 256
2092 +#define BM_MAX_HLEN 1024
2093 +
2094 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
2095 +
2096 +struct ipt_string_info {
2097 +    char string[BM_MAX_NLEN];
2098 +    u_int16_t invert;
2099 +    u_int16_t len;
2100 +};
2101 +
2102 +#endif /* _IPT_STRING_H */
2103 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
2104 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h    1970-01-01 01:00:00.000000000 +0100
2105 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TCPLAG.h        2003-12-11 10:24:10.437229888 +0100
2106 @@ -0,0 +1,10 @@
2107 +#ifndef _IPT_TCPLAG_H
2108 +#define _IPT_TCPLAG_H
2109 +
2110 +struct ipt_tcplag
2111 +{
2112 +       unsigned char level;
2113 +       unsigned char prefix[ 15 ];
2114 +};
2115 +
2116 +#endif
2117 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
2118 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_time.h      1970-01-01 01:00:00.000000000 +0100
2119 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_time.h  2003-12-11 10:23:40.871724528 +0100
2120 @@ -0,0 +1,13 @@
2121 +#ifndef __ipt_time_h_included__
2122 +#define __ipt_time_h_included__
2123 +
2124 +
2125 +struct ipt_time_info {
2126 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
2127 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
2128 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
2129 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
2130 +};
2131 +
2132 +
2133 +#endif /* __ipt_time_h_included__ */
2134 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
2135 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_TTL.h       1970-01-01 01:00:00.000000000 +0100
2136 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_TTL.h   2003-12-11 10:23:41.987554896 +0100
2137 @@ -0,0 +1,21 @@
2138 +/* TTL modification module for IP tables
2139 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
2140 +
2141 +#ifndef _IPT_TTL_H
2142 +#define _IPT_TTL_H
2143 +
2144 +enum {
2145 +       IPT_TTL_SET = 0,
2146 +       IPT_TTL_INC,
2147 +       IPT_TTL_DEC
2148 +};
2149 +
2150 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
2151 +
2152 +struct ipt_TTL_info {
2153 +       u_int8_t        mode;
2154 +       u_int8_t        ttl;
2155 +};
2156 +
2157 +
2158 +#endif
2159 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
2160 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_u32.h       1970-01-01 01:00:00.000000000 +0100
2161 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_u32.h   2003-12-11 10:23:43.131381008 +0100
2162 @@ -0,0 +1,40 @@
2163 +#ifndef _IPT_U32_H
2164 +#define _IPT_U32_H
2165 +#include <linux/netfilter_ipv4/ip_tables.h>
2166 +
2167 +enum ipt_u32_ops
2168 +{
2169 +       IPT_U32_AND,
2170 +       IPT_U32_LEFTSH,
2171 +       IPT_U32_RIGHTSH,
2172 +       IPT_U32_AT
2173 +};
2174 +
2175 +struct ipt_u32_location_element
2176 +{
2177 +       u_int32_t number;
2178 +       u_int8_t nextop;
2179 +};
2180 +struct ipt_u32_value_element
2181 +{
2182 +       u_int32_t min;
2183 +       u_int32_t max;
2184 +};
2185 +/* *** any way to allow for an arbitrary number of elements?
2186 +   for now I settle for a limit of 10 of each */
2187 +#define U32MAXSIZE 10
2188 +struct ipt_u32_test
2189 +{
2190 +       u_int8_t nnums;
2191 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
2192 +       u_int8_t nvalues;
2193 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
2194 +};
2195 +
2196 +struct ipt_u32
2197 +{
2198 +       u_int8_t ntests;
2199 +       struct ipt_u32_test tests[U32MAXSIZE+1];
2200 +};
2201 +
2202 +#endif /*_IPT_U32_H*/
2203 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
2204 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_ULOG.h      2003-11-26 21:43:39.000000000 +0100
2205 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_ULOG.h  2003-12-11 10:23:14.921669536 +0100
2206 @@ -11,6 +11,9 @@
2207  #define NETLINK_NFLOG  5
2208  #endif
2209  
2210 +#define NFLOG_DEFAULT_NLGROUP          1
2211 +#define NFLOG_DEFAULT_QTHRESHOLD       1
2212 +
2213  #define ULOG_MAC_LEN   80
2214  #define ULOG_PREFIX_LEN        32
2215  
2216 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
2217 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4/ipt_XOR.h       1970-01-01 01:00:00.000000000 +0100
2218 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4/ipt_XOR.h   2003-12-11 10:24:11.736032440 +0100
2219 @@ -0,0 +1,9 @@
2220 +#ifndef _IPT_XOR_H
2221 +#define _IPT_XOR_H
2222 +
2223 +struct ipt_XOR_info {
2224 +       char            key[30];
2225 +       u_int8_t        block_size;
2226 +};
2227 +
2228 +#endif /* _IPT_XOR_H */
2229 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h linux-2.6.0-test11/include/linux/netfilter_ipv4.h
2230 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv4.h       2003-11-26 21:45:25.000000000 +0100
2231 +++ linux-2.6.0-test11/include/linux/netfilter_ipv4.h   2003-12-11 10:23:17.223319632 +0100
2232 @@ -51,6 +51,8 @@
2233  
2234  enum nf_ip_hook_priorities {
2235         NF_IP_PRI_FIRST = INT_MIN,
2236 +       NF_IP_PRI_CONNTRACK_DEFRAG = -400,
2237 +       NF_IP_PRI_RAW = -300,
2238         NF_IP_PRI_CONNTRACK = -200,
2239         NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
2240         NF_IP_PRI_MANGLE = -150,
2241 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
2242 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6_tables.h    2003-11-26 21:45:41.000000000 +0100
2243 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6_tables.h        2003-12-11 10:23:17.223319632 +0100
2244 @@ -140,6 +140,12 @@
2245         /* Back pointer */
2246         unsigned int comefrom;
2247  
2248 +       /* Name of the chain */
2249 +       char *chainname;
2250 +       
2251 +       /* Rule number in the chain. */
2252 +       u_int32_t rulenum;
2253 +
2254         /* Packet and byte counters. */
2255         struct ip6t_counters counters;
2256  
2257 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
2258 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_condition.h        1970-01-01 01:00:00.000000000 +0100
2259 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_condition.h    2003-12-11 10:23:45.446029128 +0100
2260 @@ -0,0 +1,11 @@
2261 +#ifndef __IP6T_CONDITION_MATCH__
2262 +#define __IP6T_CONDITION_MATCH__
2263 +
2264 +#define CONDITION6_NAME_LEN  32
2265 +
2266 +struct condition6_info {
2267 +       char name[CONDITION6_NAME_LEN];
2268 +       int  invert;
2269 +};
2270 +
2271 +#endif
2272 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
2273 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h    1970-01-01 01:00:00.000000000 +0100
2274 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_fuzzy.h        2003-12-11 10:23:21.621650984 +0100
2275 @@ -0,0 +1,21 @@
2276 +#ifndef _IP6T_FUZZY_H
2277 +#define _IP6T_FUZZY_H
2278 +
2279 +#include <linux/param.h>
2280 +#include <linux/types.h>
2281 +
2282 +#define MAXFUZZYRATE 10000000
2283 +#define MINFUZZYRATE 3
2284 +
2285 +struct ip6t_fuzzy_info {
2286 +       u_int32_t minimum_rate;
2287 +       u_int32_t maximum_rate;
2288 +       u_int32_t packets_total;
2289 +       u_int32_t bytes_total;
2290 +       u_int32_t previous_time;
2291 +       u_int32_t present_time;
2292 +       u_int32_t mean_rate;
2293 +       u_int8_t acceptance_rate;
2294 +};
2295 +
2296 +#endif /*_IP6T_FUZZY_H*/
2297 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
2298 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_HL.h       1970-01-01 01:00:00.000000000 +0100
2299 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_HL.h   2003-12-11 10:23:23.851312024 +0100
2300 @@ -0,0 +1,22 @@
2301 +/* Hop Limit modification module for ip6tables
2302 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
2303 + * Based on HW's TTL module */
2304 +
2305 +#ifndef _IP6T_HL_H
2306 +#define _IP6T_HL_H
2307 +
2308 +enum {
2309 +       IP6T_HL_SET = 0,
2310 +       IP6T_HL_INC,
2311 +       IP6T_HL_DEC
2312 +};
2313 +
2314 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
2315 +
2316 +struct ip6t_HL_info {
2317 +       u_int8_t        mode;
2318 +       u_int8_t        hop_limit;
2319 +};
2320 +
2321 +
2322 +#endif
2323 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
2324 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_nth.h      1970-01-01 01:00:00.000000000 +0100
2325 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_nth.h  2003-12-11 10:23:29.532448360 +0100
2326 @@ -0,0 +1,19 @@
2327 +#ifndef _IP6T_NTH_H
2328 +#define _IP6T_NTH_H
2329 +
2330 +#include <linux/param.h>
2331 +#include <linux/types.h>
2332 +
2333 +#ifndef IP6T_NTH_NUM_COUNTERS
2334 +#define IP6T_NTH_NUM_COUNTERS 16
2335 +#endif
2336 +
2337 +struct ip6t_nth_info {
2338 +       u_int8_t every;
2339 +       u_int8_t not;
2340 +       u_int8_t startat;
2341 +       u_int8_t counter;
2342 +       u_int8_t packet;
2343 +};
2344 +
2345 +#endif /*_IP6T_NTH_H*/
2346 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
2347 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_owner.h    2003-11-26 21:44:32.000000000 +0100
2348 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_owner.h        2003-12-11 10:23:58.199090368 +0100
2349 @@ -6,12 +6,14 @@
2350  #define IP6T_OWNER_GID 0x02
2351  #define IP6T_OWNER_PID 0x04
2352  #define IP6T_OWNER_SID 0x08
2353 +#define IP6T_OWNER_COMM 0x10
2354  
2355  struct ip6t_owner_info {
2356      uid_t uid;
2357      gid_t gid;
2358      pid_t pid;
2359      pid_t sid;
2360 +    char comm[16];
2361      u_int8_t match, invert;    /* flags */
2362  };
2363  
2364 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
2365 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_random.h   1970-01-01 01:00:00.000000000 +0100
2366 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_random.h       2003-12-11 10:23:36.320416432 +0100
2367 @@ -0,0 +1,11 @@
2368 +#ifndef _IP6T_RAND_H
2369 +#define _IP6T_RAND_H
2370 +
2371 +#include <linux/param.h>
2372 +#include <linux/types.h>
2373 +
2374 +struct ip6t_rand_info {
2375 +       u_int8_t average;
2376 +};
2377 +
2378 +#endif /*_IP6T_RAND_H*/
2379 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
2380 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_REJECT.h   2003-11-26 21:42:47.000000000 +0100
2381 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_REJECT.h       2003-12-11 10:23:39.702902216 +0100
2382 @@ -2,15 +2,17 @@
2383  #define _IP6T_REJECT_H
2384  
2385  enum ip6t_reject_with {
2386 -       IP6T_ICMP_NET_UNREACHABLE,
2387 -       IP6T_ICMP_HOST_UNREACHABLE,
2388 -       IP6T_ICMP_PROT_UNREACHABLE,
2389 -       IP6T_ICMP_PORT_UNREACHABLE,
2390 -       IP6T_ICMP_ECHOREPLY
2391 +       IP6T_ICMP6_NO_ROUTE,
2392 +       IP6T_ICMP6_ADM_PROHIBITED,
2393 +       IP6T_ICMP6_NOT_NEIGHBOUR,
2394 +       IP6T_ICMP6_ADDR_UNREACH,
2395 +       IP6T_ICMP6_PORT_UNREACH,
2396 +       IP6T_ICMP6_ECHOREPLY,
2397 +       IP6T_TCP_RESET
2398  };
2399  
2400  struct ip6t_reject_info {
2401         enum ip6t_reject_with with;      /* reject type */
2402  };
2403  
2404 -#endif /*_IPT_REJECT_H*/
2405 +#endif /*_IP6T_REJECT_H*/
2406 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
2407 --- linux-2.6.0-test11.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h    1970-01-01 01:00:00.000000000 +0100
2408 +++ linux-2.6.0-test11/include/linux/netfilter_ipv6/ip6t_ROUTE.h        2003-12-11 10:24:03.166335232 +0100
2409 @@ -0,0 +1,22 @@
2410 +/* Header file for iptables ip6t_ROUTE target
2411 + *
2412 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
2413 + *
2414 + * This software is distributed under GNU GPL v2, 1991
2415 + */
2416 +#ifndef _IPT_ROUTE_H_target
2417 +#define _IPT_ROUTE_H_target
2418 +
2419 +#define IP6T_ROUTE_IFNAMSIZ 16
2420 +
2421 +struct ip6t_route_target_info {
2422 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
2423 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
2424 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
2425 +       u_int8_t  flags;
2426 +};
2427 +
2428 +/* Values for "flags" field */
2429 +#define IP6T_ROUTE_CONTINUE        0x01
2430 +
2431 +#endif /*_IP6T_ROUTE_H_target*/
2432 diff -Nur linux-2.6.0-test11.org/include/linux/netfilter_mime.h linux-2.6.0-test11/include/linux/netfilter_mime.h
2433 --- linux-2.6.0-test11.org/include/linux/netfilter_mime.h       1970-01-01 01:00:00.000000000 +0100
2434 +++ linux-2.6.0-test11/include/linux/netfilter_mime.h   2003-12-11 10:24:06.855774352 +0100
2435 @@ -0,0 +1,89 @@
2436 +/*
2437 + * MIME functions for netfilter modules.  This file provides implementations
2438 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
2439 + * HTTP, RTSP, SIP, etc.
2440 + *
2441 + * gcc will warn for defined but unused functions, so we only include the
2442 + * functions requested.  The following macros are used:
2443 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
2444 + */
2445 +#ifndef _NETFILTER_MIME_H
2446 +#define _NETFILTER_MIME_H
2447 +
2448 +/* Only include these functions for kernel code. */
2449 +#ifdef __KERNEL__
2450 +
2451 +#include <linux/ctype.h>
2452 +
2453 +/*
2454 + * Given a buffer and length, advance to the next line and mark the current
2455 + * line.  If the current line is empty, *plinelen will be set to zero.  If
2456 + * not, it will be set to the actual line length (including CRLF).
2457 + *
2458 + * 'line' in this context means logical line (includes LWS continuations).
2459 + * Returns 1 on success, 0 on failure.
2460 + */
2461 +#ifdef NF_NEED_MIME_NEXTLINE
2462 +static int
2463 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2464 +{
2465 +    uint    off = *poff;
2466 +    uint    physlen = 0;
2467 +    int     is_first_line = 1;
2468 +
2469 +    if (off >= len)
2470 +    {
2471 +        return 0;
2472 +    }
2473 +
2474 +    do
2475 +    {
2476 +        while (p[off] != '\n')
2477 +        {
2478 +            if (len-off <= 1)
2479 +            {
2480 +                return 0;
2481 +            }
2482 +
2483 +            physlen++;
2484 +            off++;
2485 +        }
2486 +
2487 +        /* if we saw a crlf, physlen needs adjusted */
2488 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2489 +        {
2490 +            physlen--;
2491 +        }
2492 +
2493 +        /* advance past the newline */
2494 +        off++;
2495 +
2496 +        /* check for an empty line */
2497 +        if (physlen == 0)
2498 +        {
2499 +            break;
2500 +        }
2501 +
2502 +        /* check for colon on the first physical line */
2503 +        if (is_first_line)
2504 +        {
2505 +            is_first_line = 0;
2506 +            if (memchr(p+(*poff), ':', physlen) == NULL)
2507 +            {
2508 +                return 0;
2509 +            }
2510 +        }
2511 +    }
2512 +    while (p[off] == ' ' || p[off] == '\t');
2513 +
2514 +    *plineoff = *poff;
2515 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
2516 +    *poff = off;
2517 +
2518 +    return 1;
2519 +}
2520 +#endif /* NF_NEED_MIME_NEXTLINE */
2521 +
2522 +#endif /* __KERNEL__ */
2523 +
2524 +#endif /* _NETFILTER_MIME_H */
2525 diff -Nur linux-2.6.0-test11.org/include/linux/smp.h linux-2.6.0-test11/include/linux/smp.h
2526 --- linux-2.6.0-test11.org/include/linux/smp.h  2003-11-26 21:44:20.000000000 +0100
2527 +++ linux-2.6.0-test11/include/linux/smp.h      2003-12-11 11:43:37.505525352 +0100
2528 @@ -74,6 +74,8 @@
2529   */
2530  extern int smp_threads_ready;
2531  
2532 +extern int smp_num_cpus;
2533 +
2534  #define MSG_ALL_BUT_SELF       0x8000  /* Assume <32768 CPU's */
2535  #define MSG_ALL                        0x8001
2536  
2537 diff -Nur linux-2.6.0-test11.org/net/core/netfilter.c linux-2.6.0-test11/net/core/netfilter.c
2538 --- linux-2.6.0-test11.org/net/core/netfilter.c 2003-11-26 21:43:56.000000000 +0100
2539 +++ linux-2.6.0-test11/net/core/netfilter.c     2003-12-11 10:23:57.175246016 +0100
2540 @@ -8,8 +8,10 @@
2541   *
2542   * February 2000: Modified by James Morris to have 1 queue per protocol.
2543   * 15-Mar-2000:   Added NF_REPEAT --RR.
2544 + * 08-May-2003:          Internal logging interface added by Jozsef Kadlecsik.
2545   */
2546  #include <linux/config.h>
2547 +#include <linux/kernel.h>
2548  #include <linux/netfilter.h>
2549  #include <net/protocol.h>
2550  #include <linux/init.h>
2551 @@ -61,6 +63,10 @@
2552  } queue_handler[NPROTO];
2553  static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
2554  
2555 +/**
2556 + * nf_register_hook - Register with a netfilter hook
2557 + * @reg: Hook operations to be registered
2558 + */
2559  int nf_register_hook(struct nf_hook_ops *reg)
2560  {
2561         struct list_head *i;
2562 @@ -77,6 +83,10 @@
2563         return 0;
2564  }
2565  
2566 +/**
2567 + * nf_unregister_hook - Unregister from a netfilter hook
2568 + * @reg: hook operations to be unregistered
2569 + */
2570  void nf_unregister_hook(struct nf_hook_ops *reg)
2571  {
2572         spin_lock_bh(&nf_hook_lock);
2573 @@ -389,6 +399,18 @@
2574         return NF_ACCEPT;
2575  }
2576  
2577 +/**
2578 + * nf_register_queue_handler - Registere a queue handler with netfilter
2579 + * @pf: protocol family
2580 + * @outfn: function called by core to enqueue a packet
2581 + * @data: opaque parameter, passed through
2582 + *
2583 + * This function registers a queue handler with netfilter.  There can only
2584 + * be one queue handler for every protocol family.
2585 + *
2586 + * A queue handler _must_ reinject every packet via nf_reinject, no
2587 + * matter what.
2588 + */
2589  int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
2590  {      
2591         int ret;
2592 @@ -406,7 +428,12 @@
2593         return ret;
2594  }
2595  
2596 -/* The caller must flush their queue before this */
2597 +/**
2598 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
2599 + * @pf: protocol family
2600 + *
2601 + * The caller must flush their queue before unregistering
2602 + */
2603  int nf_unregister_queue_handler(int pf)
2604  {
2605         write_lock_bh(&queue_handler_lock);
2606 @@ -549,6 +576,15 @@
2607         return ret;
2608  }
2609  
2610 +/**
2611 + * nf_reinject - Reinject a packet from a queue handler
2612 + * @skb: the packet to be reinjected
2613 + * @info: info which was passed to the outfn() of the queue handler
2614 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
2615 + *
2616 + * This is the function called by a queue handler to reinject a
2617 + * packet.
2618 + */
2619  void nf_reinject(struct sk_buff *skb, struct nf_info *info,
2620                  unsigned int verdict)
2621  {
2622 @@ -743,7 +779,70 @@
2623  EXPORT_SYMBOL(skb_ip_make_writable);
2624  #endif /*CONFIG_INET*/
2625  
2626 +/* Internal logging interface, which relies on the real 
2627 +   LOG target modules */
2628 +
2629 +#define NF_LOG_PREFIXLEN               128
2630 +
2631 +static nf_logfn *nf_logging[NPROTO]; /* = NULL */
2632 +static int reported = 0;
2633 +static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
2634 +
2635 +int nf_log_register(int pf, nf_logfn *logfn)
2636 +{
2637 +       int ret = -EBUSY;
2638 +
2639 +       /* Any setup of logging members must be done before
2640 +        * substituting pointer. */
2641 +       smp_wmb();
2642 +       spin_lock(&nf_log_lock);
2643 +       if (!nf_logging[pf]) {
2644 +               nf_logging[pf] = logfn;
2645 +               ret = 0;
2646 +       }
2647 +       spin_unlock(&nf_log_lock);
2648 +       return ret;
2649 +}              
2650  
2651 +void nf_log_unregister(int pf, nf_logfn *logfn)
2652 +{
2653 +       spin_lock(&nf_log_lock);
2654 +       if (nf_logging[pf] == logfn)
2655 +               nf_logging[pf] = NULL;
2656 +       spin_unlock(&nf_log_lock);
2657 +
2658 +       /* Give time to concurrent readers. */
2659 +       synchronize_net();
2660 +}              
2661 +
2662 +void nf_log_packet(int pf,
2663 +                  unsigned int hooknum,
2664 +                  const struct sk_buff *skb,
2665 +                  const struct net_device *in,
2666 +                  const struct net_device *out,
2667 +                  const char *fmt, ...)
2668 +{
2669 +       va_list args;
2670 +       char prefix[NF_LOG_PREFIXLEN];
2671 +       nf_logfn *logfn;
2672 +       
2673 +       rcu_read_lock();
2674 +       logfn = nf_logging[pf];
2675 +       if (logfn) {
2676 +               va_start(args, fmt);
2677 +               vsnprintf(prefix, sizeof(prefix), fmt, args);
2678 +               va_end(args);
2679 +               /* We must read logging before nf_logfn[pf] */
2680 +               smp_read_barrier_depends();
2681 +               logfn(hooknum, skb, in, out, prefix);
2682 +       } else if (!reported) {
2683 +               printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
2684 +                      "no backend logging module loaded in!\n");
2685 +               reported++;
2686 +       }
2687 +       rcu_read_unlock();
2688 +}
2689
2690  /* This does not belong here, but ipt_REJECT needs it if connection
2691     tracking in use: without this, connection may not be in hash table,
2692     and hence manufactured ICMP or RST packets will not be associated
2693 @@ -763,6 +862,9 @@
2694  EXPORT_SYMBOL(ip_ct_attach);
2695  EXPORT_SYMBOL(ip_route_me_harder);
2696  EXPORT_SYMBOL(nf_getsockopt);
2697 +EXPORT_SYMBOL(nf_log_register);
2698 +EXPORT_SYMBOL(nf_log_unregister);
2699 +EXPORT_SYMBOL(nf_log_packet);
2700  EXPORT_SYMBOL(nf_hook_slow);
2701  EXPORT_SYMBOL(nf_hooks);
2702  EXPORT_SYMBOL(nf_register_hook);
2703 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
2704 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_core.c       2003-11-26 21:42:40.000000000 +0100
2705 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_core.c   2003-12-11 10:24:15.987386136 +0100
2706 @@ -4,6 +4,7 @@
2707  
2708  /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
2709   * Public Licence. 
2710 + * (C) 2000-2003 by the netfilter core team <coreteam@netfilter.org>
2711   *
2712   * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
2713   *     - new API and handling of conntrack/nat helpers
2714 @@ -11,6 +12,8 @@
2715   * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
2716   *     - add usage/reference counts to ip_conntrack_expect
2717   *     - export ip_conntrack[_expect]_{find_get,put} functions
2718 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
2719 + *     - added DocBook-style comments for public API
2720   * */
2721  
2722  #include <linux/config.h>
2723 @@ -29,8 +32,7 @@
2724  #include <linux/slab.h>
2725  #include <linux/random.h>
2726  #include <linux/jhash.h>
2727 -/* For ERR_PTR().  Yeah, I know... --RR */
2728 -#include <linux/fs.h>
2729 +#include <linux/err.h>
2730  
2731  /* This rwlock protects the main hash table, protocol/helper/expected
2732     registrations, conntrack timers*/
2733 @@ -63,6 +65,7 @@
2734  static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
2735  struct list_head *ip_conntrack_hash;
2736  static kmem_cache_t *ip_conntrack_cachep;
2737 +struct ip_conntrack ip_conntrack_untracked;
2738  
2739  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
2740  
2741 @@ -85,6 +88,10 @@
2742         return p;
2743  }
2744  
2745 +/**
2746 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
2747 + * @protocol: protocol number
2748 + */
2749  struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
2750  {
2751         struct ip_conntrack_protocol *p;
2752 @@ -150,6 +157,8 @@
2753         inverse->dst.ip = orig->src.ip;
2754         inverse->dst.protonum = orig->dst.protonum;
2755  
2756 +       inverse->src.u.all = inverse->dst.u.all = 0;
2757 +
2758         return protocol->invert_tuple(inverse, orig);
2759  }
2760  
2761 @@ -342,7 +351,7 @@
2762         atomic_dec(&ip_conntrack_count);
2763  }
2764  
2765 -static void death_by_timeout(unsigned long ul_conntrack)
2766 +void ip_ct_death_by_timeout(unsigned long ul_conntrack)
2767  {
2768         struct ip_conntrack *ct = (void *)ul_conntrack;
2769  
2770 @@ -377,7 +386,14 @@
2771         return h;
2772  }
2773  
2774 -/* Find a connection corresponding to a tuple. */
2775 +/**
2776 + * ip_conntrack_find_get - find conntrack according to tuple
2777 + * @tuple: conntrack tuple for which we search conntrack
2778 + * @ignored_conntrack: ignore this conntrack during search
2779 + *
2780 + * This function increments the reference count of the found
2781 + * conntrack (if any).
2782 + */
2783  struct ip_conntrack_tuple_hash *
2784  ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
2785                       const struct ip_conntrack *ignored_conntrack)
2786 @@ -405,7 +421,14 @@
2787         return ct;
2788  }
2789  
2790 -/* Return conntrack and conntrack_info given skb->nfct->master */
2791 +/**
2792 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
2793 + * @skb: skb for which we want to find conntrack and conntrack_info
2794 + * @ctinfo: pointer to ctinfo, used as return value
2795 + *
2796 + * This function resolves the respective conntrack and conntrack_info
2797 + * structures for the connection this packet (skb) is part of.
2798 + */
2799  struct ip_conntrack *
2800  ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
2801  {
2802 @@ -475,8 +498,14 @@
2803         return NF_DROP;
2804  }
2805  
2806 -/* Returns true if a connection correspondings to the tuple (required
2807 -   for NAT). */
2808 +/**
2809 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
2810 + * @tuple: tuple to be used for this test
2811 + * @ignored_conntrack: conntrack which is excluded from result
2812 + *
2813 + * This function is called by the NAT code in order to find out if
2814 + * a particular tuple is already in use by some connection.
2815 + */
2816  int
2817  ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
2818                          const struct ip_conntrack *ignored_conntrack)
2819 @@ -590,7 +619,7 @@
2820                 return dropped;
2821  
2822         if (del_timer(&h->ctrack->timeout)) {
2823 -               death_by_timeout((unsigned long)h->ctrack);
2824 +               ip_ct_death_by_timeout((unsigned long)h->ctrack);
2825                 dropped = 1;
2826         }
2827         ip_conntrack_put(h->ctrack);
2828 @@ -602,7 +631,13 @@
2829  {
2830         return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
2831  }
2832 -
2833 +/**
2834 + * ip_ct_find_helper - Find application helper according to tuple
2835 + * @tuple: tuple for which helper needs to be found
2836 + *
2837 + * This function is used to determine if any registered conntrack helper
2838 + * is to be used for the given tuple.
2839 + */
2840  struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
2841  {
2842         return LIST_FIND(&helpers, helper_cmp,
2843 @@ -676,7 +711,7 @@
2844         /* Don't set timer yet: wait for confirmation */
2845         init_timer(&conntrack->timeout);
2846         conntrack->timeout.data = (unsigned long)conntrack;
2847 -       conntrack->timeout.function = death_by_timeout;
2848 +       conntrack->timeout.function = ip_ct_death_by_timeout;
2849  
2850         INIT_LIST_HEAD(&conntrack->sibling_list);
2851  
2852 @@ -713,6 +748,9 @@
2853                 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
2854                 conntrack->master = expected;
2855                 expected->sibling = conntrack;
2856 +#if CONFIG_IP_NF_CONNTRACK_MARK
2857 +               conntrack->mark = expected->expectant->mark;
2858 +#endif
2859                 LIST_DELETE(&ip_conntrack_expect_list, expected);
2860                 expected->expectant->expecting--;
2861                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
2862 @@ -790,6 +828,15 @@
2863         int set_reply;
2864         int ret;
2865  
2866 +       /* Never happen */
2867 +       if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) {
2868 +               if (net_ratelimit()) {
2869 +               printk(KERN_ERR "ip_conntrack_in: Frag of proto %u (hook=%u)\n",
2870 +                      (*pskb)->nh.iph->protocol, hooknum);
2871 +               }
2872 +               return NF_DROP;
2873 +       }
2874 +
2875         /* FIXME: Do this right please. --RR */
2876         (*pskb)->nfcache |= NFC_UNKNOWN;
2877  
2878 @@ -808,18 +855,10 @@
2879         }
2880  #endif
2881  
2882 -       /* Previously seen (loopback)?  Ignore.  Do this before
2883 -           fragment check. */
2884 +       /* Previously seen (loopback or untracked)?  Ignore. */
2885         if ((*pskb)->nfct)
2886                 return NF_ACCEPT;
2887  
2888 -       /* Gather fragments. */
2889 -       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
2890 -               *pskb = ip_ct_gather_frags(*pskb);
2891 -               if (!*pskb)
2892 -                       return NF_STOLEN;
2893 -       }
2894 -
2895         proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
2896  
2897         /* It may be an icmp error... */
2898 @@ -896,6 +935,14 @@
2899         return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
2900  }
2901  
2902 +/**
2903 + * ip_conntrack_unexpect_related - Unexpect a related connection
2904 + * @expect: expecattin to be removed
2905 + *
2906 + * This function removes an existing expectation, that has not yet been
2907 + * confirmed (i.e. expectation was issued, but expected connection didn't
2908 + * arrive yet)
2909 + */
2910  inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
2911  {
2912         WRITE_LOCK(&ip_conntrack_lock);
2913 @@ -913,7 +960,20 @@
2914         WRITE_UNLOCK(&ip_conntrack_lock);
2915  }
2916  
2917 -/* Add a related connection. */
2918 +/**
2919 + * ip_conntrack_expect_related - Expect a related connection
2920 + * @related_to: master conntrack
2921 + * @expect: expectation with all values filled in
2922 + *
2923 + * This function is called by conntrack application helpers who
2924 + * have detected that the control (master) connection is just about
2925 + * to negotiate a related slave connection. 
2926 + *
2927 + * Note: This function allocates it's own struct ip_conntrack_expect,
2928 + * copying the values from the 'expect' parameter.  Thus, 'expect' can
2929 + * be allocated on the stack and does not need to be valid after this
2930 + * function returns.
2931 + */
2932  int ip_conntrack_expect_related(struct ip_conntrack *related_to,
2933                                 struct ip_conntrack_expect *expect)
2934  {
2935 @@ -925,8 +985,8 @@
2936          * so there is no need to use the tuple lock too */
2937  
2938         DEBUGP("ip_conntrack_expect_related %p\n", related_to);
2939 -       DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
2940 -       DEBUGP("mask:  "); DUMP_TUPLE(&expect->mask);
2941 +       DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
2942 +       DEBUGP("mask:  "); DUMP_TUPLE_RAW(&expect->mask);
2943  
2944         old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
2945                         struct ip_conntrack_expect *, &expect->tuple, 
2946 @@ -953,7 +1013,6 @@
2947                 }
2948         } else if (related_to->helper->max_expected && 
2949                    related_to->expecting >= related_to->helper->max_expected) {
2950 -               struct list_head *cur_item;
2951                 /* old == NULL */
2952                 if (!(related_to->helper->flags & 
2953                       IP_CT_HELPER_F_REUSE_EXPECT)) {
2954 @@ -978,21 +1037,14 @@
2955                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
2956   
2957                 /* choose the the oldest expectation to evict */
2958 -               list_for_each(cur_item, &related_to->sibling_list) { 
2959 -                       struct ip_conntrack_expect *cur;
2960 -
2961 -                       cur = list_entry(cur_item, 
2962 -                                        struct ip_conntrack_expect,
2963 -                                        expected_list);
2964 -                       if (cur->sibling == NULL) {
2965 -                               old = cur;
2966 +               list_for_each_entry(old, &related_to->sibling_list, 
2967 +                                                     expected_list)
2968 +                       if (old->sibling == NULL)
2969                                 break;
2970 -                       }
2971 -               }
2972  
2973 -               /* (!old) cannot happen, since related_to->expecting is the
2974 -                * number of unconfirmed expects */
2975 -               IP_NF_ASSERT(old);
2976 +               /* We cannot fail since related_to->expecting is the number
2977 +                * of unconfirmed expectations */
2978 +               IP_NF_ASSERT(old && old->sibling == NULL);
2979  
2980                 /* newnat14 does not reuse the real allocated memory
2981                  * structures but rather unexpects the old and
2982 @@ -1024,7 +1076,7 @@
2983         atomic_set(&new->use, 1);
2984         
2985         /* add to expected list for this connection */  
2986 -       list_add(&new->expected_list, &related_to->sibling_list);
2987 +       list_add_tail(&new->expected_list, &related_to->sibling_list);
2988         /* add to global list of expectations */
2989         list_prepend(&ip_conntrack_expect_list, &new->list);
2990         /* add and start timer if required */
2991 @@ -1043,7 +1095,15 @@
2992         return ret;
2993  }
2994  
2995 -/* Change tuple in an existing expectation */
2996 +/**
2997 + * ip_conntrack_change_expect - Change tuple in existing expectation
2998 + * @expect: expectation which is to be changed
2999 + * @newtuple: new tuple for expect
3000 + *
3001 + * This function is mostly called by NAT application helpers, who want to
3002 + * change an expectation issued by their respective conntrack application
3003 + * helper counterpart.
3004 + */
3005  int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
3006                                struct ip_conntrack_tuple *newtuple)
3007  {
3008 @@ -1051,15 +1111,14 @@
3009  
3010         MUST_BE_READ_LOCKED(&ip_conntrack_lock);
3011         WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
3012 -
3013         DEBUGP("change_expect:\n");
3014 -       DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
3015 -       DEBUGP("exp mask:  "); DUMP_TUPLE(&expect->mask);
3016 -       DEBUGP("newtuple:  "); DUMP_TUPLE(newtuple);
3017 +       DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
3018 +       DEBUGP("exp mask:  "); DUMP_TUPLE_RAW(&expect->mask);
3019 +       DEBUGP("newtuple:  "); DUMP_TUPLE_RAW(newtuple);
3020         if (expect->ct_tuple.dst.protonum == 0) {
3021                 /* Never seen before */
3022                 DEBUGP("change expect: never seen before\n");
3023 -               if (!ip_ct_tuple_equal(&expect->tuple, newtuple) 
3024 +               if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask)
3025                     && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
3026                                  struct ip_conntrack_expect *, newtuple, &expect->mask)) {
3027                         /* Force NAT to find an unused tuple */
3028 @@ -1084,8 +1143,15 @@
3029         return ret;
3030  }
3031  
3032 -/* Alter reply tuple (maybe alter helper).  If it's already taken,
3033 -   return 0 and don't do alteration. */
3034 +/**
3035 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
3036 + * @conntrack: conntrack whose reply tuple we want to alter
3037 + * @newreply: designated reply tuple for this conntrack
3038 + *
3039 + * This function alters the reply tuple of a conntrack to the given
3040 + * newreply tuple.  If this newreply tuple is already taken, return 0
3041 + * and don't do alteration
3042 + */
3043  int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
3044                              const struct ip_conntrack_tuple *newreply)
3045  {
3046 @@ -1110,6 +1176,13 @@
3047         return 1;
3048  }
3049  
3050 +/**
3051 + * ip_conntrack_helper_register - Register a conntrack application helper
3052 + * @me: structure describing the helper
3053 + *
3054 + * This function is called by conntrack application helpers to register
3055 + * themselves with the conntrack core.
3056 + */
3057  int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
3058  {
3059         WRITE_LOCK(&ip_conntrack_lock);
3060 @@ -1131,6 +1204,13 @@
3061         return 0;
3062  }
3063  
3064 +/**
3065 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
3066 + * @me: structure describing the helper
3067 + *
3068 + * This function is called by conntrack application helpers to unregister
3069 + * themselvers from the conntrack core.
3070 + */
3071  void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
3072  {
3073         unsigned int i;
3074 @@ -1149,7 +1229,14 @@
3075         synchronize_net();
3076  }
3077  
3078 -/* Refresh conntrack for this many jiffies. */
3079 +/**
3080 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
3081 + * @ct: conntrack which we want to refresh
3082 + * @extra_jiffies: number of jiffies to add
3083 + *
3084 + * This function is called by protocol helpers and application helpers in
3085 + * order to change the expiration timer of a conntrack entry.
3086 + */
3087  void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
3088  {
3089         IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
3090 @@ -1159,8 +1246,10 @@
3091         if (!is_confirmed(ct))
3092                 ct->timeout.expires = extra_jiffies;
3093         else {
3094 -               /* Need del_timer for race avoidance (may already be dying). */
3095 -               if (del_timer(&ct->timeout)) {
3096 +               /* Don't update timer for each packet, only if it's been >HZ
3097 +                * ticks since last update.
3098 +                * Need del_timer for race avoidance (may already be dying). */
3099 +               if (abs(jiffies + extra_jiffies - ct->timeout.expires) >= HZ && del_timer(&ct->timeout)) {
3100                         ct->timeout.expires = jiffies + extra_jiffies;
3101                         add_timer(&ct->timeout);
3102                 }
3103 @@ -1168,7 +1257,16 @@
3104         WRITE_UNLOCK(&ip_conntrack_lock);
3105  }
3106  
3107 -/* Returns new sk_buff, or NULL */
3108 +
3109 +/**
3110 + * ip_ct_gather_frags - Gather fragments of a particular skb
3111 + * @skb: pointer to sk_buff of fragmented IP packet
3112 + *
3113 + * This code is just a wrapper around the defragmentation code in the core IPv4
3114 + * stack.  It also takes care of nonlinear skb's.
3115 + *
3116 + * Returns new sk_buff, or NULL
3117 + */
3118  struct sk_buff *
3119  ip_ct_gather_frags(struct sk_buff *skb)
3120  {
3121 @@ -1253,6 +1351,16 @@
3122         return h;
3123  }
3124  
3125 +/**
3126 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
3127 + * @kill: callback function selecting which entries to delete
3128 + * @data: opaque data pointer, becomes 2nd argument for kill function
3129 + *
3130 + * This function can be used to selectively delete elements of the conntrack
3131 + * hashtable.  The function iterates over the list of conntrack entries and
3132 + * calls the 'kill' function for every entry.  If the return value is true,
3133 + * the connection is deleted (death_by_timeout).
3134 + */
3135  void
3136  ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
3137                         void *data)
3138 @@ -1263,7 +1371,7 @@
3139         while ((h = get_next_corpse(kill, data)) != NULL) {
3140                 /* Time to push up daises... */
3141                 if (del_timer(&h->ctrack->timeout))
3142 -                       death_by_timeout((unsigned long)h->ctrack);
3143 +                       ip_ct_death_by_timeout((unsigned long)h->ctrack);
3144                 /* ... else the timer will get him soon. */
3145  
3146                 ip_conntrack_put(h->ctrack);
3147 @@ -1419,6 +1527,15 @@
3148  
3149         /* For use by ipt_REJECT */
3150         ip_ct_attach = ip_conntrack_attach;
3151 +
3152 +       /* Set up fake conntrack:
3153 +           - to never be deleted, not in any hashes */
3154 +       atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
3155 +       /*  - and look it like as a confirmed connection */
3156 +       set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
3157 +       /*  - and prepare the ctinfo field for NAT. */
3158 +       ip_conntrack_untracked.infos[IP_CT_NEW].master = &ip_conntrack_untracked.ct_general;
3159 +
3160         return ret;
3161  
3162  err_free_hash:
3163 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
3164 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_egg.c        1970-01-01 01:00:00.000000000 +0100
3165 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_egg.c    2003-12-11 10:23:50.104320960 +0100
3166 @@ -0,0 +1,237 @@
3167 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3168 + * based on ip_conntrack_irc.c 
3169 + *
3170 + *      This module only supports the share userfile-send command,
3171 + *      used by eggdrops to share it's userfile.
3172 + *
3173 + *      There are no support for NAT at the moment.
3174 + *
3175 + *      This program is free software; you can redistribute it and/or
3176 + *      modify it under the terms of the GNU General Public License
3177 + *      as published by the Free Software Foundation; either version
3178 + *      2 of the License, or (at your option) any later version.
3179 + *
3180 + *     Module load syntax:
3181 + *     
3182 + *     please give the ports of all Eggdrops You have running
3183 + *      on your system, the default port is 3333.
3184 + *
3185 + *      2001-04-19: Security update. IP addresses are now compared
3186 + *                  to prevent unauthorized "related" access.
3187 + *
3188 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
3189 + *                 Port to netfilter 'newnat' API.
3190 + */
3191 +
3192 +#include <linux/module.h>
3193 +#include <linux/netfilter.h>
3194 +#include <linux/ip.h>
3195 +#include <net/checksum.h>
3196 +#include <net/tcp.h>
3197 +
3198 +#include <linux/netfilter_ipv4/lockhelp.h>
3199 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3200 +
3201 +#define MAX_PORTS 8
3202 +static int ports[MAX_PORTS];
3203 +static int ports_c = 0;
3204 +static unsigned int egg_timeout = 300;
3205 +
3206 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3207 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3208 +MODULE_LICENSE("GPL");
3209 +#ifdef MODULE_PARM
3210 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3211 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3212 +#endif
3213 +
3214 +DECLARE_LOCK(ip_egg_lock);
3215 +struct module *ip_conntrack_egg = THIS_MODULE;
3216 +
3217 +#if 0
3218 +#define DEBUGP printk
3219 +#else
3220 +#define DEBUGP(format, args...)
3221 +#endif
3222 +
3223 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3224 +/* tries to get the ip_addr and port out of a eggdrop command
3225 +   return value: -1 on failure, 0 on success 
3226 +   data                pointer to first byte of DCC command data
3227 +   data_end    pointer to last byte of dcc command data
3228 +   ip          returns parsed ip of dcc command
3229 +   port                returns parsed port of dcc command */
3230 +{
3231 +       if (data > data_end)
3232 +               return -1;
3233 +       
3234 +       *ip = simple_strtoul(data, &data, 10);
3235 +
3236 +       /* skip blanks between ip and port */
3237 +       while (*data == ' ' && data < data_end)
3238 +               data++;
3239 +
3240 +       *port = simple_strtoul(data, &data, 10);
3241 +       return 0;
3242 +}
3243 +
3244 +
3245 +static int help(const struct iphdr *iph, size_t len,
3246 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3247 +{
3248 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3249 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3250 +       char *data = (char *) tcph + tcph->doff * 4;
3251 +       char *data_limit;
3252 +       u_int32_t tcplen = len - iph->ihl * 4;
3253 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3254 +       int dir = CTINFO2DIR(ctinfo);
3255 +       int bytes_scanned = 0;
3256 +       struct ip_conntrack_expect exp;
3257 +
3258 +       u_int32_t egg_ip;
3259 +       u_int16_t egg_port;
3260 +
3261 +       DEBUGP("entered\n");
3262 +
3263 +       /* If packet is coming from IRC server */
3264 +       if (dir != IP_CT_DIR_REPLY)
3265 +               return NF_ACCEPT;
3266 +
3267 +       /* Until there's been traffic both ways, don't look in packets. */
3268 +       if (ctinfo != IP_CT_ESTABLISHED
3269 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3270 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
3271 +               return NF_ACCEPT;
3272 +       }
3273 +
3274 +       /* Not whole TCP header? */
3275 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3276 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3277 +               return NF_ACCEPT;
3278 +       }
3279 +
3280 +       /* Checksum invalid?  Ignore. */
3281 +       /* FIXME: Source route IP option packets --RR */
3282 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3283 +                        csum_partial((char *) tcph, tcplen, 0))) {
3284 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3285 +                       tcph, tcplen, NIPQUAD(iph->saddr),
3286 +                       NIPQUAD(iph->daddr));
3287 +               return NF_ACCEPT;
3288 +       }
3289 +
3290 +       data_limit = (char *) data + datalen;
3291 +       while (datalen > 5 && bytes_scanned < 128) {
3292 +               if (memcmp(data, "s us ", 5)) {
3293 +                       data++;
3294 +                       datalen--;
3295 +                       bytes_scanned++;
3296 +                       continue;
3297 +               }
3298 +
3299 +               data += 5;
3300 +
3301 +               DEBUGP("Userfile-share found in connection "
3302 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3303 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3304 +
3305 +               if (parse_command((char *) data, data_limit, &egg_ip,
3306 +                                 &egg_port)) {
3307 +                       DEBUGP("no data in userfile-share pkt\n");
3308 +                       return NF_ACCEPT;
3309 +               }
3310 +
3311 +               memset(&exp, 0, sizeof(exp));
3312 +
3313 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3314 +                       if (net_ratelimit())
3315 +                               printk("Forged Eggdrop command from "
3316 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3317 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3318 +                                      HIPQUAD(egg_ip), egg_port);
3319 +                       return NF_ACCEPT;
3320 +               }
3321 +
3322 +               exp.tuple.src.ip = iph->daddr;
3323 +               exp.tuple.src.u.tcp.port = 0;
3324 +               exp.tuple.dst.ip = htonl(egg_ip);
3325 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
3326 +               exp.tuple.dst.protonum = IPPROTO_TCP;
3327 +
3328 +               exp.mask.dst.u.tcp.port = 0xffff;
3329 +               exp.mask.dst.protonum = 0xffff;
3330 +
3331 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3332 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3333 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3334 +
3335 +               ip_conntrack_expect_related(ct, &exp);
3336 +               break;
3337 +       }
3338 +       return NF_ACCEPT;
3339 +}
3340 +
3341 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3342 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3343 +
3344 +static void deregister_helpers(void) {
3345 +       int i;
3346 +       
3347 +       for (i = 0; i < ports_c; i++) {
3348 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
3349 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
3350 +       }
3351 +}
3352 +
3353 +static int __init init(void)
3354 +{
3355 +       int i, ret;
3356 +       char *tmpname;
3357 +
3358 +       /* If no port given, default to standard eggdrop port */
3359 +       if (ports[0] == 0)
3360 +               ports[0] = 3333;
3361 +
3362 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3363 +               memset(&egg_helpers[i], 0,
3364 +                      sizeof(struct ip_conntrack_helper));
3365 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3366 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3367 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3368 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
3369 +               egg_helpers[i].max_expected = 1;
3370 +               egg_helpers[i].timeout = egg_timeout;
3371 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3372 +               egg_helpers[i].me = THIS_MODULE;
3373 +               egg_helpers[i].help = help;
3374 +
3375 +               tmpname = &egg_names[i][0];
3376 +               if (ports[i] == 3333)
3377 +                       sprintf(tmpname, "eggdrop");
3378 +               else
3379 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
3380 +               egg_helpers[i].name = tmpname;
3381 +
3382 +               DEBUGP("port #%d: %d\n", i, ports[i]);
3383 +
3384 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
3385 +
3386 +               if (ret) {
3387 +                       printk("ip_conntrack_egg: ERROR registering helper "
3388 +                               "for port %d\n", ports[i]);
3389 +                       deregister_helpers();
3390 +                       return 1;
3391 +               }
3392 +               ports_c++;
3393 +       }
3394 +       return 0;
3395 +}
3396 +
3397 +static void __exit fini(void)
3398 +{
3399 +       deregister_helpers();
3400 +}
3401 +
3402 +module_init(init);
3403 +module_exit(fini);
3404 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
3405 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_h323.c       1970-01-01 01:00:00.000000000 +0100
3406 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_h323.c   2003-12-11 10:23:51.335133848 +0100
3407 @@ -0,0 +1,308 @@
3408 +/* 
3409 + * H.323 'brute force' extension for H.323 connection tracking. 
3410 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3411 + *
3412 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3413 + * (http://www.coritel.it/projects/sofia/nat/)
3414 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3415 + * the unregistered helpers to the conntrack entries.
3416 + */
3417 +
3418 +
3419 +#include <linux/module.h>
3420 +#include <linux/netfilter.h>
3421 +#include <linux/ip.h>
3422 +#include <net/checksum.h>
3423 +#include <net/tcp.h>
3424 +
3425 +#include <linux/netfilter_ipv4/lockhelp.h>
3426 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3427 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3428 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3429 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3430 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3431 +
3432 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3433 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3434 +MODULE_LICENSE("GPL");
3435 +
3436 +DECLARE_LOCK(ip_h323_lock);
3437 +struct module *ip_conntrack_h323 = THIS_MODULE;
3438 +
3439 +#if 0
3440 +#define DEBUGP printk
3441 +#else
3442 +#define DEBUGP(format, args...)
3443 +#endif
3444 +
3445 +/* FIXME: This should be in userspace.  Later. */
3446 +static int h245_help(const struct iphdr *iph, size_t len,
3447 +                    struct ip_conntrack *ct,
3448 +                    enum ip_conntrack_info ctinfo)
3449 +{
3450 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3451 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3452 +       unsigned char *data_limit;
3453 +       u_int32_t tcplen = len - iph->ihl * 4;
3454 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3455 +       int dir = CTINFO2DIR(ctinfo);
3456 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3457 +       struct ip_conntrack_expect expect, *exp = &expect;
3458 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3459 +       u_int16_t data_port;
3460 +       u_int32_t data_ip;
3461 +       unsigned int i;
3462 +
3463 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3464 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3465 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3466 +
3467 +       /* Can't track connections formed before we registered */
3468 +       if (!info)
3469 +               return NF_ACCEPT;
3470 +               
3471 +       /* Until there's been traffic both ways, don't look in packets. */
3472 +       if (ctinfo != IP_CT_ESTABLISHED
3473 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3474 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3475 +               return NF_ACCEPT;
3476 +       }
3477 +
3478 +       /* Not whole TCP header or too short packet? */
3479 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3480 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3481 +               return NF_ACCEPT;
3482 +       }
3483 +
3484 +       /* Checksum invalid?  Ignore. */
3485 +       /* FIXME: Source route IP option packets --RR */
3486 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3487 +                             csum_partial((char *)tcph, tcplen, 0))) {
3488 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3489 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3490 +                      NIPQUAD(iph->daddr));
3491 +               return NF_ACCEPT;
3492 +       }
3493 +
3494 +       data_limit = (unsigned char *) data + datalen;
3495 +       /* bytes: 0123   45
3496 +                 ipadrr port */
3497 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3498 +               data_ip = *((u_int32_t *)data);
3499 +               if (data_ip == iph->saddr) {
3500 +                       data_port = *((u_int16_t *)(data + 4));
3501 +                       memset(&expect, 0, sizeof(expect));
3502 +                       /* update the H.225 info */
3503 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3504 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3505 +                               NIPQUAD(iph->saddr), ntohs(data_port));
3506 +                       LOCK_BH(&ip_h323_lock);
3507 +                       info->is_h225 = H225_PORT + 1;
3508 +                       exp_info->port = data_port;
3509 +                       exp_info->dir = dir;
3510 +                       exp_info->offset = i;
3511 +
3512 +                       exp->seq = ntohl(tcph->seq) + i;
3513 +                   
3514 +                       exp->tuple = ((struct ip_conntrack_tuple)
3515 +                               { { ct->tuplehash[!dir].tuple.src.ip,
3516 +                                   { 0 } },
3517 +                                 { data_ip,
3518 +                                   { .tcp = { data_port } },
3519 +                                   IPPROTO_UDP }});
3520 +                       exp->mask = ((struct ip_conntrack_tuple)
3521 +                               { { 0xFFFFFFFF, { 0 } },
3522 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3523 +       
3524 +                       exp->expectfn = NULL;
3525 +                       
3526 +                       /* Ignore failure; should only happen with NAT */
3527 +                       ip_conntrack_expect_related(ct, exp);
3528 +
3529 +                       UNLOCK_BH(&ip_h323_lock);
3530 +               }
3531 +       }
3532 +
3533 +       return NF_ACCEPT;
3534 +
3535 +}
3536 +
3537 +/* H.245 helper is not registered! */
3538 +static struct ip_conntrack_helper h245 = 
3539 +       { { NULL, NULL },
3540 +          "H.245",                             /* name */
3541 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
3542 +          NULL,                                        /* module */
3543 +          8,                                   /* max_ expected */
3544 +          240,                                 /* timeout */
3545 +          { { 0, { 0 } },                      /* tuple */
3546 +            { 0, { 0 }, IPPROTO_TCP } },
3547 +          { { 0, { 0xFFFF } },                 /* mask */
3548 +            { 0, { 0 }, 0xFFFF } },
3549 +          h245_help                            /* helper */
3550 +       };
3551 +
3552 +static int h225_expect(struct ip_conntrack *ct)
3553 +{
3554 +       WRITE_LOCK(&ip_conntrack_lock);
3555 +       ct->helper = &h245;
3556 +       DEBUGP("h225_expect: helper for %p added\n", ct);
3557 +       WRITE_UNLOCK(&ip_conntrack_lock);
3558 +       
3559 +       return NF_ACCEPT;       /* unused */
3560 +}
3561 +
3562 +/* FIXME: This should be in userspace.  Later. */
3563 +static int h225_help(const struct iphdr *iph, size_t len,
3564 +                    struct ip_conntrack *ct,
3565 +                    enum ip_conntrack_info ctinfo)
3566 +{
3567 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3568 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3569 +       unsigned char *data_limit;
3570 +       u_int32_t tcplen = len - iph->ihl * 4;
3571 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3572 +       int dir = CTINFO2DIR(ctinfo);
3573 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3574 +       struct ip_conntrack_expect expect, *exp = &expect;
3575 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3576 +       u_int16_t data_port;
3577 +       u_int32_t data_ip;
3578 +       unsigned int i;
3579 +       
3580 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3581 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3582 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3583 +
3584 +       /* Can't track connections formed before we registered */
3585 +       if (!info)
3586 +               return NF_ACCEPT;
3587 +
3588 +       /* Until there's been traffic both ways, don't look in packets. */
3589 +       if (ctinfo != IP_CT_ESTABLISHED
3590 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3591 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3592 +               return NF_ACCEPT;
3593 +       }
3594 +
3595 +       /* Not whole TCP header or too short packet? */
3596 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3597 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3598 +               return NF_ACCEPT;
3599 +       }
3600 +
3601 +       /* Checksum invalid?  Ignore. */
3602 +       /* FIXME: Source route IP option packets --RR */
3603 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3604 +                             csum_partial((char *)tcph, tcplen, 0))) {
3605 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3606 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3607 +                      NIPQUAD(iph->daddr));
3608 +               return NF_ACCEPT;
3609 +       }
3610 +       
3611 +       data_limit = (unsigned char *) data + datalen;
3612 +       /* bytes: 0123   45
3613 +                 ipadrr port */
3614 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3615 +               data_ip = *((u_int32_t *)data);
3616 +               if (data_ip == iph->saddr) {
3617 +                       data_port = *((u_int16_t *)(data + 4));
3618 +                       if (data_port == tcph->source) {
3619 +                               /* Signal address */
3620 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3621 +                                       NIPQUAD(iph->saddr));
3622 +                               /* Update the H.225 info so that NAT can mangle the address/port
3623 +                                  even when we have no expected connection! */
3624 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3625 +                               LOCK_BH(&ip_h323_lock);
3626 +                               info->dir = dir;
3627 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3628 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
3629 +                               UNLOCK_BH(&ip_h323_lock);
3630 +#endif
3631 +                       } else {
3632 +                               memset(&expect, 0, sizeof(expect));
3633 +
3634 +                               /* update the H.225 info */
3635 +                               LOCK_BH(&ip_h323_lock);
3636 +                               info->is_h225 = H225_PORT;
3637 +                               exp_info->port = data_port;
3638 +                               exp_info->dir = dir;
3639 +                               exp_info->offset = i;
3640 +
3641 +                               exp->seq = ntohl(tcph->seq) + i;
3642 +
3643 +                               exp->tuple = ((struct ip_conntrack_tuple)
3644 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
3645 +                                           { 0 } },
3646 +                                         { data_ip,
3647 +                                           { .tcp = { data_port } },
3648 +                                           IPPROTO_TCP }});
3649 +                               exp->mask = ((struct ip_conntrack_tuple)
3650 +                                       { { 0xFFFFFFFF, { 0 } },
3651 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3652 +       
3653 +                               exp->expectfn = h225_expect;
3654 +                               
3655 +                               /* Ignore failure */
3656 +                               ip_conntrack_expect_related(ct, exp);
3657 +
3658 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3659 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3660 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
3661 +
3662 +                               UNLOCK_BH(&ip_h323_lock);
3663 +                       }  
3664 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3665 +               } else if (data_ip == iph->daddr) {
3666 +                       data_port = *((u_int16_t *)(data + 4));
3667 +                       if (data_port == tcph->dest) {
3668 +                               /* Signal address */
3669 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3670 +                                       NIPQUAD(iph->daddr));
3671 +                               /* Update the H.225 info so that NAT can mangle the address/port
3672 +                                  even when we have no expected connection! */
3673 +                               LOCK_BH(&ip_h323_lock);
3674 +                               info->dir = dir;
3675 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3676 +                               info->offset[IP_CT_DIR_REPLY] = i;
3677 +                               UNLOCK_BH(&ip_h323_lock);
3678 +                       }
3679 +#endif
3680 +               }
3681 +       }
3682 +
3683 +       return NF_ACCEPT;
3684 +
3685 +}
3686 +
3687 +static struct ip_conntrack_helper h225 = 
3688 +       { { NULL, NULL },
3689 +         "H.225",                                      /* name */
3690 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
3691 +         THIS_MODULE,                                  /* module */
3692 +         2,                                            /* max_expected */
3693 +         240,                                          /* timeout */
3694 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
3695 +           { 0, { 0 }, IPPROTO_TCP } },
3696 +         { { 0, { 0xFFFF } },                          /* mask */
3697 +           { 0, { 0 }, 0xFFFF } },
3698 +         h225_help                                     /* helper */
3699 +       };
3700 +
3701 +static int __init init(void)
3702 +{
3703 +       return ip_conntrack_helper_register(&h225);
3704 +}
3705 +
3706 +static void __exit fini(void)
3707 +{
3708 +       /* Unregister H.225 helper */   
3709 +       ip_conntrack_helper_unregister(&h225);
3710 +}
3711 +
3712 +EXPORT_SYMBOL(ip_h323_lock);
3713 +
3714 +module_init(init);
3715 +module_exit(fini);
3716 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
3717 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_mms.c        1970-01-01 01:00:00.000000000 +0100
3718 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_mms.c    2003-12-11 10:23:55.933434800 +0100
3719 @@ -0,0 +1,308 @@
3720 +/* MMS extension for IP connection tracking
3721 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3722 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
3723 + *
3724 + * ip_conntrack_mms.c v0.3 2002-09-22
3725 + *
3726 + *      This program is free software; you can redistribute it and/or
3727 + *      modify it under the terms of the GNU General Public License
3728 + *      as published by the Free Software Foundation; either version
3729 + *      2 of the License, or (at your option) any later version.
3730 + *
3731 + *      Module load syntax:
3732 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
3733 + *
3734 + *      Please give the ports of all MMS servers You wish to connect to.
3735 + *      If you don't specify ports, the default will be TCP port 1755.
3736 + *
3737 + *      More info on MMS protocol, firewalls and NAT:
3738 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
3739 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
3740 + *
3741 + *      The SDP project people are reverse-engineering MMS:
3742 + *      http://get.to/sdp
3743 + */
3744 +
3745 +#include <linux/config.h>
3746 +#include <linux/module.h>
3747 +#include <linux/netfilter.h>
3748 +#include <linux/ip.h>
3749 +#include <linux/ctype.h>
3750 +#include <net/checksum.h>
3751 +#include <net/tcp.h>
3752 +
3753 +#include <linux/netfilter_ipv4/lockhelp.h>
3754 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3755 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
3756 +
3757 +DECLARE_LOCK(ip_mms_lock);
3758 +struct module *ip_conntrack_mms = THIS_MODULE;
3759 +
3760 +#define MAX_PORTS 8
3761 +static int ports[MAX_PORTS];
3762 +static int ports_c;
3763 +#ifdef MODULE_PARM
3764 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3765 +#endif
3766 +
3767 +#if 0 
3768 +#define DEBUGP printk
3769 +#else
3770 +#define DEBUGP(format, args...)
3771 +#endif
3772 +
3773 +EXPORT_SYMBOL(ip_mms_lock);
3774 +
3775 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3776 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
3777 +MODULE_LICENSE("GPL");
3778 +
3779 +/* #define isdigit(c) (c >= '0' && c <= '9') */
3780 +
3781 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
3782 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
3783 +{
3784 +       int i;
3785 +       for (i = 0; i < unicode_size; ++i) {
3786 +               string[i] = (char)(unicode[i]);
3787 +       }
3788 +       string[unicode_size] = 0x00;
3789 +}
3790 +
3791 +__inline static int atoi(char *s) 
3792 +{
3793 +       int i=0;
3794 +       while (isdigit(*s)) {
3795 +               i = i*10 + *(s++) - '0';
3796 +       }
3797 +       return i;
3798 +}
3799 +
3800 +/* convert ip address string like "192.168.0.10" to unsigned int */
3801 +__inline static u_int32_t asciiiptoi(char *s)
3802 +{
3803 +       unsigned int i, j, k;
3804 +
3805 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
3806 +               i+=atoi(s);
3807 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
3808 +                       ;
3809 +       }
3810 +       i+=atoi(s);
3811 +       return ntohl(i);
3812 +}
3813 +
3814 +int parse_mms(const char *data, 
3815 +             const unsigned int datalen,
3816 +             u_int32_t *mms_ip,
3817 +             u_int16_t *mms_proto,
3818 +             u_int16_t *mms_port,
3819 +             char **mms_string_b,
3820 +             char **mms_string_e,
3821 +             char **mms_padding_e)
3822 +{
3823 +       int unicode_size, i;
3824 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
3825 +       char getlengthstring[28];
3826 +       
3827 +       for(unicode_size=0; 
3828 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
3829 +           unicode_size++)
3830 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
3831 +                       return -1; /* out of bounds - incomplete packet */
3832 +       
3833 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
3834 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
3835 +       
3836 +       /* IP address ? */
3837 +       *mms_ip = asciiiptoi(tempstring+2);
3838 +       
3839 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
3840 +               
3841 +       /* protocol ? */
3842 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
3843 +               *mms_proto = IPPROTO_TCP;
3844 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
3845 +               *mms_proto = IPPROTO_UDP;
3846 +
3847 +       /* port ? */
3848 +       *mms_port = atoi(tempstring+7+i);
3849 +
3850 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
3851 +          unicode string, one to the end of the string, and one to the end 
3852 +          of the packet, since we must keep track of the number of bytes 
3853 +          between end of the unicode string and the end of packet (padding) */
3854 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
3855 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
3856 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
3857 +       return 0;
3858 +}
3859 +
3860 +
3861 +/* FIXME: This should be in userspace.  Later. */
3862 +static int help(const struct iphdr *iph, size_t len,
3863 +               struct ip_conntrack *ct,
3864 +               enum ip_conntrack_info ctinfo)
3865 +{
3866 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
3867 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3868 +       const char *data = (const char *)tcph + tcph->doff * 4;
3869 +       unsigned int tcplen = len - iph->ihl * 4;
3870 +       unsigned int datalen = tcplen - tcph->doff * 4;
3871 +       int dir = CTINFO2DIR(ctinfo);
3872 +       struct ip_conntrack_expect expect, *exp = &expect; 
3873 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
3874 +       
3875 +       u_int32_t mms_ip;
3876 +       u_int16_t mms_proto;
3877 +       char mms_proto_string[8];
3878 +       u_int16_t mms_port;
3879 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
3880 +            
3881 +       /* Until there's been traffic both ways, don't look in packets. */
3882 +       if (ctinfo != IP_CT_ESTABLISHED
3883 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
3884 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
3885 +               return NF_ACCEPT;
3886 +       }
3887 +
3888 +       /* Not whole TCP header? */
3889 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
3890 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
3891 +               return NF_ACCEPT;
3892 +       }
3893 +
3894 +       /* Checksum invalid?  Ignore. */
3895 +       /* FIXME: Source route IP option packets --RR */
3896 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3897 +           csum_partial((char *)tcph, tcplen, 0))) {
3898 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3899 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3900 +                      NIPQUAD(iph->daddr));
3901 +               return NF_ACCEPT;
3902 +       }
3903 +       
3904 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
3905 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
3906 +          the client has already sent a packet to the server with the server's hostname 
3907 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
3908 +          server will break the connection if this doesn't correspond to its own host 
3909 +          header. The client can also connect to an IP address; if it's the server's IP
3910 +          address, it will not break the connection. When doing DNAT on a connection 
3911 +          where the client uses a server's IP address, the nat module should detect
3912 +          this and change this string accordingly to the DNATed address. This should
3913 +          probably be done by checking for an IP address, then storing it as a member
3914 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
3915 +          */
3916 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
3917 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
3918 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
3919 +                      (u8)*(data+36), (u8)*(data+37), 
3920 +                      (u8)*(data+38), (u8)*(data+39),
3921 +                      datalen);
3922 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
3923 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
3924 +                       if(net_ratelimit())
3925 +                               /* FIXME: more verbose debugging ? */
3926 +                               printk(KERN_WARNING
3927 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
3928 +
3929 +               memset(&expect, 0, sizeof(expect));
3930 +
3931 +               sprintf(mms_proto_string, "(%u)", mms_proto);
3932 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
3933 +                      mms_proto == IPPROTO_TCP ? "TCP"
3934 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
3935 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3936 +                      NIPQUAD(mms_ip),
3937 +                      mms_port);
3938 +               
3939 +               /* it's possible that the client will just ask the server to tunnel
3940 +                  the stream over the same TCP session (from port 1755): there's 
3941 +                  shouldn't be a need to add an expectation in that case, but it
3942 +                  makes NAT packet mangling so much easier */
3943 +               LOCK_BH(&ip_mms_lock);
3944 +
3945 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
3946 +               
3947 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
3948 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
3949 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
3950 +               exp_mms_info->port    = mms_port;
3951 +               
3952 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
3953 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
3954 +               
3955 +               exp->tuple = ((struct ip_conntrack_tuple)
3956 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3957 +                             { mms_ip,
3958 +                               { .tcp = { (__u16) ntohs(mms_port) } },
3959 +                               mms_proto } }
3960 +                            );
3961 +               exp->mask  = ((struct ip_conntrack_tuple)
3962 +                            { { 0xFFFFFFFF, { 0 } },
3963 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3964 +               exp->expectfn = NULL;
3965 +               ip_conntrack_expect_related(ct, &expect);
3966 +               UNLOCK_BH(&ip_mms_lock);
3967 +       }
3968 +
3969 +       return NF_ACCEPT;
3970 +}
3971 +
3972 +static struct ip_conntrack_helper mms[MAX_PORTS];
3973 +static char mms_names[MAX_PORTS][10];
3974 +
3975 +/* Not __exit: called from init() */
3976 +static void fini(void)
3977 +{
3978 +       int i;
3979 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3980 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
3981 +                               ports[i]);
3982 +               ip_conntrack_helper_unregister(&mms[i]);
3983 +       }
3984 +}
3985 +
3986 +static int __init init(void)
3987 +{
3988 +       int i, ret;
3989 +       char *tmpname;
3990 +
3991 +       if (ports[0] == 0)
3992 +               ports[0] = MMS_PORT;
3993 +
3994 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3995 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
3996 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
3997 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
3998 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
3999 +               mms[i].mask.dst.protonum = 0xFFFF;
4000 +               mms[i].max_expected = 1;
4001 +               mms[i].timeout = 0;
4002 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4003 +               mms[i].me = THIS_MODULE;
4004 +               mms[i].help = help;
4005 +
4006 +               tmpname = &mms_names[i][0];
4007 +               if (ports[i] == MMS_PORT)
4008 +                       sprintf(tmpname, "mms");
4009 +               else
4010 +                       sprintf(tmpname, "mms-%d", ports[i]);
4011 +               mms[i].name = tmpname;
4012 +
4013 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
4014 +                               ports[i]);
4015 +               ret = ip_conntrack_helper_register(&mms[i]);
4016 +
4017 +               if (ret) {
4018 +                       fini();
4019 +                       return ret;
4020 +               }
4021 +               ports_c++;
4022 +       }
4023 +       return 0;
4024 +}
4025 +
4026 +module_init(init);
4027 +module_exit(fini);
4028 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
4029 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp.c       1970-01-01 01:00:00.000000000 +0100
4030 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp.c   2003-12-11 10:25:04.543004560 +0100
4031 @@ -0,0 +1,639 @@
4032 +/*
4033 + * ip_conntrack_pptp.c - Version 1.9
4034 + *
4035 + * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
4036 + * PPTP is a a protocol for creating virtual private networks.
4037 + * It is a specification defined by Microsoft and some vendors
4038 + * working with Microsoft.  PPTP is built on top of a modified
4039 + * version of the Internet Generic Routing Encapsulation Protocol.
4040 + * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
4041 + * PPTP can be found in RFC 2637
4042 + *
4043 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4044 + *
4045 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4046 + *
4047 + * Limitations:
4048 + *      - We blindly assume that control connections are always
4049 + *        established in PNS->PAC direction.  This is a violation
4050 + *        of RFFC2673
4051 + *
4052 + * TODO: - finish support for multiple calls within one session
4053 + *        (needs expect reservations in newnat)
4054 + *      - testing of incoming PPTP calls 
4055 + *
4056 + * Changes: 
4057 + *     2002-02-05 - Version 1.3
4058 + *       - Call ip_conntrack_unexpect_related() from 
4059 + *         pptp_timeout_related() to destroy expectations in case
4060 + *         CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
4061 + *         (Philip Craig <philipc@snapgear.com>)
4062 + *       - Add Version information at module loadtime
4063 + *     2002-02-10 - Version 1.6
4064 + *       - move to C99 style initializers
4065 + *       - remove second expectation if first arrives
4066 + *
4067 + */
4068 +
4069 +#include <linux/config.h>
4070 +#include <linux/module.h>
4071 +#include <linux/netfilter.h>
4072 +#include <linux/ip.h>
4073 +#include <net/checksum.h>
4074 +#include <net/tcp.h>
4075 +
4076 +#include <linux/netfilter_ipv4/lockhelp.h>
4077 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4078 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4079 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4080 +
4081 +#define IP_CT_PPTP_VERSION "1.9"
4082 +
4083 +MODULE_LICENSE("GPL");
4084 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4085 +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
4086 +
4087 +DECLARE_LOCK(ip_pptp_lock);
4088 +
4089 +#if 0
4090 +#include "ip_conntrack_pptp_priv.h"
4091 +#define DEBUGP(format, args...)        printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4092 +                                       ": " format, ## args)
4093 +#else
4094 +#define DEBUGP(format, args...)
4095 +#endif
4096 +
4097 +#define SECS *HZ
4098 +#define MINS * 60 SECS
4099 +#define HOURS * 60 MINS
4100 +#define DAYS * 24 HOURS
4101 +
4102 +#define PPTP_GRE_TIMEOUT               (10 MINS)
4103 +#define PPTP_GRE_STREAM_TIMEOUT        (5 DAYS)
4104 +
4105 +static int pptp_expectfn(struct ip_conntrack *ct)
4106 +{
4107 +       struct ip_conntrack *master;
4108 +       struct ip_conntrack_expect *exp;
4109 +
4110 +       DEBUGP("increasing timeouts\n");
4111 +       /* increase timeout of GRE data channel conntrack entry */
4112 +       ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
4113 +       ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
4114 +
4115 +       master = master_ct(ct);
4116 +       if (!master) {
4117 +               DEBUGP(" no master!!!\n");
4118 +               return 0;
4119 +       }
4120 +
4121 +       exp = ct->master;
4122 +       if (!exp) {
4123 +               DEBUGP("no expectation!!\n");
4124 +               return 0;
4125 +       }
4126 +
4127 +       DEBUGP("completing tuples with ct info\n");
4128 +       /* we can do this, since we're unconfirmed */
4129 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == 
4130 +               htonl(master->help.ct_pptp_info.pac_call_id)) { 
4131 +               /* assume PNS->PAC */
4132 +               ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = 
4133 +                       htonl(master->help.ct_pptp_info.pns_call_id);
4134 +               ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4135 +                       htonl(master->help.ct_pptp_info.pns_call_id);
4136 +       } else {
4137 +               /* assume PAC->PNS */
4138 +               ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
4139 +                       htonl(master->help.ct_pptp_info.pac_call_id);
4140 +               ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
4141 +                       htonl(master->help.ct_pptp_info.pac_call_id);
4142 +       }
4143 +       
4144 +       /* delete other expectation */
4145 +       if (exp->expected_list.next != &exp->expected_list) {
4146 +               struct ip_conntrack_expect *other_exp;
4147 +               struct list_head *cur_item, *next;
4148 +
4149 +               for (cur_item = master->sibling_list.next;
4150 +                    cur_item != &master->sibling_list; cur_item = next) {
4151 +                       next = cur_item->next;
4152 +                       other_exp = list_entry(cur_item,
4153 +                                              struct ip_conntrack_expect,
4154 +                                              expected_list);
4155 +                       /* remove only if occurred at same sequence number */
4156 +                       if (other_exp != exp && other_exp->seq == exp->seq) {
4157 +                               DEBUGP("unexpecting other direction\n");
4158 +                               ip_ct_gre_keymap_destroy(other_exp);
4159 +                               ip_conntrack_unexpect_related(other_exp);
4160 +                       }
4161 +               }
4162 +       }
4163 +
4164 +       return 0;
4165 +}
4166 +
4167 +/* timeout GRE data connections */
4168 +static int pptp_timeout_related(struct ip_conntrack *ct)
4169 +{
4170 +       struct list_head *cur_item, *next;
4171 +       struct ip_conntrack_expect *exp;
4172 +
4173 +       /* FIXME: do we have to lock something ? */
4174 +       for (cur_item = ct->sibling_list.next;
4175 +           cur_item != &ct->sibling_list; cur_item = next) {
4176 +               next = cur_item->next;
4177 +               exp = list_entry(cur_item, struct ip_conntrack_expect,
4178 +                                expected_list);
4179 +
4180 +               ip_ct_gre_keymap_destroy(exp);
4181 +               if (!exp->sibling) {
4182 +                       ip_conntrack_unexpect_related(exp);
4183 +                       continue;
4184 +               }
4185 +
4186 +               DEBUGP("killing conntrack %p\n",
4187 +                       exp->sibling);
4188 +               exp->sibling->proto.gre.timeout = 0;
4189 +               exp->sibling->proto.gre.stream_timeout = 0;
4190 +
4191 +               if (del_timer(&exp->sibling->timeout))
4192 +                       ip_ct_death_by_timeout((unsigned long)exp->sibling);
4193 +       }
4194 +
4195 +       return 0;
4196 +}
4197 +
4198 +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
4199 +static inline int
4200 +exp_gre(struct ip_conntrack *master,
4201 +       u_int32_t seq,
4202 +       u_int16_t callid,
4203 +       u_int16_t peer_callid)
4204 +{
4205 +       struct ip_conntrack_expect exp;
4206 +       struct ip_conntrack_tuple inv_tuple;
4207 +
4208 +       memset(&exp, 0, sizeof(exp));
4209 +       /* tuple in original direction, PNS->PAC */
4210 +       exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
4211 +       exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
4212 +       exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
4213 +       exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
4214 +       exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
4215 +       exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
4216 +       exp.tuple.dst.protonum = IPPROTO_GRE;
4217 +
4218 +       exp.mask.src.ip = 0xffffffff;
4219 +       exp.mask.src.u.all = 0;
4220 +       exp.mask.dst.u.all = 0;
4221 +       exp.mask.dst.u.gre.key = 0xffffffff;
4222 +       exp.mask.dst.u.gre.version = 0xff;
4223 +       exp.mask.dst.u.gre.protocol = 0xffff;
4224 +       exp.mask.dst.ip = 0xffffffff;
4225 +       exp.mask.dst.protonum = 0xffff;
4226 +                       
4227 +       exp.seq = seq;
4228 +       exp.expectfn = pptp_expectfn;
4229 +
4230 +       exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
4231 +       exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
4232 +
4233 +       DEBUGP("calling expect_related ");
4234 +       DUMP_TUPLE_RAW(&exp.tuple);
4235 +       
4236 +       /* Add GRE keymap entries */
4237 +       if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
4238 +               return 1;
4239 +
4240 +       invert_tuplepr(&inv_tuple, &exp.tuple);
4241 +       if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
4242 +               ip_ct_gre_keymap_destroy(&exp);
4243 +               return 1;
4244 +       }
4245 +       
4246 +       if (ip_conntrack_expect_related(master, &exp) != 0) {
4247 +               ip_ct_gre_keymap_destroy(&exp);
4248 +               DEBUGP("cannot expect_related()\n");
4249 +               return 1;
4250 +       }
4251 +
4252 +       /* tuple in reply direction, PAC->PNS */
4253 +       exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
4254 +       exp.tuple.src.u.gre.key = htonl(ntohs(callid));
4255 +       exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
4256 +       exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
4257 +
4258 +       DEBUGP("calling expect_related ");
4259 +       DUMP_TUPLE_RAW(&exp.tuple);
4260 +       
4261 +       /* Add GRE keymap entries */
4262 +       ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
4263 +       invert_tuplepr(&inv_tuple, &exp.tuple);
4264 +       ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
4265 +       /* FIXME: cannot handle error correctly, since we need to free
4266 +        * the above keymap :( */
4267 +       
4268 +       if (ip_conntrack_expect_related(master, &exp) != 0) {
4269 +               /* free the second pair of keypmaps */
4270 +               ip_ct_gre_keymap_destroy(&exp);
4271 +               DEBUGP("cannot expect_related():\n");
4272 +               return 1;
4273 +       }
4274 +
4275 +       return 0;
4276 +}
4277 +
4278 +static inline int 
4279 +pptp_inbound_pkt(struct tcphdr *tcph,
4280 +                struct pptp_pkt_hdr *pptph, 
4281 +                size_t datalen,
4282 +                struct ip_conntrack *ct,
4283 +                enum ip_conntrack_info ctinfo)
4284 +{
4285 +       struct PptpControlHeader *ctlh;
4286 +        union pptp_ctrl_union pptpReq;
4287 +       
4288 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4289 +       u_int16_t msg, *cid, *pcid;
4290 +       u_int32_t seq;  
4291 +
4292 +       ctlh = (struct PptpControlHeader *) 
4293 +               ((char *) pptph + sizeof(struct pptp_pkt_hdr));
4294 +       pptpReq.rawreq = (void *) 
4295 +               ((char *) ctlh + sizeof(struct PptpControlHeader));
4296 +
4297 +       msg = ntohs(ctlh->messageType);
4298 +       DEBUGP("inbound control message %s\n", strMName[msg]);
4299 +
4300 +       switch (msg) {
4301 +       case PPTP_START_SESSION_REPLY:
4302 +               /* server confirms new control session */
4303 +               if (info->sstate < PPTP_SESSION_REQUESTED) {
4304 +                       DEBUGP("%s without START_SESS_REQUEST\n",
4305 +                               strMName[msg]);
4306 +                       break;
4307 +               }
4308 +               if (pptpReq.srep->resultCode == PPTP_START_OK)
4309 +                       info->sstate = PPTP_SESSION_CONFIRMED;
4310 +               else 
4311 +                       info->sstate = PPTP_SESSION_ERROR;
4312 +               break;
4313 +
4314 +       case PPTP_STOP_SESSION_REPLY:
4315 +               /* server confirms end of control session */
4316 +               if (info->sstate > PPTP_SESSION_STOPREQ) {
4317 +                       DEBUGP("%s without STOP_SESS_REQUEST\n",
4318 +                               strMName[msg]);
4319 +                       break;
4320 +               }
4321 +               if (pptpReq.strep->resultCode == PPTP_STOP_OK)
4322 +                       info->sstate = PPTP_SESSION_NONE;
4323 +               else
4324 +                       info->sstate = PPTP_SESSION_ERROR;
4325 +               break;
4326 +
4327 +       case PPTP_OUT_CALL_REPLY:
4328 +               /* server accepted call, we now expect GRE frames */
4329 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4330 +                       DEBUGP("%s but no session\n", strMName[msg]);
4331 +                       break;
4332 +               }
4333 +               if (info->cstate != PPTP_CALL_OUT_REQ &&
4334 +                   info->cstate != PPTP_CALL_OUT_CONF) {
4335 +                       DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
4336 +                       break;
4337 +               }
4338 +               if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
4339 +                       info->cstate = PPTP_CALL_NONE;
4340 +                       break;
4341 +               }
4342 +
4343 +               cid = &pptpReq.ocack->callID;
4344 +               pcid = &pptpReq.ocack->peersCallID;
4345 +
4346 +               info->pac_call_id = ntohs(*cid);
4347 +               
4348 +               if (htons(info->pns_call_id) != *pcid) {
4349 +                       DEBUGP("%s for unknown callid %u\n",
4350 +                               strMName[msg], ntohs(*pcid));
4351 +                       break;
4352 +               }
4353 +
4354 +               DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg], 
4355 +                       ntohs(*cid), ntohs(*pcid));
4356 +               
4357 +               info->cstate = PPTP_CALL_OUT_CONF;
4358 +
4359 +               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4360 +               if (exp_gre(ct, seq, *cid, *pcid) != 0)
4361 +                       printk("ip_conntrack_pptp: error during exp_gre\n");
4362 +               break;
4363 +
4364 +       case PPTP_IN_CALL_REQUEST:
4365 +               /* server tells us about incoming call request */
4366 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4367 +                       DEBUGP("%s but no session\n", strMName[msg]);
4368 +                       break;
4369 +               }
4370 +               pcid = &pptpReq.icack->peersCallID;
4371 +               DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4372 +               info->cstate = PPTP_CALL_IN_REQ;
4373 +               info->pac_call_id= ntohs(*pcid);
4374 +               break;
4375 +
4376 +       case PPTP_IN_CALL_CONNECT:
4377 +               /* server tells us about incoming call established */
4378 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4379 +                       DEBUGP("%s but no session\n", strMName[msg]);
4380 +                       break;
4381 +               }
4382 +               if (info->sstate != PPTP_CALL_IN_REP
4383 +                   && info->sstate != PPTP_CALL_IN_CONF) {
4384 +                       DEBUGP("%s but never sent IN_CALL_REPLY\n",
4385 +                               strMName[msg]);
4386 +                       break;
4387 +               }
4388 +
4389 +               pcid = &pptpReq.iccon->peersCallID;
4390 +               cid = &info->pac_call_id;
4391 +
4392 +               if (info->pns_call_id != ntohs(*pcid)) {
4393 +                       DEBUGP("%s for unknown CallID %u\n", 
4394 +                               strMName[msg], ntohs(*cid));
4395 +                       break;
4396 +               }
4397 +
4398 +               DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
4399 +               info->cstate = PPTP_CALL_IN_CONF;
4400 +
4401 +               /* we expect a GRE connection from PAC to PNS */
4402 +               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
4403 +               if (exp_gre(ct, seq, *cid, *pcid) != 0)
4404 +                       printk("ip_conntrack_pptp: error during exp_gre\n");
4405 +
4406 +               break;
4407 +
4408 +       case PPTP_CALL_DISCONNECT_NOTIFY:
4409 +               /* server confirms disconnect */
4410 +               cid = &pptpReq.disc->callID;
4411 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4412 +               info->cstate = PPTP_CALL_NONE;
4413 +
4414 +               /* untrack this call id, unexpect GRE packets */
4415 +               pptp_timeout_related(ct);
4416 +               break;
4417 +
4418 +       case PPTP_WAN_ERROR_NOTIFY:
4419 +               break;
4420 +
4421 +       case PPTP_ECHO_REQUEST:
4422 +       case PPTP_ECHO_REPLY:
4423 +               /* I don't have to explain these ;) */
4424 +               break;
4425 +       default:
4426 +               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
4427 +                       ? strMName[msg]:strMName[0], msg);
4428 +               break;
4429 +       }
4430 +
4431 +       return NF_ACCEPT;
4432 +
4433 +}
4434 +
4435 +static inline int
4436 +pptp_outbound_pkt(struct tcphdr *tcph,
4437 +                 struct pptp_pkt_hdr *pptph,
4438 +                 size_t datalen,
4439 +                 struct ip_conntrack *ct,
4440 +                 enum ip_conntrack_info ctinfo)
4441 +{
4442 +       struct PptpControlHeader *ctlh;
4443 +        union pptp_ctrl_union pptpReq;
4444 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4445 +       u_int16_t msg, *cid, *pcid;
4446 +
4447 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
4448 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
4449 +
4450 +       msg = ntohs(ctlh->messageType);
4451 +       DEBUGP("outbound control message %s\n", strMName[msg]);
4452 +
4453 +       switch (msg) {
4454 +       case PPTP_START_SESSION_REQUEST:
4455 +               /* client requests for new control session */
4456 +               if (info->sstate != PPTP_SESSION_NONE) {
4457 +                       DEBUGP("%s but we already have one",
4458 +                               strMName[msg]);
4459 +               }
4460 +               info->sstate = PPTP_SESSION_REQUESTED;
4461 +               break;
4462 +       case PPTP_STOP_SESSION_REQUEST:
4463 +               /* client requests end of control session */
4464 +               info->sstate = PPTP_SESSION_STOPREQ;
4465 +               break;
4466 +
4467 +       case PPTP_OUT_CALL_REQUEST:
4468 +               /* client initiating connection to server */
4469 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4470 +                       DEBUGP("%s but no session\n",
4471 +                               strMName[msg]);
4472 +                       break;
4473 +               }
4474 +               info->cstate = PPTP_CALL_OUT_REQ;
4475 +               /* track PNS call id */
4476 +               cid = &pptpReq.ocreq->callID;
4477 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
4478 +               info->pns_call_id = ntohs(*cid);
4479 +               break;
4480 +       case PPTP_IN_CALL_REPLY:
4481 +               /* client answers incoming call */
4482 +               if (info->cstate != PPTP_CALL_IN_REQ
4483 +                   && info->cstate != PPTP_CALL_IN_REP) {
4484 +                       DEBUGP("%s without incall_req\n", 
4485 +                               strMName[msg]);
4486 +                       break;
4487 +               }
4488 +               if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
4489 +                       info->cstate = PPTP_CALL_NONE;
4490 +                       break;
4491 +               }
4492 +               pcid = &pptpReq.icack->peersCallID;
4493 +               if (info->pac_call_id != ntohs(*pcid)) {
4494 +                       DEBUGP("%s for unknown call %u\n", 
4495 +                               strMName[msg], ntohs(*pcid));
4496 +                       break;
4497 +               }
4498 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
4499 +               /* part two of the three-way handshake */
4500 +               info->cstate = PPTP_CALL_IN_REP;
4501 +               info->pns_call_id = ntohs(pptpReq.icack->callID);
4502 +               break;
4503 +
4504 +       case PPTP_CALL_CLEAR_REQUEST:
4505 +               /* client requests hangup of call */
4506 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
4507 +                       DEBUGP("CLEAR_CALL but no session\n");
4508 +                       break;
4509 +               }
4510 +               /* FUTURE: iterate over all calls and check if
4511 +                * call ID is valid.  We don't do this without newnat,
4512 +                * because we only know about last call */
4513 +               info->cstate = PPTP_CALL_CLEAR_REQ;
4514 +               break;
4515 +       case PPTP_SET_LINK_INFO:
4516 +               break;
4517 +       case PPTP_ECHO_REQUEST:
4518 +       case PPTP_ECHO_REPLY:
4519 +               /* I don't have to explain these ;) */
4520 +               break;
4521 +       default:
4522 +               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? 
4523 +                       strMName[msg]:strMName[0], msg);
4524 +               /* unknown: no need to create GRE masq table entry */
4525 +               break;
4526 +       }
4527 +
4528 +       return NF_ACCEPT;
4529 +}
4530 +
4531 +
4532 +/* track caller id inside control connection, call expect_related */
4533 +static int 
4534 +conntrack_pptp_help(const struct iphdr *iph, size_t len,
4535 +                   struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4536 +
4537 +{
4538 +       struct pptp_pkt_hdr *pptph;
4539 +       
4540 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4541 +       u_int32_t tcplen = len - iph->ihl * 4;
4542 +       u_int32_t datalen = tcplen - tcph->doff * 4;
4543 +       void *datalimit;
4544 +       int dir = CTINFO2DIR(ctinfo);
4545 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
4546 +
4547 +       int oldsstate, oldcstate;
4548 +       int ret;
4549 +
4550 +       /* don't do any tracking before tcp handshake complete */
4551 +       if (ctinfo != IP_CT_ESTABLISHED 
4552 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4553 +               DEBUGP("ctinfo = %u, skipping\n", ctinfo);
4554 +               return NF_ACCEPT;
4555 +       }
4556 +       
4557 +       /* not a complete TCP header? */
4558 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4559 +               DEBUGP("tcplen = %u\n", tcplen);
4560 +               return NF_ACCEPT;
4561 +       }
4562 +
4563 +       /* checksum invalid? */
4564 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4565 +                       csum_partial((char *) tcph, tcplen, 0))) {
4566 +               printk(KERN_NOTICE __FILE__ ": bad csum\n");
4567 +               /* W2K PPTP server sends TCP packets with wrong checksum :(( */
4568 +               //return NF_ACCEPT;
4569 +       }
4570 +
4571 +       if (tcph->fin || tcph->rst) {
4572 +               DEBUGP("RST/FIN received, timeouting GRE\n");
4573 +               /* can't do this after real newnat */
4574 +               info->cstate = PPTP_CALL_NONE;
4575 +
4576 +               /* untrack this call id, unexpect GRE packets */
4577 +               pptp_timeout_related(ct);
4578 +       }
4579 +
4580 +
4581 +       pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
4582 +       datalimit = (void *) pptph + datalen;
4583 +
4584 +       /* not a full pptp packet header? */
4585 +       if ((void *) pptph+sizeof(*pptph) >= datalimit) {
4586 +               DEBUGP("no full PPTP header, can't track\n");
4587 +               return NF_ACCEPT;
4588 +       }
4589 +       
4590 +       /* if it's not a control message we can't do anything with it */
4591 +        if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
4592 +           ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
4593 +               DEBUGP("not a control packet\n");
4594 +               return NF_ACCEPT;
4595 +       }
4596 +
4597 +       oldsstate = info->sstate;
4598 +       oldcstate = info->cstate;
4599 +
4600 +       LOCK_BH(&ip_pptp_lock);
4601 +
4602 +       /* FIXME: We just blindly assume that the control connection is always
4603 +        * established from PNS->PAC.  However, RFC makes no guarantee */
4604 +       if (dir == IP_CT_DIR_ORIGINAL)
4605 +               /* client -> server (PNS -> PAC) */
4606 +               ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4607 +       else
4608 +               /* server -> client (PAC -> PNS) */
4609 +               ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
4610 +       DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
4611 +               oldsstate, info->sstate, oldcstate, info->cstate);
4612 +       UNLOCK_BH(&ip_pptp_lock);
4613 +
4614 +       return ret;
4615 +}
4616 +
4617 +/* control protocol helper */
4618 +static struct ip_conntrack_helper pptp = { 
4619 +       .list = { NULL, NULL },
4620 +       .name = "pptp", 
4621 +       .flags = IP_CT_HELPER_F_REUSE_EXPECT,
4622 +       .me = THIS_MODULE,
4623 +       .max_expected = 2,
4624 +       .timeout = 0,
4625 +       .tuple = { .src = { .ip = 0, 
4626 +                           .u = { .tcp = { .port =  
4627 +                                   __constant_htons(PPTP_CONTROL_PORT) } } 
4628 +                         }, 
4629 +                  .dst = { .ip = 0, 
4630 +                           .u = { .all = 0 },
4631 +                           .protonum = IPPROTO_TCP
4632 +                         } 
4633 +                },
4634 +       .mask = { .src = { .ip = 0, 
4635 +                          .u = { .tcp = { .port = 0xffff } } 
4636 +                        }, 
4637 +                 .dst = { .ip = 0, 
4638 +                          .u = { .all = 0 },
4639 +                          .protonum = 0xffff 
4640 +                        } 
4641 +               },
4642 +       .help = conntrack_pptp_help
4643 +};
4644 +
4645 +/* ip_conntrack_pptp initialization */
4646 +static int __init init(void)
4647 +{
4648 +       int retcode;
4649 +
4650 +       DEBUGP(__FILE__ ": registering helper\n");
4651 +       if ((retcode = ip_conntrack_helper_register(&pptp))) {
4652 +                printk(KERN_ERR "Unable to register conntrack application "
4653 +                               "helper for pptp: %d\n", retcode);
4654 +               return -EIO;
4655 +       }
4656 +
4657 +       printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
4658 +       return 0;
4659 +}
4660 +
4661 +static void __exit fini(void)
4662 +{
4663 +       ip_conntrack_helper_unregister(&pptp);
4664 +       printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
4665 +}
4666 +
4667 +module_init(init);
4668 +module_exit(fini);
4669 +
4670 +EXPORT_SYMBOL(ip_pptp_lock);
4671 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
4672 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h  1970-01-01 01:00:00.000000000 +0100
4673 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_pptp_priv.h      2003-11-17 09:09:34.000000000 +0100
4674 @@ -0,0 +1,24 @@
4675 +#ifndef _IP_CT_PPTP_PRIV_H
4676 +#define _IP_CT_PPTP_PRIV_H
4677 +
4678 +/* PptpControlMessageType names */
4679 +static const char *strMName[] = {
4680 +       "UNKNOWN_MESSAGE",
4681 +       "START_SESSION_REQUEST",
4682 +       "START_SESSION_REPLY",
4683 +       "STOP_SESSION_REQUEST",
4684 +       "STOP_SESSION_REPLY",
4685 +       "ECHO_REQUEST",
4686 +       "ECHO_REPLY",
4687 +       "OUT_CALL_REQUEST",
4688 +       "OUT_CALL_REPLY",
4689 +       "IN_CALL_REQUEST",
4690 +       "IN_CALL_REPLY",
4691 +       "IN_CALL_CONNECT",
4692 +       "CALL_CLEAR_REQUEST",
4693 +       "CALL_DISCONNECT_NOTIFY",
4694 +       "WAN_ERROR_NOTIFY",
4695 +       "SET_LINK_INFO"
4696 +};
4697 +
4698 +#endif
4699 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
4700 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c  1970-01-01 01:00:00.000000000 +0100
4701 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_proto_gre.c      2003-11-17 09:09:34.000000000 +0100
4702 @@ -0,0 +1,343 @@
4703 +/*
4704 + * ip_conntrack_proto_gre.c - Version 1.2 
4705 + *
4706 + * Connection tracking protocol helper module for GRE.
4707 + *
4708 + * GRE is a generic encapsulation protocol, which is generally not very
4709 + * suited for NAT, as it has no protocol-specific part as port numbers.
4710 + *
4711 + * It has an optional key field, which may help us distinguishing two 
4712 + * connections between the same two hosts.
4713 + *
4714 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
4715 + *
4716 + * PPTP is built on top of a modified version of GRE, and has a mandatory
4717 + * field called "CallID", which serves us for the same purpose as the key
4718 + * field in plain GRE.
4719 + *
4720 + * Documentation about PPTP can be found in RFC 2637
4721 + *
4722 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
4723 + *
4724 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
4725 + *
4726 + */
4727 +
4728 +#include <linux/config.h>
4729 +#include <linux/module.h>
4730 +#include <linux/types.h>
4731 +#include <linux/timer.h>
4732 +#include <linux/netfilter.h>
4733 +#include <linux/ip.h>
4734 +#include <linux/in.h>
4735 +#include <linux/list.h>
4736 +
4737 +#include <linux/netfilter_ipv4/lockhelp.h>
4738 +
4739 +DECLARE_RWLOCK(ip_ct_gre_lock);
4740 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock)
4741 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock)
4742 +
4743 +#include <linux/netfilter_ipv4/listhelp.h>
4744 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4745 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4746 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4747 +
4748 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
4749 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
4750 +
4751 +MODULE_LICENSE("GPL");
4752 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
4753 +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
4754 +
4755 +/* shamelessly stolen from ip_conntrack_proto_udp.c */
4756 +#define GRE_TIMEOUT            (30*HZ)
4757 +#define GRE_STREAM_TIMEOUT     (180*HZ)
4758 +
4759 +#if 0
4760 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
4761 +                                      ": " format, ## args)
4762 +#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
4763 +                       NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
4764 +                       NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key), \
4765 +                       (x)->dst.u.gre.version, \
4766 +                       ntohs((x)->dst.u.gre.protocol))
4767 +#else
4768 +#define DEBUGP(x, args...)
4769 +#define DUMP_TUPLE_GRE(x)
4770 +#endif
4771 +                               
4772 +/* GRE KEYMAP HANDLING FUNCTIONS */
4773 +static LIST_HEAD(gre_keymap_list);
4774 +
4775 +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
4776 +                               const struct ip_conntrack_tuple *t)
4777 +{
4778 +       return ((km->tuple.src.ip == t->src.ip) &&
4779 +               (km->tuple.dst.ip == t->dst.ip) &&
4780 +               (km->tuple.dst.protonum == t->dst.protonum) &&
4781 +               (km->tuple.dst.u.all == t->dst.u.all));
4782 +}
4783 +
4784 +/* look up the source key for a given tuple */
4785 +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
4786 +{
4787 +       struct ip_ct_gre_keymap *km;
4788 +       u_int32_t key;
4789 +
4790 +       READ_LOCK(&ip_ct_gre_lock);
4791 +       km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
4792 +                       struct ip_ct_gre_keymap *, t);
4793 +       if (!km) {
4794 +               READ_UNLOCK(&ip_ct_gre_lock);
4795 +               return 0;
4796 +       }
4797 +
4798 +       key = km->tuple.src.u.gre.key;
4799 +       READ_UNLOCK(&ip_ct_gre_lock);
4800 +
4801 +       return key;
4802 +}
4803 +
4804 +/* add a single keymap entry, associate with specified expect */
4805 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
4806 +                        struct ip_conntrack_tuple *t, int reply)
4807 +{
4808 +       struct ip_ct_gre_keymap *km;
4809 +
4810 +       km = kmalloc(sizeof(*km), GFP_ATOMIC);
4811 +       if (!km)
4812 +               return -1;
4813 +
4814 +       /* initializing list head should be sufficient */
4815 +       memset(km, 0, sizeof(*km));
4816 +
4817 +       memcpy(&km->tuple, t, sizeof(*t));
4818 +
4819 +       if (!reply)
4820 +               exp->proto.gre.keymap_orig = km;
4821 +       else
4822 +               exp->proto.gre.keymap_reply = km;
4823 +
4824 +       DEBUGP("adding new entry %p: ", km);
4825 +       DUMP_TUPLE_GRE(&km->tuple);
4826 +
4827 +       WRITE_LOCK(&ip_ct_gre_lock);
4828 +       list_append(&gre_keymap_list, km);
4829 +       WRITE_UNLOCK(&ip_ct_gre_lock);
4830 +
4831 +       return 0;
4832 +}
4833 +
4834 +/* change the tuple of a keymap entry (used by nat helper) */
4835 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
4836 +                            struct ip_conntrack_tuple *t)
4837 +{
4838 +       DEBUGP("changing entry %p to: ", km);
4839 +       DUMP_TUPLE_GRE(t);
4840 +
4841 +       WRITE_LOCK(&ip_ct_gre_lock);
4842 +       memcpy(&km->tuple, t, sizeof(km->tuple));
4843 +       WRITE_UNLOCK(&ip_ct_gre_lock);
4844 +}
4845 +
4846 +/* destroy the keymap entries associated with specified expect */
4847 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
4848 +{
4849 +       DEBUGP("entering for exp %p\n", exp);
4850 +       WRITE_LOCK(&ip_ct_gre_lock);
4851 +       if (exp->proto.gre.keymap_orig) {
4852 +               DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
4853 +               list_del(&exp->proto.gre.keymap_orig->list);
4854 +               kfree(exp->proto.gre.keymap_orig);
4855 +               exp->proto.gre.keymap_orig = NULL;
4856 +       }
4857 +       if (exp->proto.gre.keymap_reply) {
4858 +               DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
4859 +               list_del(&exp->proto.gre.keymap_reply->list);
4860 +               kfree(exp->proto.gre.keymap_reply);
4861 +               exp->proto.gre.keymap_reply = NULL;
4862 +       }
4863 +       WRITE_UNLOCK(&ip_ct_gre_lock);
4864 +}
4865 +
4866 +
4867 +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
4868 +
4869 +/* invert gre part of tuple */
4870 +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
4871 +                           const struct ip_conntrack_tuple *orig)
4872 +{
4873 +       tuple->dst.u.gre.protocol = orig->dst.u.gre.protocol;
4874 +       tuple->dst.u.gre.version = orig->dst.u.gre.version;
4875 +
4876 +       tuple->dst.u.gre.key = orig->src.u.gre.key;
4877 +       tuple->src.u.gre.key = orig->dst.u.gre.key;
4878 +
4879 +       return 1;
4880 +}
4881 +
4882 +/* gre hdr info to tuple */
4883 +static int gre_pkt_to_tuple(const void *datah, size_t datalen,
4884 +                           struct ip_conntrack_tuple *tuple)
4885 +{
4886 +       struct gre_hdr *grehdr = (struct gre_hdr *) datah;
4887 +       struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
4888 +       u_int32_t srckey;
4889 +
4890 +       /* core guarantees 8 protocol bytes, no need for size check */
4891 +
4892 +       tuple->dst.u.gre.version = grehdr->version; 
4893 +       tuple->dst.u.gre.protocol = grehdr->protocol;
4894 +
4895 +       switch (grehdr->version) {
4896 +               case GRE_VERSION_1701:
4897 +                       if (!grehdr->key) {
4898 +                               DEBUGP("Can't track GRE without key\n");
4899 +                               return 0;
4900 +                       }
4901 +                       tuple->dst.u.gre.key = *(gre_key(grehdr));
4902 +                       break;
4903 +
4904 +               case GRE_VERSION_PPTP:
4905 +                       if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
4906 +                               DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
4907 +                               return 0;
4908 +                       }
4909 +                       tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
4910 +                       break;
4911 +
4912 +               default:
4913 +                       printk(KERN_WARNING "unknown GRE version %hu\n",
4914 +                               tuple->dst.u.gre.version);
4915 +                       return 0;
4916 +       }
4917 +
4918 +       srckey = gre_keymap_lookup(tuple);
4919 +
4920 +#if 0
4921 +       DEBUGP("found src key %x for tuple ", ntohl(srckey));
4922 +       DUMP_TUPLE_GRE(tuple);
4923 +#endif
4924 +       tuple->src.u.gre.key = srckey;
4925 +
4926 +       return 1;
4927 +}
4928 +
4929 +/* print gre part of tuple */
4930 +static unsigned int gre_print_tuple(char *buffer,
4931 +                                   const struct ip_conntrack_tuple *tuple)
4932 +{
4933 +       return sprintf(buffer, "version=%d protocol=0x%04x srckey=0x%x dstkey=0x%x ", 
4934 +                       tuple->dst.u.gre.version,
4935 +                       ntohs(tuple->dst.u.gre.protocol),
4936 +                       ntohl(tuple->src.u.gre.key),
4937 +                       ntohl(tuple->dst.u.gre.key));
4938 +}
4939 +
4940 +/* print private data for conntrack */
4941 +static unsigned int gre_print_conntrack(char *buffer,
4942 +                                       const struct ip_conntrack *ct)
4943 +{
4944 +       return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
4945 +                      (ct->proto.gre.timeout / HZ),
4946 +                      (ct->proto.gre.stream_timeout / HZ));
4947 +}
4948 +
4949 +/* Returns verdict for packet, and may modify conntrack */
4950 +static int gre_packet(struct ip_conntrack *ct,
4951 +                     struct iphdr *iph, size_t len,
4952 +                     enum ip_conntrack_info conntrackinfo)
4953 +{
4954 +       /* If we've seen traffic both ways, this is a GRE connection.
4955 +        * Extend timeout. */
4956 +       if (ct->status & IPS_SEEN_REPLY) {
4957 +               ip_ct_refresh(ct, ct->proto.gre.stream_timeout);
4958 +               /* Also, more likely to be important, and not a probe. */
4959 +               set_bit(IPS_ASSURED_BIT, &ct->status);
4960 +       } else
4961 +               ip_ct_refresh(ct, ct->proto.gre.timeout);
4962 +       
4963 +       return NF_ACCEPT;
4964 +}
4965 +
4966 +/* Called when a new connection for this protocol found. */
4967 +static int gre_new(struct ip_conntrack *ct,
4968 +                  struct iphdr *iph, size_t len)
4969 +{ 
4970 +       DEBUGP(": ");
4971 +       DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
4972 +
4973 +       /* initialize to sane value.  Ideally a conntrack helper
4974 +        * (e.g. in case of pptp) is increasing them */
4975 +       ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
4976 +       ct->proto.gre.timeout = GRE_TIMEOUT;
4977 +
4978 +       return 1;
4979 +}
4980 +
4981 +/* Called when a conntrack entry has already been removed from the hashes
4982 + * and is about to be deleted from memory */
4983 +static void gre_destroy(struct ip_conntrack *ct)
4984 +{
4985 +       struct ip_conntrack_expect *master = ct->master;
4986 +
4987 +       DEBUGP(" entering\n");
4988 +
4989 +       if (!master) {
4990 +               DEBUGP("no master exp for ct %p\n", ct);
4991 +               return;
4992 +       }
4993 +
4994 +       ip_ct_gre_keymap_destroy(master);
4995 +}
4996 +
4997 +/* protocol helper struct */
4998 +static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
4999 +                                           "gre", 
5000 +                                           gre_pkt_to_tuple,
5001 +                                           gre_invert_tuple,
5002 +                                           gre_print_tuple,
5003 +                                           gre_print_conntrack,
5004 +                                           gre_packet,
5005 +                                           gre_new,
5006 +                                           gre_destroy,
5007 +                                           NULL,
5008 +                                           THIS_MODULE };
5009 +
5010 +/* ip_conntrack_proto_gre initialization */
5011 +static int __init init(void)
5012 +{
5013 +       int retcode;
5014 +
5015 +       if ((retcode = ip_conntrack_protocol_register(&gre))) {
5016 +                printk(KERN_ERR "Unable to register conntrack protocol "
5017 +                               "helper for gre: %d\n", retcode);
5018 +               return -EIO;
5019 +       }
5020 +
5021 +       return 0;
5022 +}
5023 +
5024 +static void __exit fini(void)
5025 +{
5026 +       struct list_head *pos, *n;
5027 +
5028 +       /* delete all keymap entries */
5029 +       WRITE_LOCK(&ip_ct_gre_lock);
5030 +       list_for_each_safe(pos, n, &gre_keymap_list) {
5031 +               DEBUGP("deleting keymap %p at module unload time\n", pos);
5032 +               list_del(pos);
5033 +               kfree(pos);
5034 +       }
5035 +       WRITE_UNLOCK(&ip_ct_gre_lock);
5036 +
5037 +       ip_conntrack_protocol_unregister(&gre); 
5038 +}
5039 +
5040 +EXPORT_SYMBOL(ip_ct_gre_keymap_add);
5041 +EXPORT_SYMBOL(ip_ct_gre_keymap_change);
5042 +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
5043 +
5044 +module_init(init);
5045 +module_exit(fini);
5046 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
5047 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_quake3.c     1970-01-01 01:00:00.000000000 +0100
5048 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_quake3.c 2003-12-11 10:24:00.845688024 +0100
5049 @@ -0,0 +1,156 @@
5050 +/* Quake3 extension for IP connection tracking
5051 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5052 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5053 + *
5054 + * ip_conntrack_quake3.c v0.04 2002-08-31
5055 + *
5056 + *      This program is free software; you can redistribute it and/or
5057 + *      modify it under the terms of the GNU General Public License
5058 + *      as published by the Free Software Foundation; either version
5059 + *      2 of the License, or (at your option) any later version.
5060 + *
5061 + *      Module load syntax:
5062 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5063 + *
5064 + *      please give the ports of all Quake3 master servers You wish to 
5065 + *      connect to. If you don't specify ports, the default will be UDP 
5066 + *      port 27950.
5067 + *
5068 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5069 + */
5070 +
5071 +#include <linux/module.h>
5072 +#include <linux/ip.h>
5073 +#include <linux/udp.h>
5074 +
5075 +#include <linux/netfilter.h>
5076 +#include <linux/netfilter_ipv4/ip_tables.h>
5077 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5078 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5079 +
5080 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5081 +
5082 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5083 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5084 +MODULE_LICENSE("GPL");
5085 +
5086 +#define MAX_PORTS 8
5087 +static int ports[MAX_PORTS];
5088 +static int ports_c = 0;
5089 +#ifdef MODULE_PARM
5090 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5091 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5092 +#endif
5093 +
5094 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5095 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5096 +#if 0 
5097 +#define DEBUGP printk
5098 +#else
5099 +#define DEBUGP(format, args...)
5100 +#endif
5101 +
5102 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5103 +
5104 +static int quake3_help(const struct iphdr *iph, size_t len,
5105 +       struct ip_conntrack *ct,
5106 +       enum ip_conntrack_info ctinfo)
5107 +{
5108 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5109 +       int dir = CTINFO2DIR(ctinfo);
5110 +       struct ip_conntrack_expect exp;
5111 +       int i;
5112 +       
5113 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5114 +       if (ctinfo != IP_CT_ESTABLISHED
5115 +           && ctinfo != IP_CT_IS_REPLY) {
5116 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5117 +               return NF_ACCEPT;
5118 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5119 +       
5120 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5121 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5122 +                   i+6 < ntohs(udph->len);
5123 +                   i+=7) {
5124 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5125 +                              i, ntohs(udph->len),
5126 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
5127 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5128 +
5129 +                       memset(&exp, 0, sizeof(exp));
5130 +
5131 +                       exp.tuple = ((struct ip_conntrack_tuple)
5132 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5133 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
5134 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
5135 +                                        IPPROTO_UDP } }
5136 +                                   );
5137 +                       exp.mask  = ((struct ip_conntrack_tuple)
5138 +                                    { { 0xFFFFFFFF, { 0 } },
5139 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5140 +                       exp.expectfn = NULL;
5141 +
5142 +                       ip_conntrack_expect_related(ct, &exp);
5143 +               }
5144 +
5145 +       }
5146 +       
5147 +       return(NF_ACCEPT);
5148 +}
5149 +
5150 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5151 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
5152 +
5153 +static void fini(void)
5154 +{
5155 +       int i;
5156 +
5157 +       for(i = 0 ; (i < ports_c); i++) {
5158 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5159 +                                       ports[i]);
5160 +               ip_conntrack_helper_unregister(&quake3[i]);
5161 +       } 
5162 +}
5163 +
5164 +static int __init init(void)
5165 +{
5166 +       int i, ret;
5167 +       char *tmpname;
5168 +
5169 +       if(!ports[0])
5170 +               ports[0]=QUAKE3_MASTER_PORT;
5171 +
5172 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5173 +               /* Create helper structure */
5174 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5175 +
5176 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5177 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5178 +               quake3[i].mask.dst.protonum = 0xFFFF;
5179 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
5180 +               quake3[i].help = quake3_help;
5181 +               quake3[i].me = THIS_MODULE;
5182 +
5183 +               tmpname = &quake3_names[i][0];
5184 +               if (ports[i] == QUAKE3_MASTER_PORT)
5185 +                       sprintf(tmpname, "quake3");
5186 +               else
5187 +                       sprintf(tmpname, "quake3-%d", i);
5188 +               quake3[i].name = tmpname;
5189 +               
5190 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5191 +                      ports[i]);
5192 +
5193 +               ret=ip_conntrack_helper_register(&quake3[i]);
5194 +               if(ret) {
5195 +                       fini();
5196 +                       return(ret);
5197 +               }
5198 +               ports_c++;
5199 +       }
5200 +
5201 +       return(0);
5202 +}
5203 +
5204 +module_init(init);
5205 +module_exit(fini);
5206 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
5207 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c    1970-01-01 01:00:00.000000000 +0100
5208 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c        2003-12-11 10:24:04.352154960 +0100
5209 @@ -0,0 +1,508 @@
5210 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
5211 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5212 + *     - original rpc tracking module
5213 + *     - "recent" connection handling for kernel 2.3+ netfilter
5214 + *
5215 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5216 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5217 + *
5218 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5219 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
5220 + *     - extended matching to support filtering on procedures
5221 + *
5222 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
5223 + *
5224 + *     This program is free software; you can redistribute it and/or
5225 + *     modify it under the terms of the GNU General Public License
5226 + *     as published by the Free Software Foundation; either version
5227 + *     2 of the License, or (at your option) any later version.
5228 + **
5229 + *     Module load syntax:
5230 + *     insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
5231 + *
5232 + *     Please give the ports of all RPC servers you wish to connect to.
5233 + *     If you don't specify ports, the default will be port 111.
5234 + **
5235 + *     Note to all:
5236 + *
5237 + *     RPCs should not be exposed to the internet - ask the Pentagon;
5238 + *
5239 + *       "The unidentified crackers pleaded guilty in July to charges
5240 + *        of juvenile delinquency stemming from a string of Pentagon
5241 + *        network intrusions in February.
5242 + *
5243 + *        The youths, going by the names TooShort and Makaveli, used
5244 + *        a common server security hole to break in, according to
5245 + *        Dane Jasper, owner of the California Internet service
5246 + *        provider, Sonic. They used the hole, known as the 'statd'
5247 + *        exploit, to attempt more than 800 break-ins, Jasper said."
5248 + *
5249 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5250 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
5251 + **
5252 + */
5253 +
5254 +#include <linux/module.h>
5255 +#include <linux/netfilter.h>
5256 +#include <linux/ip.h>
5257 +#include <net/checksum.h>
5258 +#include <net/tcp.h>
5259 +
5260 +#include <asm/param.h>
5261 +#include <linux/sched.h>
5262 +#include <linux/timer.h>
5263 +#include <linux/stddef.h>
5264 +#include <linux/list.h>
5265 +
5266 +#include <linux/netfilter_ipv4/lockhelp.h>
5267 +#include <linux/netfilter_ipv4/ip_tables.h>
5268 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5269 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5270 +
5271 +#define MAX_PORTS 8
5272 +static int ports[MAX_PORTS];
5273 +static int ports_n_c = 0;
5274 +
5275 +#ifdef MODULE_PARM
5276 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5277 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5278 +#endif
5279 +
5280 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5281 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
5282 +MODULE_LICENSE("GPL");
5283 +
5284 +#if 0
5285 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
5286 +                                       format, ## args)
5287 +#else
5288 +#define DEBUGP(format, args...)
5289 +#endif
5290 +
5291 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
5292 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
5293 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
5294 +#include <linux/netfilter_ipv4/listhelp.h>
5295 +
5296 +/* For future conections RPC, using client's cache bindings
5297 + * I'll use ip_conntrack_lock to lock these lists         */
5298 +
5299 +LIST_HEAD(request_p_list_tcp);
5300 +
5301 +
5302 +static void delete_request_p(unsigned long request_p_ul) 
5303 +{
5304 +       struct request_p *p = (void *)request_p_ul;
5305 +       
5306 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5307 +       LIST_DELETE(&request_p_list_tcp, p);
5308 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5309 +       kfree(p);
5310 +       return;
5311 +}
5312 +
5313 +
5314 +static void req_cl(struct request_p * r)
5315 +{
5316 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5317 +       del_timer(&r->timeout);
5318 +       LIST_DELETE(&request_p_list_tcp, r);
5319 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5320 +       kfree(r);
5321 +       return;
5322 +}
5323 +
5324 +
5325 +static void clean_request(struct list_head *list)
5326 +{
5327 +       struct list_head *first = list->prev;
5328 +       struct list_head *temp = list->next;
5329 +       struct list_head *aux;
5330 +
5331 +       if (list_empty(list))
5332 +               return;
5333 +
5334 +       while (first != temp) {
5335 +               aux = temp->next;
5336 +               req_cl((struct request_p *)temp);
5337 +               temp = aux;     
5338 +       }
5339 +       req_cl((struct request_p *)temp);
5340 +       return;
5341 +}
5342 +
5343 +
5344 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5345 +                    u_int16_t port)
5346 +{
5347 +       struct request_p *req_p;
5348 +       
5349 +       /* Verifies if entry already exists */
5350 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5351 +       req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5352 +               struct request_p *, xid, ip, port);
5353 +
5354 +       if (req_p) {
5355 +               /* Refresh timeout */
5356 +               if (del_timer(&req_p->timeout)) {
5357 +                       req_p->timeout.expires = jiffies + EXP;
5358 +                       add_timer(&req_p->timeout);     
5359 +               } 
5360 +               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5361 +               return; 
5362 +
5363 +       }
5364 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
5365 +       
5366 +       /* Allocate new request_p */
5367 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5368 +       if (!req_p) {
5369 +               DEBUGP("can't allocate request_p\n");
5370 +               return;                 
5371 +       }
5372 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
5373 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5374 +                       NULL }}); 
5375 +      
5376 +       /* Initialize timer */
5377 +       init_timer(&req_p->timeout);
5378 +       req_p->timeout.function = delete_request_p;
5379 +       add_timer(&req_p->timeout); 
5380 +
5381 +       /* Put in list */
5382 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
5383 +       list_prepend(&request_p_list_tcp, req_p);
5384 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
5385 +       return; 
5386 +
5387 +}
5388 +
5389 +
5390 +static int check_rpc_packet(const u_int32_t *data,
5391 +                       int dir, struct ip_conntrack *ct,
5392 +                       struct list_head request_p_list)
5393 +{
5394 +       struct request_p *req_p;
5395 +       u_int32_t xid;
5396 +       struct ip_conntrack_expect expect, *exp = &expect;
5397 +
5398 +        /* Translstion's buffer for XDR */
5399 +        u_int16_t port_buf;
5400 +
5401 +
5402 +       /* Get XID */
5403 +       xid = *data;
5404 +
5405 +       /* This does sanity checking on RPC payloads,
5406 +        * and permits only the RPC "get port" (3)
5407 +        * in authorised procedures in client
5408 +        * communications with the portmapper.
5409 +        */
5410 +
5411 +       /* perform direction dependant RPC work */
5412 +       if (dir == IP_CT_DIR_ORIGINAL) {
5413 +
5414 +               data += 5;
5415 +
5416 +               /* Get RPC requestor */
5417 +               if (IXDR_GET_INT32(data) != 3) {
5418 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5419 +                       return NF_ACCEPT;
5420 +               }
5421 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5422 +
5423 +               data++;
5424 +
5425 +               /* Jump Credentials and Verfifier */
5426 +               data += IXDR_GET_INT32(data) + 2;
5427 +               data += IXDR_GET_INT32(data) + 2;
5428 +
5429 +               /* Get RPC procedure */
5430 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5431 +                       (unsigned int)IXDR_GET_INT32(data));
5432 +
5433 +               /* Get RPC protocol and store against client parameters */
5434 +               data = data + 2;
5435 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5436 +                               ct->tuplehash[dir].tuple.src.u.all);
5437 +
5438 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5439 +                       xid, IXDR_GET_INT32(data),
5440 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5441 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
5442 +
5443 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
5444 +                       (unsigned int)IXDR_GET_INT32(data));
5445 +
5446 +       } else {
5447 +
5448 +               /* Check for returning packet's stored counterpart */
5449 +               req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
5450 +                                 struct request_p *, xid,
5451 +                                 ct->tuplehash[!dir].tuple.src.ip,
5452 +                                 ct->tuplehash[!dir].tuple.src.u.all);
5453 +
5454 +               /* Drop unexpected packets */
5455 +               if (!req_p) {
5456 +                       DEBUGP("packet is not expected. [skip]\n");
5457 +                       return NF_ACCEPT;
5458 +               }
5459 +
5460 +               /* Verifies if packet is really an RPC reply packet */
5461 +               data = data++;
5462 +               if (IXDR_GET_INT32(data) != 1) {
5463 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
5464 +                       return NF_ACCEPT;
5465 +               }
5466 +
5467 +               /* Is status accept? */
5468 +               data++;
5469 +               if (IXDR_GET_INT32(data)) {
5470 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
5471 +                       return NF_ACCEPT;
5472 +               }
5473 +
5474 +               /* Get Verifier length. Jump verifier */
5475 +               data++;
5476 +               data = data + IXDR_GET_INT32(data) + 2;
5477 +
5478 +               /* Is accpet status "success"? */
5479 +               if (IXDR_GET_INT32(data)) {
5480 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5481 +                       return NF_ACCEPT;
5482 +               }
5483 +
5484 +               /* Get server port number */      
5485 +               data++;
5486 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
5487 +
5488 +               /* If a packet has made it this far then it deserves an
5489 +                * expectation ...  if port == 0, then this service is 
5490 +                * not going to be registered.
5491 +                */
5492 +               if (port_buf) {
5493 +                       DEBUGP("port found: %u\n", port_buf);
5494 +
5495 +                       memset(&expect, 0, sizeof(expect));
5496 +
5497 +                       /* Watch out, Radioactive-Man! */
5498 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5499 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5500 +                       exp->mask.src.ip = 0xffffffff;
5501 +                       exp->mask.dst.ip = 0xffffffff;
5502 +
5503 +                       switch (req_p->proto) {
5504 +                               case IPPROTO_UDP:
5505 +                                       exp->tuple.src.u.udp.port = 0;
5506 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
5507 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
5508 +                                       exp->mask.src.u.udp.port = 0;
5509 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
5510 +                                       exp->mask.dst.protonum = 0xffff;
5511 +                                       break;
5512 +
5513 +                               case IPPROTO_TCP:
5514 +                                       exp->tuple.src.u.tcp.port = 0;
5515 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
5516 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
5517 +                                       exp->mask.src.u.tcp.port = 0;
5518 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
5519 +                                       exp->mask.dst.protonum = 0xffff;
5520 +                                       break;
5521 +                       }
5522 +                       exp->expectfn = NULL;
5523 +
5524 +                       ip_conntrack_expect_related(ct, &expect);
5525 +
5526 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
5527 +                               NIPQUAD(exp->tuple.src.ip),
5528 +                               NIPQUAD(exp->tuple.dst.ip),
5529 +                               port_buf, req_p->proto);
5530 +
5531 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
5532 +                               NIPQUAD(exp->mask.src.ip),
5533 +                               NIPQUAD(exp->mask.dst.ip),
5534 +                               exp->mask.dst.protonum);
5535 +
5536 +               }
5537 +
5538 +               req_cl(req_p);
5539 +
5540 +               DEBUGP("packet evaluated. [expect]\n");
5541 +               return NF_ACCEPT;
5542 +       }
5543 +
5544 +       return NF_ACCEPT;
5545 +
5546 +}
5547 +
5548 +
5549 +/* RPC TCP helper */
5550 +static int help(const struct iphdr *iph, size_t len,
5551 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5552 +{
5553 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5554 +       const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
5555 +       size_t tcplen = len - iph->ihl * 4;
5556 +
5557 +       int dir = CTINFO2DIR(ctinfo);
5558 +       int crp_ret;
5559 +
5560 +
5561 +       DEBUGP("new packet to evaluate ..\n");
5562 +
5563 +       /* This works for packets like handshake packets, ignore */
5564 +       if (len == ((tcph->doff + iph->ihl) * 4)) {
5565 +               DEBUGP("packet has no data (may still be handshaking). [skip]\n");
5566 +               return NF_ACCEPT;
5567 +       }
5568 +
5569 +       /* Until there's been traffic both ways, don't look in packets. */
5570 +       if (ctinfo != IP_CT_ESTABLISHED
5571 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5572 +               DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
5573 +               DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
5574 +               DEBUGP("packet is not yet part of a two way stream. [skip]\n");
5575 +               return NF_ACCEPT;
5576 +       }
5577 +
5578 +       /* Not whole TCP header? */
5579 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5580 +               DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
5581 +               DEBUGP("packet does not contain a complete TCP header. [skip]\n");
5582 +               return NF_ACCEPT;
5583 +       }
5584 +
5585 +       /* FIXME: Source route IP option packets --RR */
5586 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5587 +                        csum_partial((char *) tcph, tcplen, 0))) {
5588 +               DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5589 +                    tcph, tcplen, NIPQUAD(iph->saddr),
5590 +                    NIPQUAD(iph->daddr));
5591 +               DEBUGP("[note: failure to get past this error may indicate source routing]\n");
5592 +               DEBUGP("packet contains a bad checksum. [skip]\n");
5593 +               return NF_ACCEPT;
5594 +       }
5595 +
5596 +       /* perform direction dependant protocol work */
5597 +       if (dir == IP_CT_DIR_ORIGINAL) {
5598 +
5599 +               DEBUGP("packet is from the initiator. [cont]\n");
5600 +
5601 +               /* Tests if packet len is ok */
5602 +               if ((tcplen - (tcph->doff * 4)) != 60) {
5603 +                       DEBUGP("packet length is not correct. [skip]\n");
5604 +                       return NF_ACCEPT;
5605 +               }
5606 +
5607 +       } else {
5608 +
5609 +               DEBUGP("packet is from the receiver. [cont]\n");
5610 +
5611 +               /* Tests if packet len is ok */
5612 +               if ((tcplen - (tcph->doff * 4)) != 32) {
5613 +                       DEBUGP("packet length is not correct. [skip]\n");
5614 +                       return NF_ACCEPT;
5615 +               }
5616 +       }
5617 +
5618 +       /* Get to the data */
5619 +       data++;
5620 +
5621 +       /* Check the RPC data */
5622 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
5623 +
5624 +       return crp_ret;
5625 +
5626 +}
5627 +
5628 +
5629 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
5630 +
5631 +static void fini(void);
5632 +
5633 +
5634 +static int __init init(void)
5635 +{
5636 +       int port, ret;
5637 +       static char name[10];
5638 +
5639 +
5640 +       /* If no port given, default to standard RPC port */
5641 +       if (ports[0] == 0)
5642 +               ports[0] = RPC_PORT;
5643 +
5644 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5645 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5646 +
5647 +                if (ports[port] == RPC_PORT)
5648 +                        sprintf(name, "rpc");
5649 +                else
5650 +                        sprintf(name, "rpc-%d", port);
5651 +
5652 +               rpc_helpers[port].name = name;
5653 +               rpc_helpers[port].me = THIS_MODULE;
5654 +               rpc_helpers[port].max_expected = 1;
5655 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5656 +               rpc_helpers[port].timeout = 0;
5657 +
5658 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5659 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
5660 +
5661 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
5662 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
5663 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
5664 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
5665 +
5666 +               rpc_helpers[port].help = help;
5667 +
5668 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5669 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5670 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
5671 +                       ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
5672 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
5673 +                       ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
5674 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5675 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
5676 +                       ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
5677 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
5678 +                       ntohs(rpc_helpers[port].mask.src.u.tcp.port));
5679 +
5680 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
5681 +
5682 +               if (ret) {
5683 +                       printk("ERROR registering port %d\n",
5684 +                               ports[port]);
5685 +                       fini();
5686 +                       return -EBUSY;
5687 +               }
5688 +               ports_n_c++;
5689 +       }
5690 +       return 0;
5691 +}
5692 +
5693 +
5694 +/* This function is intentionally _NOT_ defined as __exit, because 
5695 + * it is needed by the init function */
5696 +static void fini(void)
5697 +{
5698 +       int port;
5699 +
5700 +       DEBUGP("cleaning request list\n");
5701 +       clean_request(&request_p_list_tcp);
5702 +
5703 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
5704 +               DEBUGP("unregistering port %d\n", ports[port]);
5705 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
5706 +       }
5707 +}
5708 +
5709 +
5710 +module_init(init);
5711 +module_exit(fini);
5712 +
5713 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
5714 +EXPORT_SYMBOL(request_p_list_tcp);
5715 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
5716 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
5717 +
5718 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
5719 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c    1970-01-01 01:00:00.000000000 +0100
5720 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rpc_udp.c        2003-12-11 10:24:04.353154808 +0100
5721 @@ -0,0 +1,503 @@
5722 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
5723 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
5724 + *     - original rpc tracking module
5725 + *     - "recent" connection handling for kernel 2.3+ netfilter
5726 + *
5727 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
5728 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
5729 + *
5730 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5731 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
5732 + *     - extended matching to support filtering on procedures
5733 + *
5734 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
5735 + *
5736 + *     This program is free software; you can redistribute it and/or
5737 + *     modify it under the terms of the GNU General Public License
5738 + *     as published by the Free Software Foundation; either version
5739 + *     2 of the License, or (at your option) any later version.
5740 + **
5741 + *     Module load syntax:
5742 + *     insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
5743 + *
5744 + *     Please give the ports of all RPC servers you wish to connect to.
5745 + *     If you don't specify ports, the default will be port 111.
5746 + **
5747 + *     Note to all:
5748 + *
5749 + *     RPCs should not be exposed to the internet - ask the Pentagon;
5750 + *
5751 + *       "The unidentified crackers pleaded guilty in July to charges
5752 + *        of juvenile delinquency stemming from a string of Pentagon
5753 + *        network intrusions in February.
5754 + *
5755 + *        The youths, going by the names TooShort and Makaveli, used
5756 + *        a common server security hole to break in, according to
5757 + *        Dane Jasper, owner of the California Internet service
5758 + *        provider, Sonic. They used the hole, known as the 'statd'
5759 + *        exploit, to attempt more than 800 break-ins, Jasper said."
5760 + *
5761 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
5762 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
5763 + **
5764 + */
5765 +
5766 +#include <linux/module.h>
5767 +#include <linux/netfilter.h>
5768 +#include <linux/ip.h>
5769 +#include <net/checksum.h>
5770 +#include <net/udp.h>
5771 +
5772 +#include <asm/param.h>
5773 +#include <linux/sched.h>
5774 +#include <linux/timer.h>
5775 +#include <linux/stddef.h>
5776 +#include <linux/list.h>
5777 +
5778 +#include <linux/netfilter_ipv4/lockhelp.h>
5779 +#include <linux/netfilter_ipv4/ip_tables.h>
5780 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5781 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
5782 +
5783 +#define MAX_PORTS 8
5784 +static int ports[MAX_PORTS];
5785 +static int ports_n_c = 0;
5786 +
5787 +#ifdef MODULE_PARM
5788 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5789 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
5790 +#endif
5791 +
5792 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
5793 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
5794 +MODULE_LICENSE("GPL");
5795 +
5796 +#if 0
5797 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
5798 +                                       format, ## args)
5799 +#else
5800 +#define DEBUGP(format, args...)
5801 +#endif
5802 +
5803 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
5804 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
5805 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
5806 +#include <linux/netfilter_ipv4/listhelp.h>
5807 +
5808 +/* For future conections RPC, using client's cache bindings
5809 + * I'll use ip_conntrack_lock to lock these lists           */
5810 +
5811 +LIST_HEAD(request_p_list_udp);
5812 +
5813 +
5814 +static void delete_request_p(unsigned long request_p_ul)
5815 +{
5816 +       struct request_p *p = (void *)request_p_ul;
5817 +       
5818 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5819 +       LIST_DELETE(&request_p_list_udp, p);
5820 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
5821 +       kfree(p);
5822 +       return;
5823 +}
5824 +
5825 +
5826 +static void req_cl(struct request_p * r)
5827 +{
5828 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5829 +       del_timer(&r->timeout);
5830 +       LIST_DELETE(&request_p_list_udp, r);
5831 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
5832 +       kfree(r);
5833 +       return;
5834 +}
5835 +
5836 +
5837 +static void clean_request(struct list_head *list)
5838 +{
5839 +       struct list_head *first = list->prev;
5840 +       struct list_head *temp = list->next;
5841 +       struct list_head *aux;
5842 +
5843 +       if (list_empty(list))
5844 +               return;
5845 +
5846 +       while (first != temp) {
5847 +               aux = temp->next;
5848 +               req_cl((struct request_p *)temp);
5849 +               temp = aux;     
5850 +       }
5851 +       req_cl((struct request_p *)temp);
5852 +       return;
5853 +}
5854 +
5855 +
5856 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
5857 +                    u_int16_t port)
5858 +{
5859 +       struct request_p *req_p;
5860 +        
5861 +       /* Verifies if entry already exists */
5862 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5863 +       req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5864 +               struct request_p *, xid, ip, port);
5865 +
5866 +       if (req_p) {
5867 +               /* Refresh timeout */
5868 +               if (del_timer(&req_p->timeout)) {
5869 +                       req_p->timeout.expires = jiffies + EXP;
5870 +                       add_timer(&req_p->timeout);     
5871 +               } 
5872 +               WRITE_UNLOCK(&ipct_rpc_udp_lock);
5873 +               return; 
5874 +
5875 +       }
5876 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
5877 +       
5878 +       /* Allocate new request_p */
5879 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
5880 +       if (!req_p) {
5881 +               DEBUGP("can't allocate request_p\n");
5882 +               return;                 
5883 +       }
5884 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
5885 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
5886 +                       NULL }}); 
5887 +      
5888 +       /* Initialize timer */
5889 +       init_timer(&req_p->timeout);
5890 +       req_p->timeout.function = delete_request_p;
5891 +       add_timer(&req_p->timeout); 
5892 +
5893 +       /* Put in list */
5894 +       WRITE_LOCK(&ipct_rpc_udp_lock);
5895 +       list_prepend(&request_p_list_udp, req_p);
5896 +       WRITE_UNLOCK(&ipct_rpc_udp_lock); 
5897 +       return; 
5898 +
5899 +}
5900 +
5901 +
5902 +static int check_rpc_packet(const u_int32_t *data,
5903 +                       int dir, struct ip_conntrack *ct,
5904 +                       struct list_head request_p_list)
5905 +{
5906 +       struct request_p *req_p;
5907 +       u_int32_t xid;
5908 +       struct ip_conntrack_expect expect, *exp = &expect;
5909 +
5910 +       /* Translstion's buffer for XDR */
5911 +       u_int16_t port_buf;
5912 +
5913 +
5914 +       /* Get XID */
5915 +       xid = *data;
5916 +
5917 +       /* This does sanity checking on RPC payloads,
5918 +        * and permits only the RPC "get port" (3)
5919 +        * in authorised procedures in client
5920 +        * communications with the portmapper.
5921 +        */
5922 +
5923 +       /* perform direction dependant RPC work */
5924 +       if (dir == IP_CT_DIR_ORIGINAL) {
5925 +
5926 +               data += 5;
5927 +
5928 +               /* Get RPC requestor */
5929 +               if (IXDR_GET_INT32(data) != 3) {
5930 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
5931 +                       return NF_ACCEPT;
5932 +               }
5933 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
5934 +
5935 +               data++;
5936 +
5937 +               /* Jump Credentials and Verfifier */
5938 +               data = data + IXDR_GET_INT32(data) + 2;
5939 +               data = data + IXDR_GET_INT32(data) + 2;
5940 +
5941 +               /* Get RPC procedure */
5942 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
5943 +                       (unsigned int)IXDR_GET_INT32(data));
5944 +
5945 +               /* Get RPC protocol and store against client parameters */
5946 +               data = data + 2;
5947 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
5948 +                               ct->tuplehash[dir].tuple.src.u.all);
5949 +
5950 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
5951 +                       xid, IXDR_GET_INT32(data),
5952 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
5953 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
5954 +
5955 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
5956 +                       (unsigned int)IXDR_GET_INT32(data));
5957 +
5958 +       } else {
5959 +
5960 +               /* Check for returning packet's stored counterpart */
5961 +               req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
5962 +                                 struct request_p *, xid,
5963 +                                 ct->tuplehash[!dir].tuple.src.ip,
5964 +                                 ct->tuplehash[!dir].tuple.src.u.all);
5965 +
5966 +               /* Drop unexpected packets */
5967 +               if (!req_p) {
5968 +                       DEBUGP("packet is not expected. [skip]\n");
5969 +                       return NF_ACCEPT;
5970 +               }
5971 +
5972 +               /* Verifies if packet is really an RPC reply packet */
5973 +               data = data++;
5974 +               if (IXDR_GET_INT32(data) != 1) {
5975 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
5976 +                       return NF_ACCEPT;
5977 +               }
5978 +
5979 +               /* Is status accept? */
5980 +               data++;
5981 +               if (IXDR_GET_INT32(data)) {
5982 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
5983 +                       return NF_ACCEPT;
5984 +               }
5985 +
5986 +               /* Get Verifier length. Jump verifier */
5987 +               data++;
5988 +               data = data + IXDR_GET_INT32(data) + 2;
5989 +
5990 +               /* Is accpet status "success"? */
5991 +               if (IXDR_GET_INT32(data)) {
5992 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
5993 +                       return NF_ACCEPT;
5994 +               }
5995 +
5996 +               /* Get server port number */      
5997 +               data++;
5998 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
5999 +
6000 +               /* If a packet has made it this far then it deserves an
6001 +                * expectation ...  if port == 0, then this service is 
6002 +                * not going to be registered.
6003 +                */
6004 +               if (port_buf) {
6005 +                       DEBUGP("port found: %u\n", port_buf);
6006 +
6007 +                       memset(&expect, 0, sizeof(expect));
6008 +
6009 +                       /* Watch out, Radioactive-Man! */
6010 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6011 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
6012 +                       exp->mask.src.ip = 0xffffffff;
6013 +                       exp->mask.dst.ip = 0xffffffff;
6014 +
6015 +                       switch (req_p->proto) {
6016 +                               case IPPROTO_UDP:
6017 +                                       exp->tuple.src.u.udp.port = 0;
6018 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
6019 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
6020 +                                       exp->mask.src.u.udp.port = 0;
6021 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
6022 +                                       exp->mask.dst.protonum = 0xffff;
6023 +                                       break;
6024 +
6025 +                               case IPPROTO_TCP:
6026 +                                       exp->tuple.src.u.tcp.port = 0;
6027 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
6028 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
6029 +                                       exp->mask.src.u.tcp.port = 0;
6030 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
6031 +                                       exp->mask.dst.protonum = 0xffff;
6032 +                                       break;
6033 +                       }
6034 +                       exp->expectfn = NULL;
6035 +
6036 +                       ip_conntrack_expect_related(ct, &expect);
6037 +
6038 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
6039 +                               NIPQUAD(exp->tuple.src.ip),
6040 +                               NIPQUAD(exp->tuple.dst.ip),
6041 +                               port_buf, req_p->proto);
6042 +
6043 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
6044 +                               NIPQUAD(exp->mask.src.ip),
6045 +                               NIPQUAD(exp->mask.dst.ip),
6046 +                               exp->mask.dst.protonum);
6047 +
6048 +               }
6049 +
6050 +               req_cl(req_p);
6051 +
6052 +               DEBUGP("packet evaluated. [expect]\n");
6053 +               return NF_ACCEPT;
6054 +       }
6055 +
6056 +       return NF_ACCEPT;
6057 +
6058 +}
6059 +
6060 +
6061 +/* RPC UDP helper */
6062 +static int help(const struct iphdr *iph, size_t len,
6063 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6064 +{
6065 +       struct udphdr *udph = (void *) iph + iph->ihl * 4;
6066 +       const u_int32_t *data = (const u_int32_t *)udph + 2;
6067 +       size_t udplen = len - iph->ihl * 4;
6068 +       int dir = CTINFO2DIR(ctinfo);
6069 +       int crp_ret;
6070 +
6071 +       /* Checksum */
6072 +       const u_int16_t *chsm = (const u_int16_t *)udph + 3;
6073 +
6074 +
6075 +       DEBUGP("new packet to evaluate ..\n");
6076 +
6077 +       /* Not whole UDP header? */
6078 +       if (udplen < sizeof(struct udphdr)) {
6079 +               DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
6080 +               DEBUGP("packet does not contain a complete UDP header. [skip]\n");
6081 +               return NF_ACCEPT;
6082 +       }
6083 +
6084 +       /* FIXME: Source route IP option packets --RR */
6085 +       if (*chsm) {
6086 +               if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6087 +                   csum_partial((char *)udph, udplen, 0))) {
6088 +                       DEBUGP("[note: failure to get past this error may indicate source routing]\n");
6089 +                       DEBUGP("packet contains a bad checksum. [skip]\n");
6090 +                       return NF_ACCEPT;
6091 +                  } 
6092 +       }
6093 +
6094 +       /* perform direction dependant protocol work */
6095 +       if (dir == IP_CT_DIR_ORIGINAL) {
6096 +
6097 +               DEBUGP("packet is from the initiator. [cont]\n");
6098 +
6099 +               /* Tests if packet len is ok */
6100 +               if ((udplen - sizeof(struct udphdr)) != 56) {
6101 +                       DEBUGP("packet length is not correct. [skip]\n");
6102 +                       return NF_ACCEPT;
6103 +               }
6104 +
6105 +       } else {
6106 +
6107 +               DEBUGP("packet is from the receiver. [cont]\n");
6108 +
6109 +               /* Until there's been traffic both ways, don't look in packets. */
6110 +               if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6111 +                       DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
6112 +                       DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
6113 +                       DEBUGP("packet is not yet part of a two way stream. [skip]\n");
6114 +                       return NF_ACCEPT;
6115 +               }
6116 +
6117 +               /* Tests if packet len is ok */
6118 +                       if ((udplen - sizeof(struct udphdr)) != 28) {
6119 +                       DEBUGP("packet length is not correct. [skip]\n");
6120 +                       return NF_ACCEPT;
6121 +               }
6122 +
6123 +       }
6124 +
6125 +       /* Get to the data */
6126 +       /* udp *data == *correct */
6127 +
6128 +       /* Check the RPC data */
6129 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
6130 +
6131 +       return crp_ret;
6132 +
6133 +}
6134 +
6135 +
6136 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
6137 +
6138 +static void fini(void);
6139 +
6140 +
6141 +static int __init init(void)
6142 +{
6143 +       int port, ret;
6144 +       static char name[10];
6145 +
6146 +
6147 +       /* If no port given, default to standard RPC port */
6148 +       if (ports[0] == 0)
6149 +               ports[0] = RPC_PORT;
6150 +
6151 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6152 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6153 +
6154 +                if (ports[port] == RPC_PORT)
6155 +                        sprintf(name, "rpc");
6156 +                else
6157 +                        sprintf(name, "rpc-%d", port);
6158 +
6159 +               rpc_helpers[port].name = name;
6160 +               rpc_helpers[port].me = THIS_MODULE;
6161 +               rpc_helpers[port].max_expected = 1;
6162 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6163 +               rpc_helpers[port].timeout = 0;
6164 +
6165 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
6166 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
6167 +
6168 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
6169 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
6170 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
6171 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
6172 +
6173 +               rpc_helpers[port].help = help;
6174 +
6175 +               DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
6176 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6177 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
6178 +                       ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
6179 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
6180 +                       ntohs(rpc_helpers[port].tuple.src.u.udp.port));
6181 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6182 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
6183 +                       ntohs(rpc_helpers[port].mask.dst.u.udp.port),
6184 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
6185 +                       ntohs(rpc_helpers[port].mask.src.u.udp.port));
6186 +
6187 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
6188 +
6189 +               if (ret) {
6190 +                       printk("ERROR registering port %d\n",
6191 +                               ports[port]);
6192 +                       fini();
6193 +                       return -EBUSY;
6194 +               }
6195 +               ports_n_c++;
6196 +       }
6197 +       return 0;
6198 +}
6199 +
6200 +
6201 +/* This function is intentionally _NOT_ defined as __exit, because 
6202 + * it is needed by the init function */
6203 +static void fini(void)
6204 +{
6205 +       int port;
6206 +
6207 +       DEBUGP("cleaning request list\n");
6208 +       clean_request(&request_p_list_udp);
6209 +
6210 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
6211 +               DEBUGP("unregistering port %d\n", ports[port]);
6212 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
6213 +       }
6214 +}
6215 +
6216 +
6217 +module_init(init);
6218 +module_exit(fini);
6219 +
6220 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
6221 +EXPORT_SYMBOL(request_p_list_udp);
6222 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
6223 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
6224 +
6225 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
6226 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rsh.c        1970-01-01 01:00:00.000000000 +0100
6227 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rsh.c    2003-12-11 10:24:05.587967088 +0100
6228 @@ -0,0 +1,331 @@
6229 +/* RSH extension for IP connection tracking, Version 1.0
6230 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
6231 + * based on HW's ip_conntrack_irc.c    
6232 + *
6233 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
6234 + *
6235 + *      This program is free software; you can redistribute it and/or
6236 + *      modify it under the terms of the GNU General Public License
6237 + *      as published by the Free Software Foundation; either version
6238 + *      2 of the License, or (at your option) any later version.
6239 + **
6240 + *     Module load syntax:
6241 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
6242 + *     
6243 + *     please give the ports of all RSH servers You wish to connect to.
6244 + *     If You don't specify ports, the default will be port 514
6245 + **
6246 + *      Note to all:
6247 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
6248 + *        unfortunately I babysit some sysadmins that won't migrate
6249 + *       their legacy crap, in our second tier.
6250 + */
6251 +
6252 +
6253 +/*
6254 + *  Some docco ripped from the net to teach me all there is to know about
6255 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
6256 + *  this module).
6257 + *
6258 + *  I have no idea what "unix rshd man pages" these guys have .. but that
6259 + *  is some pretty detailed docco!
6260 + **
6261 + *
6262 + *  4. Of the rsh protocol.
6263 + *  -----------------------
6264 + * 
6265 + *   The rshd listens on TCP port #514. The following info is from the unix
6266 + *   rshd man pages :
6267 + * 
6268 + *   "Service Request Protocol
6269 + * 
6270 + *    When the rshd daemon receives a service request, it initiates the
6271 + *    following protocol:
6272 + * 
6273 + *     1. The rshd daemon checks the source port number for the request.
6274 + *        If the port number is not in the range 0 through 1023, the rshd daemon
6275 + *        terminates the connection.
6276 + * 
6277 + *     2. The rshd daemon reads characters from the socket up to a null byte.
6278 + *        The string read is interpreted as an ASCII number (base 10). If this
6279 + *        number is nonzero, the rshd daemon interprets it as the port number
6280 + *        of a secondary stream to be used as standard error. A second connection
6281 + *        is created to the specified port on the client host. The source port
6282 + *        on the local host is in the range 0 through 1023.
6283 + * 
6284 + *     3. The rshd daemon uses the source address of the initial connection
6285 + *        request to determine the name of the client host. If the name cannot
6286 + *        be determined, the rshd daemon uses the dotted decimal representation
6287 + *        of the client host's address.
6288 + * 
6289 + *     4. The rshd daemon retrieves the following information from the initial
6290 + *        socket:
6291 + * 
6292 + *         * A null-terminated string of at most 16 bytes interpreted as
6293 + *           the user name of the user on the client host.
6294 + * 
6295 + *         * A null-terminated string of at most 16 bytes interpreted as
6296 + *           the user name to be used on the local server host.
6297 + * 
6298 + *         * Another null-terminated string interpreted as a command line
6299 + *           to be passed to a shell on the local server host.
6300 + * 
6301 + *     5. The rshd daemon attempts to validate the user using the following steps:
6302 + * 
6303 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
6304 + *            file and tries to switch to the home directory (using the chdir
6305 + *            subroutine). If either the lookup or the directory change fails,
6306 + *            the rshd daemon terminates the connection.
6307 + * 
6308 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
6309 + *            the /etc/hosts.equiv file to see if the name of the client
6310 + *            workstation is listed. If the client workstation is listed as an
6311 + *            equivalent host, the rshd daemon validates the user.
6312 + * 
6313 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
6314 + *            authenticate the user by checking the .rhosts file.
6315 + * 
6316 + *         d. If either the $HOME/.rhosts authentication fails or the
6317 + *            client host is not an equivalent host, the rshd daemon
6318 + *            terminates the connection.
6319 + * 
6320 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
6321 + *        on the initial connection and passes the command line to the user's
6322 + *        local login shell. The shell then inherits the network connections
6323 + *        established by the rshd daemon."
6324 + * 
6325 + */
6326 +
6327 +
6328 +#include <linux/module.h>
6329 +#include <linux/netfilter.h>
6330 +#include <linux/ip.h>
6331 +#include <net/checksum.h>
6332 +#include <net/tcp.h>
6333 +
6334 +#include <linux/netfilter_ipv4/lockhelp.h>
6335 +#include <linux/netfilter_ipv4/ip_tables.h>
6336 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6337 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
6338 +
6339 +#define MAX_PORTS 8
6340 +static int ports[MAX_PORTS];
6341 +static int ports_n_c = 0;
6342 +
6343 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
6344 +MODULE_DESCRIPTION("RSH connection tracking module");
6345 +MODULE_LICENSE("GPL");
6346 +#ifdef MODULE_PARM
6347 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6348 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
6349 +#endif
6350 +
6351 +DECLARE_LOCK(ip_rsh_lock);
6352 +struct module *ip_conntrack_rsh = THIS_MODULE;
6353 +
6354 +#if 0
6355 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
6356 +                                       format, ## args)
6357 +#else
6358 +#define DEBUGP(format, args...)
6359 +#endif
6360 +
6361 +
6362 +
6363 +/* FIXME: This should be in userspace.  Later. */
6364 +static int help(const struct iphdr *iph, size_t len,
6365 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6366 +{
6367 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6368 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6369 +       const char *data = (const char *) tcph + tcph->doff * 4;
6370 +       u_int32_t tcplen = len - iph->ihl * 4;
6371 +       int dir = CTINFO2DIR(ctinfo);
6372 +        struct ip_conntrack_expect expect, *exp = &expect;
6373 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
6374 +       u_int16_t port;
6375 +       int maxoctet;
6376 +
6377 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
6378 +        *  original array size used in rshd/glibc) -- is there a
6379 +        *  vulnerability in rshd.c in the looped port *= 10?
6380 +        */
6381 +
6382 +
6383 +       DEBUGP("entered\n");
6384 +
6385 +       /* bail if packet is not from RSH client */
6386 +       if (dir == IP_CT_DIR_REPLY)
6387 +               return NF_ACCEPT;
6388 +
6389 +       /* Until there's been traffic both ways, don't look in packets. */
6390 +       if (ctinfo != IP_CT_ESTABLISHED
6391 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6392 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
6393 +               return NF_ACCEPT;
6394 +       }
6395 +
6396 +       /* Not whole TCP header? */
6397 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
6398 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
6399 +               return NF_ACCEPT;
6400 +       }
6401 +
6402 +       /* Checksum invalid?  Ignore. */
6403 +       /* FIXME: Source route IP option packets --RR */
6404 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6405 +                        csum_partial((char *) tcph, tcplen, 0))) {
6406 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6407 +                    tcph, tcplen, NIPQUAD(iph->saddr),
6408 +                    NIPQUAD(iph->daddr));
6409 +               return NF_ACCEPT;
6410 +       }
6411 +
6412 +       /* find the rsh stderr port */
6413 +       maxoctet = 4;
6414 +       port = 0;
6415 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
6416 +               if (*data < 0)
6417 +                       return(1);
6418 +               if (*data == 0)
6419 +                       break;
6420 +               if (*data < 48 || *data > 57) {
6421 +                       DEBUGP("these aren't the packets you're looking for ..\n");
6422 +                       return NF_ACCEPT;
6423 +               }
6424 +               port = port * 10 + ( *data - 48 );
6425 +       }
6426 +
6427 +       /* dont relate sessions that try to expose the client */
6428 +       DEBUGP("found port %u\n", port);
6429 +       if (port > 1023) {
6430 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
6431 +               return NF_ACCEPT;
6432 +       }
6433 +
6434 +
6435 +       LOCK_BH(&ip_rsh_lock);
6436 +
6437 +       /*  new(,related) connection is;
6438 +        *          reply + dst (uint)port + src port (0:1023)
6439 +        */
6440 +       memset(&expect, 0, sizeof(expect));
6441 +
6442 +       /*  save some discovered data, in case someone ever wants to write
6443 +        *  a NAT module for this bastard ..
6444 +        */
6445 +       exp_rsh_info->port = port;
6446 +
6447 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
6448 +
6449 +
6450 +       /* Watch out, Radioactive-Man! */
6451 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6452 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
6453 +       exp->tuple.src.u.tcp.port = 0;
6454 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
6455 +       exp->tuple.dst.protonum = IPPROTO_TCP;
6456 +
6457 +       exp->mask.src.ip = 0xffffffff;
6458 +       exp->mask.dst.ip = 0xffffffff;
6459 +
6460 +       exp->mask.src.u.tcp.port = htons(0xfc00);
6461 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
6462 +       exp->mask.dst.protonum = 0xffff;
6463 +
6464 +       exp->expectfn = NULL;
6465 +
6466 +       ip_conntrack_expect_related(ct, &expect);
6467 +
6468 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6469 +               NIPQUAD(exp->tuple.src.ip),
6470 +               ntohs(exp->tuple.src.u.tcp.port),
6471 +               NIPQUAD(exp->tuple.dst.ip),
6472 +               ntohs(exp->tuple.dst.u.tcp.port));
6473 +
6474 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6475 +               NIPQUAD(exp->mask.src.ip),
6476 +               ntohs(exp->mask.src.u.tcp.port),
6477 +               NIPQUAD(exp->mask.dst.ip),
6478 +               ntohs(exp->mask.dst.u.tcp.port));
6479 +       UNLOCK_BH(&ip_rsh_lock);
6480 +
6481 +       return NF_ACCEPT;
6482 +}
6483 +
6484 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
6485 +
6486 +static void fini(void);
6487 +
6488 +static int __init init(void)
6489 +{
6490 +       int port, ret;
6491 +       static char name[10];
6492 +
6493 +
6494 +       /* If no port given, default to standard RSH port */
6495 +       if (ports[0] == 0)
6496 +               ports[0] = RSH_PORT;
6497 +
6498 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6499 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
6500 +
6501 +                if (ports[port] == RSH_PORT)
6502 +                        sprintf(name, "rsh");
6503 +                else
6504 +                        sprintf(name, "rsh-%d", port);
6505 +
6506 +               rsh_helpers[port].name = name;
6507 +               rsh_helpers[port].me = THIS_MODULE;
6508 +               rsh_helpers[port].max_expected = 1;
6509 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6510 +               rsh_helpers[port].timeout = 0;
6511 +
6512 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
6513 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
6514 +
6515 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
6516 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
6517 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
6518 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
6519 +
6520 +               rsh_helpers[port].help = help;
6521 +
6522 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
6523 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6524 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
6525 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
6526 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
6527 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
6528 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6529 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
6530 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
6531 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
6532 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
6533 +
6534 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
6535 +
6536 +               if (ret) {
6537 +                       printk("ERROR registering port %d\n",
6538 +                               ports[port]);
6539 +                       fini();
6540 +                       return -EBUSY;
6541 +               }
6542 +               ports_n_c++;
6543 +       }
6544 +       return 0;
6545 +}
6546 +
6547 +/* This function is intentionally _NOT_ defined as __exit, because 
6548 + * it is needed by the init function */
6549 +static void fini(void)
6550 +{
6551 +       int port;
6552 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
6553 +               DEBUGP("unregistering port %d\n", ports[port]);
6554 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
6555 +       }
6556 +}
6557 +
6558 +module_init(init);
6559 +module_exit(fini);
6560 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
6561 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_rtsp.c       1970-01-01 01:00:00.000000000 +0100
6562 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_rtsp.c   2003-12-11 11:19:50.678436040 +0100
6563 @@ -0,0 +1,509 @@
6564 +/*
6565 + * RTSP extension for IP connection tracking
6566 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6567 + * based on ip_conntrack_irc.c
6568 + *
6569 + *      This program is free software; you can redistribute it and/or
6570 + *      modify it under the terms of the GNU General Public License
6571 + *      as published by the Free Software Foundation; either version
6572 + *      2 of the License, or (at your option) any later version.
6573 + *
6574 + * Module load syntax:
6575 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6576 + *                              max_outstanding=n setup_timeout=secs
6577 + *
6578 + * If no ports are specified, the default will be port 554.
6579 + *
6580 + * With max_outstanding you can define the maximum number of not yet
6581 + * answered SETUP requests per RTSP session (default 8).
6582 + * With setup_timeout you can specify how long the system waits for
6583 + * an expected data channel (default 300 seconds).
6584 + */
6585 +
6586 +#include <linux/config.h>
6587 +#include <linux/module.h>
6588 +#include <linux/netfilter.h>
6589 +#include <linux/ip.h>
6590 +#include <net/checksum.h>
6591 +#include <net/tcp.h>
6592 +
6593 +#include <linux/netfilter_ipv4/lockhelp.h>
6594 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6595 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6596 +
6597 +#include <linux/ctype.h>
6598 +#define NF_NEED_STRNCASECMP
6599 +#define NF_NEED_STRTOU16
6600 +#define NF_NEED_STRTOU32
6601 +#define NF_NEED_NEXTLINE
6602 +#include <linux/netfilter_helpers.h>
6603 +#define NF_NEED_MIME_NEXTLINE
6604 +#include <linux/netfilter_mime.h>
6605 +
6606 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
6607 +
6608 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
6609 +#ifdef IP_NF_RTSP_DEBUG
6610 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args)
6611 +#else
6612 +#define DEBUGP(args...)
6613 +#endif
6614 +
6615 +#define MAX_PORTS 8
6616 +static int ports[MAX_PORTS];
6617 +static int num_ports = 0;
6618 +static int max_outstanding = 8;
6619 +static unsigned int setup_timeout = 300;
6620 +
6621 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
6622 +MODULE_DESCRIPTION("RTSP connection tracking module");
6623 +MODULE_LICENSE("GPL");
6624 +#ifdef MODULE_PARM
6625 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6626 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
6627 +MODULE_PARM(max_outstanding, "i");
6628 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
6629 +MODULE_PARM(setup_timeout, "i");
6630 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
6631 +#endif
6632 +
6633 +DECLARE_LOCK(ip_rtsp_lock);
6634 +struct module* ip_conntrack_rtsp = THIS_MODULE;
6635 +
6636 +/*
6637 + * Max mappings we will allow for one RTSP connection (for RTP, the number
6638 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
6639 + * ports so keep this reasonably high.  If this is too low, you will see a
6640 + * lot of "no free client map entries" messages.
6641 + */
6642 +#define MAX_PORT_MAPS 16
6643 +
6644 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
6645 +
6646 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
6647 +
6648 +/*
6649 + * Parse an RTSP packet.
6650 + *
6651 + * Returns zero if parsing failed.
6652 + *
6653 + * Parameters:
6654 + *  IN      ptcp        tcp data pointer
6655 + *  IN      tcplen      tcp data len
6656 + *  IN/OUT  ptcpoff     points to current tcp offset
6657 + *  OUT     phdrsoff    set to offset of rtsp headers
6658 + *  OUT     phdrslen    set to length of rtsp headers
6659 + *  OUT     pcseqoff    set to offset of CSeq header
6660 + *  OUT     pcseqlen    set to length of CSeq header
6661 + */
6662 +static int
6663 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
6664 +                   uint* phdrsoff, uint* phdrslen,
6665 +                   uint* pcseqoff, uint* pcseqlen)
6666 +{
6667 +    uint    entitylen = 0;
6668 +    uint    lineoff;
6669 +    uint    linelen;
6670 +
6671 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6672 +    {
6673 +        return 0;
6674 +    }
6675 +
6676 +    *phdrsoff = *ptcpoff;
6677 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
6678 +    {
6679 +        if (linelen == 0)
6680 +        {
6681 +            if (entitylen > 0)
6682 +            {
6683 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
6684 +            }
6685 +            break;
6686 +        }
6687 +        if (lineoff+linelen > tcplen)
6688 +        {
6689 +//            INFOP("!! overrun !!\n");
6690 +            break;
6691 +        }
6692 +
6693 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
6694 +        {
6695 +            *pcseqoff = lineoff;
6696 +            *pcseqlen = linelen;
6697 +        }
6698 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
6699 +        {
6700 +            uint off = lineoff+15;
6701 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
6702 +            nf_strtou32(ptcp+off, &entitylen);
6703 +        }
6704 +    }
6705 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
6706 +
6707 +    return 1;
6708 +}
6709 +
6710 +/*
6711 + * Find lo/hi client ports (if any) in transport header
6712 + * In:
6713 + *   ptcp, tcplen = packet
6714 + *   tranoff, tranlen = buffer to search
6715 + *
6716 + * Out:
6717 + *   pport_lo, pport_hi = lo/hi ports (host endian)
6718 + *
6719 + * Returns nonzero if any client ports found
6720 + *
6721 + * Note: it is valid (and expected) for the client to request multiple
6722 + * transports, so we need to parse the entire line.
6723 + */
6724 +static int
6725 +rtsp_parse_transport(char* ptran, uint tranlen,
6726 +                     struct ip_ct_rtsp_expect* prtspexp)
6727 +{
6728 +    int     rc = 0;
6729 +    uint    off = 0;
6730 +
6731 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
6732 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
6733 +    {
6734 +        //INFOP("sanity check failed\n");
6735 +        return 0;
6736 +    }
6737 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
6738 +    off += 10;
6739 +    SKIP_WSPACE(ptran, tranlen, off);
6740 +
6741 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
6742 +    while (off < tranlen)
6743 +    {
6744 +        const char* pparamend;
6745 +        uint        nextparamoff;
6746 +
6747 +        pparamend = memchr(ptran+off, ',', tranlen-off);
6748 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
6749 +        nextparamoff = pparamend-ptran;
6750 +
6751 +        while (off < nextparamoff)
6752 +        {
6753 +            const char* pfieldend;
6754 +            uint        nextfieldoff;
6755 +
6756 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6757 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6758 +
6759 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
6760 +            {
6761 +                u_int16_t   port;
6762 +                uint        numlen;
6763 +
6764 +                off += 12;
6765 +                numlen = nf_strtou16(ptran+off, &port);
6766 +                off += numlen;
6767 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
6768 +                {
6769 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
6770 +                }
6771 +                else
6772 +                {
6773 +                    prtspexp->loport = prtspexp->hiport = port;
6774 +                    if (ptran[off] == '-')
6775 +                    {
6776 +                        off++;
6777 +                        numlen = nf_strtou16(ptran+off, &port);
6778 +                        off += numlen;
6779 +                        prtspexp->pbtype = pb_range;
6780 +                        prtspexp->hiport = port;
6781 +
6782 +                        // If we have a range, assume rtp:
6783 +                        // loport must be even, hiport must be loport+1
6784 +                        if ((prtspexp->loport & 0x0001) != 0 ||
6785 +                            prtspexp->hiport != prtspexp->loport+1)
6786 +                        {
6787 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
6788 +                                   prtspexp->loport, prtspexp->hiport);
6789 +                            prtspexp->loport &= 0xfffe;
6790 +                            prtspexp->hiport = prtspexp->loport+1;
6791 +                        }
6792 +                    }
6793 +                    else if (ptran[off] == '/')
6794 +                    {
6795 +                        off++;
6796 +                        numlen = nf_strtou16(ptran+off, &port);
6797 +                        off += numlen;
6798 +                        prtspexp->pbtype = pb_discon;
6799 +                        prtspexp->hiport = port;
6800 +                    }
6801 +                    rc = 1;
6802 +                }
6803 +            }
6804 +
6805 +            /*
6806 +             * Note we don't look for the destination parameter here.
6807 +             * If we are using NAT, the NAT module will handle it.  If not,
6808 +             * and the client is sending packets elsewhere, the expectation
6809 +             * will quietly time out.
6810 +             */
6811 +
6812 +            off = nextfieldoff;
6813 +        }
6814 +
6815 +        off = nextparamoff;
6816 +    }
6817 +
6818 +    return rc;
6819 +}
6820 +
6821 +/*** conntrack functions ***/
6822 +
6823 +/* outbound packet: client->server */
6824 +static int
6825 +help_out(const struct iphdr* iph, size_t pktlen,
6826 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6827 +{
6828 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
6829 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
6830 +    uint    tcplen = pktlen - iph->ihl * 4;
6831 +    char*   pdata = (char*)tcph + tcph->doff * 4;
6832 +    uint    datalen = tcplen - tcph->doff * 4;
6833 +    uint    dataoff = 0;
6834 +
6835 +    struct ip_conntrack_expect exp;
6836 +
6837 +    while (dataoff < datalen)
6838 +    {
6839 +        uint    cmdoff = dataoff;
6840 +        uint    hdrsoff = 0;
6841 +        uint    hdrslen = 0;
6842 +        uint    cseqoff = 0;
6843 +        uint    cseqlen = 0;
6844 +        uint    lineoff = 0;
6845 +        uint    linelen = 0;
6846 +        uint    off;
6847 +        int     rc;
6848 +
6849 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
6850 +                                &hdrsoff, &hdrslen,
6851 +                                &cseqoff, &cseqlen))
6852 +        {
6853 +            break;      /* not a valid message */
6854 +        }
6855 +
6856 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
6857 +        {
6858 +            continue;   /* not a SETUP message */
6859 +        }
6860 +        DEBUGP("found a setup message\n");
6861 +
6862 +        memset(&exp, 0, sizeof(exp));
6863 +
6864 +        off = 0;
6865 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
6866 +                                &lineoff, &linelen))
6867 +        {
6868 +            if (linelen == 0)
6869 +            {
6870 +                break;
6871 +            }
6872 +            if (off > hdrsoff+hdrslen)
6873 +            {
6874 +//                INFOP("!! overrun !!");
6875 +                break;
6876 +            }
6877 +
6878 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
6879 +            {
6880 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
6881 +                                     &exp.help.exp_rtsp_info);
6882 +            }
6883 +        }
6884 +
6885 +        if (exp.help.exp_rtsp_info.loport == 0)
6886 +        {
6887 +            DEBUGP("no udp transports found\n");
6888 +            continue;   /* no udp transports found */
6889 +        }
6890 +
6891 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
6892 +              (int)exp.help.exp_rtsp_info.pbtype,
6893 +              exp.help.exp_rtsp_info.loport,
6894 +              exp.help.exp_rtsp_info.hiport);
6895 +
6896 +        LOCK_BH(&ip_rtsp_lock);
6897 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
6898 +        exp.help.exp_rtsp_info.len = hdrslen;
6899 +
6900 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
6901 +        exp.mask.src.ip  = 0xffffffff;
6902 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
6903 +        exp.mask.dst.ip  = 0xffffffff;
6904 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
6905 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
6906 +        exp.tuple.dst.protonum = IPPROTO_UDP;
6907 +        exp.mask.dst.protonum  = 0xffff;
6908 +
6909 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
6910 +                NIPQUAD(exp.tuple.src.ip),
6911 +                ntohs(exp.tuple.src.u.tcp.port),
6912 +                NIPQUAD(exp.tuple.dst.ip),
6913 +                ntohs(exp.tuple.dst.u.tcp.port));
6914 +
6915 +        /* pass the request off to the nat helper */
6916 +        rc = ip_conntrack_expect_related(ct, &exp);
6917 +        UNLOCK_BH(&ip_rtsp_lock);
6918 +        if (rc == 0)
6919 +        {
6920 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
6921 +        }
6922 +        else
6923 +        {
6924 +//            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
6925 +        }
6926 +    }
6927 +
6928 +    return NF_ACCEPT;
6929 +}
6930 +
6931 +/* inbound packet: server->client */
6932 +static int
6933 +help_in(const struct iphdr* iph, size_t pktlen,
6934 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6935 +{
6936 +    return NF_ACCEPT;
6937 +}
6938 +
6939 +static int
6940 +help(const struct iphdr* iph, size_t pktlen,
6941 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
6942 +{
6943 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6944 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
6945 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
6946 +
6947 +    /* Until there's been traffic both ways, don't look in packets. */
6948 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
6949 +    {
6950 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
6951 +        return NF_ACCEPT;
6952 +    }
6953 +
6954 +    /* Not whole TCP header? */
6955 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
6956 +    {
6957 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
6958 +        return NF_ACCEPT;
6959 +    }
6960 +
6961 +    /* Checksum invalid?  Ignore. */
6962 +    /* FIXME: Source route IP option packets --RR */
6963 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6964 +                     csum_partial((char*)tcph, tcplen, 0)))
6965 +    {
6966 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6967 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6968 +        return NF_ACCEPT;
6969 +    }
6970 +
6971 +    switch (CTINFO2DIR(ctinfo))
6972 +    {
6973 +    case IP_CT_DIR_ORIGINAL:
6974 +        help_out(iph, pktlen, ct, ctinfo);
6975 +        break;
6976 +    case IP_CT_DIR_REPLY:
6977 +        help_in(iph, pktlen, ct, ctinfo);
6978 +        break;
6979 +    default:
6980 +        /* oops */
6981 +    }
6982 +
6983 +    return NF_ACCEPT;
6984 +}
6985 +
6986 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
6987 +static char rtsp_names[MAX_PORTS][10];
6988 +
6989 +/* This function is intentionally _NOT_ defined as __exit */
6990 +static void
6991 +fini(void)
6992 +{
6993 +    int i;
6994 +    for (i = 0; i < num_ports; i++)
6995 +    {
6996 +        DEBUGP("unregistering port %d\n", ports[i]);
6997 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
6998 +    }
6999 +}
7000 +
7001 +static int __init
7002 +init(void)
7003 +{
7004 +    int i, ret;
7005 +    struct ip_conntrack_helper *hlpr;
7006 +    char *tmpname;
7007 +
7008 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7009 +
7010 +    if (max_outstanding < 1)
7011 +    {
7012 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
7013 +        return -EBUSY;
7014 +    }
7015 +    if (setup_timeout < 0)
7016 +    {
7017 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
7018 +        return -EBUSY;
7019 +    }
7020 +
7021 +    /* If no port given, default to standard rtsp port */
7022 +    if (ports[0] == 0)
7023 +    {
7024 +        ports[0] = RTSP_PORT;
7025 +    }
7026 +
7027 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
7028 +    {
7029 +        hlpr = &rtsp_helpers[i];
7030 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
7031 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7032 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
7033 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
7034 +        hlpr->mask.dst.protonum = 0xFFFF;
7035 +        hlpr->max_expected = max_outstanding;
7036 +        hlpr->timeout = setup_timeout;
7037 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
7038 +        hlpr->me = ip_conntrack_rtsp;
7039 +        hlpr->help = help;
7040 +
7041 +        tmpname = &rtsp_names[i][0];
7042 +        if (ports[i] == RTSP_PORT)
7043 +        {
7044 +            sprintf(tmpname, "rtsp");
7045 +        }
7046 +        else
7047 +        {
7048 +            sprintf(tmpname, "rtsp-%d", i);
7049 +        }
7050 +        hlpr->name = tmpname;
7051 +
7052 +        DEBUGP("port #%d: %d\n", i, ports[i]);
7053 +
7054 +        ret = ip_conntrack_helper_register(hlpr);
7055 +
7056 +        if (ret)
7057 +        {
7058 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
7059 +            fini();
7060 +            return -EBUSY;
7061 +        }
7062 +        num_ports++;
7063 +    }
7064 +    return 0;
7065 +}
7066 +
7067 +#ifdef CONFIG_IP_NF_NAT_NEEDED
7068 +EXPORT_SYMBOL(ip_rtsp_lock);
7069 +#endif
7070 +
7071 +module_init(init);
7072 +module_exit(fini);
7073 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
7074 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2003-12-11 09:50:30.000000000 +0100
7075 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_standalone.c     2003-12-11 10:24:15.986386288 +0100
7076 @@ -105,6 +105,9 @@
7077                 len += sprintf(buffer + len, "[ASSURED] ");
7078         len += sprintf(buffer + len, "use=%u ",
7079                        atomic_read(&conntrack->ct_general.use));
7080 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
7081 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
7082 +#endif
7083         len += sprintf(buffer + len, "\n");
7084  
7085         return len;
7086 @@ -186,6 +189,26 @@
7087         return ip_conntrack_confirm(*pskb);
7088  }
7089  
7090 +static unsigned int ip_conntrack_defrag(unsigned int hooknum,
7091 +                                       struct sk_buff **pskb,
7092 +                                       const struct net_device *in,
7093 +                                       const struct net_device *out,
7094 +                                       int (*okfn)(struct sk_buff *))
7095 +{
7096 +       /* Previously seen (loopback)?  Ignore.  Do this before
7097 +           fragment check. */
7098 +       if ((*pskb)->nfct)
7099 +               return NF_ACCEPT;
7100 +
7101 +       /* Gather fragments. */
7102 +       if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
7103 +               *pskb = ip_ct_gather_frags(*pskb);
7104 +               if (!*pskb)
7105 +                       return NF_STOLEN;
7106 +       }
7107 +       return NF_ACCEPT;
7108 +}
7109 +
7110  static unsigned int ip_refrag(unsigned int hooknum,
7111                               struct sk_buff **pskb,
7112                               const struct net_device *in,
7113 @@ -226,6 +249,15 @@
7114         return ip_conntrack_in(hooknum, pskb, in, out, okfn);
7115  }
7116  
7117 +/* At the very first: defragment */
7118 +static struct nf_hook_ops ip_conntrack_defrag_ops = {
7119 +       .hook           = ip_conntrack_defrag,
7120 +       .owner          = THIS_MODULE,
7121 +       .pf             = PF_INET,
7122 +       .hooknum        = NF_IP_PRE_ROUTING,
7123 +       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
7124 +};
7125 +
7126  /* Connection tracking may drop packets, but never alters them, so
7127     make it the first hook. */
7128  static struct nf_hook_ops ip_conntrack_in_ops = {
7129 @@ -236,6 +268,14 @@
7130         .priority       = NF_IP_PRI_CONNTRACK,
7131  };
7132  
7133 +static struct nf_hook_ops ip_conntrack_defrag_local_out_ops = {
7134 +       .hook           = ip_conntrack_defrag,
7135 +       .owner          = THIS_MODULE,
7136 +       .pf             = PF_INET,
7137 +       .hooknum        = NF_IP_LOCAL_OUT,
7138 +       .priority       = NF_IP_PRI_CONNTRACK_DEFRAG,
7139 +};
7140 +
7141  static struct nf_hook_ops ip_conntrack_local_out_ops = {
7142         .hook           = ip_conntrack_local,
7143         .owner          = THIS_MODULE,
7144 @@ -368,10 +408,20 @@
7145         if (!proc) goto cleanup_init;
7146         proc->owner = THIS_MODULE;
7147  
7148 +       ret = nf_register_hook(&ip_conntrack_defrag_ops);
7149 +       if (ret < 0) {
7150 +               printk("ip_conntrack: can't register pre-routing defrag hook.\n");
7151 +               goto cleanup_proc;
7152 +       }
7153 +       ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
7154 +       if (ret < 0) {
7155 +               printk("ip_conntrack: can't register local_out defrag hook.\n");
7156 +               goto cleanup_defragops;
7157 +       }
7158         ret = nf_register_hook(&ip_conntrack_in_ops);
7159         if (ret < 0) {
7160                 printk("ip_conntrack: can't register pre-routing hook.\n");
7161 -               goto cleanup_proc;
7162 +               goto cleanup_defraglocalops;
7163         }
7164         ret = nf_register_hook(&ip_conntrack_local_out_ops);
7165         if (ret < 0) {
7166 @@ -409,6 +459,10 @@
7167         nf_unregister_hook(&ip_conntrack_local_out_ops);
7168   cleanup_inops:
7169         nf_unregister_hook(&ip_conntrack_in_ops);
7170 + cleanup_defraglocalops:
7171 +       nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
7172 + cleanup_defragops:
7173 +       nf_unregister_hook(&ip_conntrack_defrag_ops);
7174   cleanup_proc:
7175         proc_net_remove("ip_conntrack");
7176   cleanup_init:
7177 @@ -417,13 +471,20 @@
7178         return ret;
7179  }
7180  
7181 -/* FIXME: Allow NULL functions and sub in pointers to generic for
7182 -   them. --RR */
7183 +/**
7184 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
7185 + * @proto: structure describing this layer 4 protocol helper
7186 + *
7187 + * This function is called by layer 4 protocol helpers to register 
7188 + * themselves with the conntrack core.
7189 + */
7190  int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
7191  {
7192         int ret = 0;
7193         struct list_head *i;
7194  
7195 +       /* FIXME: Allow NULL functions and sub in pointers to generic for
7196 +          them. --RR */
7197         WRITE_LOCK(&ip_conntrack_lock);
7198         list_for_each(i, &protocol_list) {
7199                 if (((struct ip_conntrack_protocol *)i)->proto
7200 @@ -440,12 +501,20 @@
7201         return ret;
7202  }
7203  
7204 +/**
7205 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
7206 + * @proto: structure describing this layer 4 protocol helper
7207 + *
7208 + * This function is called byh layer 4 protocol helpers to unregister
7209 + * themselvers from the conntrack core.  Please note that all conntrack
7210 + * entries for this protocol are deleted from the conntrack hash table.
7211 + */
7212  void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
7213  {
7214         WRITE_LOCK(&ip_conntrack_lock);
7215  
7216 -       /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
7217 -        * helper. So this should be enough - HW */
7218 +       /* ip_ct_find_proto() returns proto_generic in case there is no
7219 +        * protocol helper. So this should be enough - HW */
7220         LIST_DELETE(&protocol_list, proto);
7221         WRITE_UNLOCK(&ip_conntrack_lock);
7222         
7223 @@ -486,6 +555,7 @@
7224  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
7225  EXPORT_SYMBOL(ip_ct_selective_cleanup);
7226  EXPORT_SYMBOL(ip_ct_refresh);
7227 +EXPORT_SYMBOL(ip_ct_death_by_timeout);
7228  EXPORT_SYMBOL(ip_ct_find_proto);
7229  EXPORT_SYMBOL(__ip_ct_find_proto);
7230  EXPORT_SYMBOL(ip_ct_find_helper);
7231 @@ -500,5 +570,6 @@
7232  EXPORT_SYMBOL(ip_conntrack_expect_list);
7233  EXPORT_SYMBOL(ip_conntrack_lock);
7234  EXPORT_SYMBOL(ip_conntrack_hash);
7235 +EXPORT_SYMBOL(ip_conntrack_untracked);
7236  EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
7237  EXPORT_SYMBOL_GPL(ip_conntrack_put);
7238 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
7239 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_talk.c       1970-01-01 01:00:00.000000000 +0100
7240 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_talk.c   2003-12-11 10:24:09.249410464 +0100
7241 @@ -0,0 +1,360 @@
7242 +/* 
7243 + * talk extension for IP connection tracking. 
7244 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7245 + *
7246 + *      This program is free software; you can redistribute it and/or
7247 + *      modify it under the terms of the GNU General Public License
7248 + *      as published by the Free Software Foundation; either version
7249 + *      2 of the License, or (at your option) any later version.
7250 + **
7251 + *     Module load syntax:
7252 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
7253 + *
7254 + *             talk=[0|1]      disable|enable old talk support
7255 + *            ntalk=[0|1]      disable|enable ntalk support
7256 + *           ntalk2=[0|1]      disable|enable ntalk2 support
7257 + *
7258 + *     The default is talk=1 ntalk=1 ntalk2=1
7259 + *
7260 + *     The helper does not support simultaneous talk requests.
7261 + **
7262 + *
7263 + *             ASCII art on talk protocols
7264 + *     
7265 + *     
7266 + *     caller server               callee server
7267 + *             |     \           /
7268 + *             |       \       /
7269 + *             |         \   /
7270 + *             |           /  
7271 + *             |         /   \
7272 + *           2 |     1 /       \ 3
7273 + *     caller client  ----------- callee client
7274 + *                              4
7275 + *
7276 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
7277 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
7278 + *     3. callee client <-> caller server: LOOK_UP invitation
7279 + *     4. callee client <-> caller client: talk data channel
7280 + *
7281 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
7282 + *      draft-hunter-talk-00.txt
7283 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
7284 + */
7285 +#include <linux/config.h>
7286 +#include <linux/module.h>
7287 +#include <linux/netfilter.h>
7288 +#include <linux/ip.h>
7289 +#include <net/checksum.h>
7290 +#include <net/udp.h>
7291 +
7292 +#include <linux/netfilter_ipv4/lockhelp.h>
7293 +#include <linux/netfilter_ipv4/ip_conntrack.h>
7294 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
7295 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7296 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7297 +
7298 +/* Default all talk protocols are supported */
7299 +static int talk = 1;
7300 +static int ntalk = 1;
7301 +static int ntalk2 = 1;
7302 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7303 +MODULE_DESCRIPTION("talk connection tracking module");
7304 +MODULE_LICENSE("GPL");
7305 +#ifdef MODULE_PARM
7306 +MODULE_PARM(talk, "i");
7307 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7308 +MODULE_PARM(ntalk, "i");
7309 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7310 +MODULE_PARM(ntalk2, "i");
7311 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7312 +#endif
7313 +
7314 +DECLARE_LOCK(ip_talk_lock);
7315 +struct module *ip_conntrack_talk = THIS_MODULE;
7316 +
7317 +#if 0
7318 +#define DEBUGP printk
7319 +#else
7320 +#define DEBUGP(format, args...)
7321 +#endif
7322 +
7323 +static int talk_expect(struct ip_conntrack *ct);
7324 +static int ntalk_expect(struct ip_conntrack *ct);
7325 +
7326 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
7327 +
7328 +static int talk_help_response(const struct iphdr *iph, size_t len,
7329 +                             struct ip_conntrack *ct,
7330 +                             enum ip_conntrack_info ctinfo,
7331 +                             int talk_port,
7332 +                             u_char mode,
7333 +                             u_char type,
7334 +                             u_char answer,
7335 +                             struct talk_addr *addr)
7336 +{
7337 +       int dir = CTINFO2DIR(ctinfo);
7338 +       struct ip_conntrack_expect expect, *exp = &expect;
7339 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
7340 +
7341 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
7342 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7343 +               type, answer);
7344 +
7345 +       if (!(answer == SUCCESS && type == mode))
7346 +               return NF_ACCEPT;
7347 +       
7348 +       memset(&expect, 0, sizeof(expect));
7349 +       
7350 +       if (type == ANNOUNCE) {
7351 +
7352 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
7353 +
7354 +               /* update the talk info */
7355 +               LOCK_BH(&ip_talk_lock);
7356 +               exp_talk_info->port = htons(talk_port);
7357 +
7358 +               /* expect callee client -> caller server message */
7359 +               exp->tuple = ((struct ip_conntrack_tuple)
7360 +                       { { ct->tuplehash[dir].tuple.src.ip,
7361 +                           { 0 } },
7362 +                         { ct->tuplehash[dir].tuple.dst.ip,
7363 +                           { .tcp = { htons(talk_port) } },
7364 +                           IPPROTO_UDP }});
7365 +               exp->mask = ((struct ip_conntrack_tuple)
7366 +                       { { 0xFFFFFFFF, { 0 } },
7367 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
7368 +               
7369 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
7370 +
7371 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
7372 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
7373 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
7374 +
7375 +               /* Ignore failure; should only happen with NAT */
7376 +               ip_conntrack_expect_related(ct, &expect);
7377 +               UNLOCK_BH(&ip_talk_lock);
7378 +       }
7379 +       if (type == LOOK_UP) {
7380 +
7381 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
7382 +
7383 +               /* update the talk info */
7384 +               LOCK_BH(&ip_talk_lock);
7385 +               exp_talk_info->port = addr->ta_port;
7386 +
7387 +               /* expect callee client -> caller client connection */
7388 +               exp->tuple = ((struct ip_conntrack_tuple)
7389 +                       { { ct->tuplehash[!dir].tuple.src.ip,
7390 +                           { 0 } },
7391 +                         { addr->ta_addr,
7392 +                           { addr->ta_port },
7393 +                           IPPROTO_TCP }});
7394 +               exp->mask = ((struct ip_conntrack_tuple)
7395 +                       { { 0xFFFFFFFF, { 0 } },
7396 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
7397 +               
7398 +               exp->expectfn = NULL;
7399 +               
7400 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
7401 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
7402 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
7403 +
7404 +               /* Ignore failure; should only happen with NAT */
7405 +               ip_conntrack_expect_related(ct, &expect);
7406 +               UNLOCK_BH(&ip_talk_lock);
7407 +       }
7408 +                   
7409 +       return NF_ACCEPT;
7410 +}
7411 +
7412 +/* FIXME: This should be in userspace.  Later. */
7413 +static int talk_help(const struct iphdr *iph, size_t len,
7414 +                    struct ip_conntrack *ct,
7415 +                    enum ip_conntrack_info ctinfo,
7416 +                    int talk_port,
7417 +                    u_char mode)
7418 +{
7419 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7420 +       const char *data = (const char *)udph + sizeof(struct udphdr);
7421 +       int dir = CTINFO2DIR(ctinfo);
7422 +       size_t udplen;
7423 +
7424 +       DEBUGP("ip_ct_talk_help: help entered\n");
7425 +
7426 +       /* Until there's been traffic both ways, don't look in packets. */
7427 +       if (ctinfo != IP_CT_ESTABLISHED
7428 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
7429 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
7430 +               return NF_ACCEPT;
7431 +       }
7432 +
7433 +       /* Not whole UDP header? */
7434 +       udplen = len - iph->ihl * 4;
7435 +       if (udplen < sizeof(struct udphdr)) {
7436 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
7437 +               return NF_ACCEPT;
7438 +       }
7439 +
7440 +       /* Checksum invalid?  Ignore. */
7441 +       /* FIXME: Source route IP option packets --RR */
7442 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7443 +                             csum_partial((char *)udph, udplen, 0))) {
7444 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
7445 +                      udph, udplen, NIPQUAD(iph->saddr),
7446 +                      NIPQUAD(iph->daddr));
7447 +               return NF_ACCEPT;
7448 +       }
7449 +       
7450 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7451 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
7452 +
7453 +       if (dir == IP_CT_DIR_ORIGINAL)
7454 +               return NF_ACCEPT;
7455 +               
7456 +       if (talk_port == TALK_PORT
7457 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7458 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7459 +                                         ((struct talk_response *)data)->type, 
7460 +                                         ((struct talk_response *)data)->answer,
7461 +                                         &(((struct talk_response *)data)->addr));
7462 +       else if (talk_port == NTALK_PORT
7463 +                 && ntalk
7464 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
7465 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
7466 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7467 +                                         ((struct ntalk_response *)data)->type, 
7468 +                                         ((struct ntalk_response *)data)->answer,
7469 +                                         &(((struct ntalk_response *)data)->addr));
7470 +       else if (talk_port == NTALK_PORT
7471 +                && ntalk2
7472 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
7473 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
7474 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
7475 +                                         ((struct ntalk2_response *)data)->type, 
7476 +                                         ((struct ntalk2_response *)data)->answer,
7477 +                                         &(((struct ntalk2_response *)data)->addr));
7478 +       else {
7479 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
7480 +                      (unsigned)udplen - sizeof(struct udphdr), 
7481 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
7482 +               return NF_ACCEPT;
7483 +       }
7484 +}
7485 +
7486 +static int lookup_help(const struct iphdr *iph, size_t len,
7487 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7488 +{
7489 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
7490 +}
7491 +
7492 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
7493 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7494 +{
7495 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
7496 +}
7497 +
7498 +static struct ip_conntrack_helper lookup_helpers[2] = 
7499 +       { { { NULL, NULL },
7500 +           "talk",                                     /* name */
7501 +           0,                                          /* flags */
7502 +           NULL,                                       /* module */
7503 +           1,                                          /* max_expected */
7504 +           240,                                        /* timeout */
7505 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
7506 +             { 0, { 0 }, IPPROTO_UDP } },
7507 +           { { 0, { 0xFFFF } },                        /* mask */
7508 +             { 0, { 0 }, 0xFFFF } },
7509 +           lookup_help },                              /* helper */
7510 +          { { NULL, NULL },
7511 +            "ntalk",                                   /* name */
7512 +           0,                                          /* flags */
7513 +           NULL,                                       /* module */
7514 +           1,                                          /* max_expected */
7515 +           240,                                        /* timeout */
7516 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
7517 +             { 0, { 0 }, IPPROTO_UDP } },
7518 +           { { 0, { 0xFFFF } },                        /* mask */
7519 +             { 0, { 0 }, 0xFFFF } },
7520 +           lookup_nhelp }                              /* helper */
7521 +        };
7522 +
7523 +static int talk_expect(struct ip_conntrack *ct)
7524 +{
7525 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
7526 +       WRITE_LOCK(&ip_conntrack_lock);
7527 +       ct->helper = &lookup_helpers[0];
7528 +       WRITE_UNLOCK(&ip_conntrack_lock);
7529 +        
7530 +       return NF_ACCEPT;       /* unused */
7531 +}
7532 +
7533 +static int ntalk_expect(struct ip_conntrack *ct)
7534 +{
7535 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
7536 +       WRITE_LOCK(&ip_conntrack_lock);
7537 +       ct->helper = &lookup_helpers[1];
7538 +       WRITE_UNLOCK(&ip_conntrack_lock);
7539 +        
7540 +       return NF_ACCEPT;       /* unused */
7541 +}
7542 +
7543 +static int help(const struct iphdr *iph, size_t len,
7544 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7545 +{
7546 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
7547 +}
7548 +
7549 +static int nhelp(const struct iphdr *iph, size_t len,
7550 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7551 +{
7552 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
7553 +}
7554 +
7555 +static struct ip_conntrack_helper talk_helpers[2] = 
7556 +       { { { NULL, NULL },
7557 +           "talk",                                     /* name */
7558 +           0,                                          /* flags */
7559 +           THIS_MODULE,                                /* module */
7560 +           1,                                          /* max_expected */
7561 +           240,                                        /* timeout */
7562 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
7563 +             { 0, { 0 }, IPPROTO_UDP } },
7564 +           { { 0, { 0xFFFF } },                        /* mask */
7565 +             { 0, { 0 }, 0xFFFF } },
7566 +           help },                                     /* helper */
7567 +          { { NULL, NULL },
7568 +           "ntalk",                                    /* name */
7569 +           0,                                          /* flags */
7570 +           THIS_MODULE,                                /* module */
7571 +           1,                                          /* max_expected */
7572 +           240,                                        /* timeout */
7573 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
7574 +             { 0, { 0 }, IPPROTO_UDP } },
7575 +           { { 0, { 0xFFFF } },                        /* mask */
7576 +             { 0, { 0 }, 0xFFFF } },
7577 +           nhelp }                                     /* helper */
7578 +       };
7579 +
7580 +static int __init init(void)
7581 +{
7582 +       if (talk > 0)
7583 +               ip_conntrack_helper_register(&talk_helpers[0]);
7584 +       if (ntalk > 0 || ntalk2 > 0)
7585 +               ip_conntrack_helper_register(&talk_helpers[1]);
7586 +               
7587 +       return 0;
7588 +}
7589 +
7590 +static void __exit fini(void)
7591 +{
7592 +       if (talk > 0)
7593 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
7594 +       if (ntalk > 0 || ntalk2 > 0)
7595 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
7596 +}
7597 +
7598 +EXPORT_SYMBOL(ip_talk_lock);
7599 +
7600 +module_init(init);
7601 +module_exit(fini);
7602 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
7603 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_conntrack_tftp.c       2003-11-26 21:43:31.000000000 +0100
7604 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_conntrack_tftp.c   2003-12-11 10:23:13.893825792 +0100
7605 @@ -97,8 +97,6 @@
7606  
7607         for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7608                 /* Create helper structure */
7609 -               memset(&tftp[i], 0, sizeof(struct ip_conntrack_helper));
7610 -
7611                 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
7612                 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
7613                 tftp[i].mask.dst.protonum = 0xFFFF;
7614 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
7615 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_amanda.c   2003-11-26 21:43:24.000000000 +0100
7616 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_amanda.c       2003-12-11 10:23:13.893825792 +0100
7617 @@ -195,8 +195,6 @@
7618         struct ip_nat_helper *hlpr;
7619  
7620         hlpr = &ip_nat_amanda_helper;
7621 -       memset(hlpr, 0, sizeof(struct ip_nat_helper));
7622 -
7623         hlpr->tuple.dst.protonum = IPPROTO_UDP;
7624         hlpr->tuple.src.u.udp.port = htons(10080);
7625         hlpr->mask.src.u.udp.port = 0xFFFF;
7626 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
7627 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_core.c     2003-11-26 21:43:07.000000000 +0100
7628 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_core.c 2003-12-11 10:23:59.482895200 +0100
7629 @@ -90,9 +90,16 @@
7630         WRITE_UNLOCK(&ip_nat_lock);
7631  }
7632  
7633 -/* We do checksum mangling, so if they were wrong before they're still
7634 - * wrong.  Also works for incomplete packets (eg. ICMP dest
7635 - * unreachables.) */
7636 +/**
7637 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
7638 + * @oldvalinv: bit-inverted old value of 32bit word
7639 + * @newval: new value of 32bit word
7640 + * @oldcheck: old checksum value
7641 + *
7642 + * This function implements incremental checksum mangling, so if a checksum
7643 + * was wrong it will still be wrong after mangling.  Also works for incomplete
7644 + * packets (eg. ICMP dest unreachables).  Return value is the new checksum.
7645 + */
7646  u_int16_t
7647  ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
7648  {
7649 @@ -118,7 +125,14 @@
7650         return i;
7651  }
7652  
7653 -/* Is this tuple already taken? (not by us) */
7654 +/**
7655 + * ip_nat_used_tuple - Is this tuple already in use?
7656 + * @tuple: tuple to be used for this check
7657 + * @ignored_conntrack: conntrack excluded from this check
7658 + *
7659 + * This function checks for the reply (inverted) tuple in the conntrack
7660 + * hash.  This is necessarry with NAT, since there is no fixed mapping.
7661 + */
7662  int
7663  ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
7664                   const struct ip_conntrack *ignored_conntrack)
7665 @@ -432,7 +446,7 @@
7666         *tuple = *orig_tuple;
7667         while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
7668                != NULL) {
7669 -               DEBUGP("Found best for "); DUMP_TUPLE(tuple);
7670 +               DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple);
7671                 /* 3) The per-protocol part of the manip is made to
7672                    map into the range to make a unique tuple. */
7673  
7674 @@ -509,6 +523,19 @@
7675  #endif
7676  };
7677  
7678 +/**
7679 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
7680 + * @conntrack: conntrack on which we operate
7681 + * @mr: address/port range which is valid for this NAT mapping
7682 + * @hooknum: hook at which this NAT mapping applies
7683 + *
7684 + * This function is called by NAT targets (SNAT,DNAT,...) and by
7685 + * the NAT application helper modules.  It is called for the NEW packet
7686 + * of a connection in order to specify which NAT mappings shall apply to
7687 + * this connection at a given hook.
7688 + *
7689 + * Note: The reply mappings are created automagically by this function. 
7690 + */
7691  unsigned int
7692  ip_nat_setup_info(struct ip_conntrack *conntrack,
7693                   const struct ip_nat_multi_range *mr,
7694 @@ -573,9 +600,9 @@
7695                        HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
7696                        conntrack);
7697                 DEBUGP("Original: ");
7698 -               DUMP_TUPLE(&orig_tp);
7699 +               DUMP_TUPLE_RAW(&orig_tp);
7700                 DEBUGP("New: ");
7701 -               DUMP_TUPLE(&new_tuple);
7702 +               DUMP_TUPLE_RAW(&new_tuple);
7703  #endif
7704  
7705                 /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
7706 @@ -810,7 +837,7 @@
7707  
7708                 /* Have to grab read lock before sibling_list traversal */
7709                 READ_LOCK(&ip_conntrack_lock);
7710 -               list_for_each(cur_item, &ct->sibling_list) { 
7711 +               list_for_each_prev(cur_item, &ct->sibling_list) { 
7712                         exp = list_entry(cur_item, struct ip_conntrack_expect, 
7713                                          expected_list);
7714                                          
7715 @@ -1010,7 +1037,11 @@
7716         /* FIXME: Man, this is a hack.  <SIGH> */
7717         IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
7718         ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
7719 -
7720 +       
7721 +       /* Initialize fake conntrack so that NAT will skip it */
7722 +       ip_conntrack_untracked.nat.info.initialized |= 
7723 +               (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
7724
7725         return 0;
7726  }
7727  
7728 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
7729 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_cuseeme.c  1970-01-01 01:00:00.000000000 +0100
7730 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_cuseeme.c      2003-12-11 10:23:48.970493328 +0100
7731 @@ -0,0 +1,289 @@
7732 +/* CuSeeMe extension for UDP NAT alteration.
7733 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7734 + * based on ip_masq_cuseeme.c in 2.2 kernels
7735 + *
7736 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
7737 + *
7738 + *      This program is free software; you can redistribute it and/or
7739 + *      modify it under the terms of the GNU General Public License
7740 + *      as published by the Free Software Foundation; either version
7741 + *      2 of the License, or (at your option) any later version.
7742 + *
7743 + *      Module load syntax:
7744 + *      insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
7745 + *
7746 + *      Please give the ports of the CuSeeMe traffic you want to track.
7747 + *      If you don't specify ports, the default will be UDP port 7648.
7748 + *
7749 + *      CuSeeMe Protocol Documentation:
7750 + *      http://cu-seeme.net/squeek/tech/contents.html
7751 + *
7752 + */
7753 +
7754 +#include <linux/module.h>
7755 +#include <linux/netfilter_ipv4.h>
7756 +#include <linux/ip.h>
7757 +#include <linux/udp.h>
7758 +
7759 +#include <linux/netfilter.h>
7760 +#include <linux/netfilter_ipv4/ip_tables.h>
7761 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7762 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
7763 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7764 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7765 +
7766 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7767 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
7768 +MODULE_LICENSE("GPL");
7769 +
7770 +#define MAX_PORTS 8
7771 +
7772 +static int ports[MAX_PORTS];
7773 +static int ports_c = 0;
7774 +#ifdef MODULE_PARM
7775 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7776 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
7777 +#endif
7778 +
7779 +#if 0
7780 +#define DEBUGP printk
7781 +#else
7782 +#define DEBUGP(format, args...)
7783 +#endif
7784 +
7785 +/* process packet from client->reflector, possibly manipulate client IP in payload */
7786 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
7787 +                             struct ip_nat_info *info,
7788 +                             enum ip_conntrack_info ctinfo,
7789 +                             struct sk_buff **pskb,
7790 +                             char *data,
7791 +                             unsigned int datalen)
7792 +{
7793 +       char new_port_ip[6];
7794 +       struct cu_header *cu_head=(struct cu_header *)data;
7795 +       
7796 +       DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n", 
7797 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7798 +               
7799 +       /* At least check that the data at offset 10 is the client's port and IP address */
7800 +       if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
7801 +           (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
7802 +               DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n", 
7803 +                      NIPQUAD(cu_head->addr),
7804 +                      ntohs(cu_head->port),
7805 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7806 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
7807 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7808 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7809 +               /* at offset 10, replace 6 bytes containing port + IP address */
7810 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7811 +                                        10, 6, (char *)(new_port_ip), 6);
7812 +       } else 
7813 +               DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7814 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7815 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
7816 +                      NIPQUAD(cu_head->addr),
7817 +                      ntohs(cu_head->port));
7818 +}
7819 +
7820 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
7821 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
7822 +                             struct ip_nat_info *info,
7823 +                             enum ip_conntrack_info ctinfo,
7824 +                             struct sk_buff **pskb,
7825 +                             char *data,
7826 +                             unsigned int datalen)
7827 +{
7828 +       char new_port_ip[6];
7829 +       struct cu_header *cu_head = (struct cu_header *)data;
7830 +       struct oc_header *oc_head = (struct oc_header *)data; 
7831 +       struct client_info *ci; 
7832 +       int i, off;
7833 +
7834 +       
7835 +       DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n", 
7836 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
7837 +               
7838 +       /* Check if we're really dealing with the client's port + IP address before rewriting */
7839 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
7840 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
7841 +               DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
7842 +                      NIPQUAD(cu_head->dest_addr),
7843 +                      ntohs(cu_head->dest_port),
7844 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7845 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
7846 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
7847 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7848 +               /* at offset 2, replace 6 bytes containing port + IP address */
7849 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7850 +                                        2, 6, (char *)(new_port_ip), 6);
7851 +       } else 
7852 +               DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7853 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
7854 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
7855 +                      NIPQUAD(cu_head->dest_addr),
7856 +                      ntohs(cu_head->dest_port));
7857 +       
7858 +       /* Check if we're really dealing with the server's port + IP address before rewriting. 
7859 +          In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
7860 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
7861 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
7862 +               DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
7863 +                      NIPQUAD(cu_head->addr),
7864 +                      ntohs(cu_head->port),
7865 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
7866 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
7867 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
7868 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7869 +               /* at offset 10, replace 6 bytes containing port + IP address */
7870 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7871 +                                        10, 6, (char *)(new_port_ip), 6);
7872 +       } else 
7873 +               /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
7874 +                  is not that important so we're not logging this unless we're debugging */
7875 +               DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
7876 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
7877 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
7878 +                      NIPQUAD(cu_head->addr),
7879 +                      ntohs(cu_head->port));
7880 +       
7881 +       /* Spin through client_info structs until we find our own */
7882 +       if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
7883 +               DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
7884 +               for(i=0, off=sizeof(struct oc_header);
7885 +                   (i < oc_head->client_count && 
7886 +                   off+sizeof(struct client_info) <= datalen); 
7887 +                   i++) {
7888 +                       ci=(struct client_info *)(data+off);
7889 +                       DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n", 
7890 +                              NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
7891 +                              (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7892 +                       if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
7893 +                               /* mangle this IP address */
7894 +                               DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
7895 +                                      NIPQUAD(ci->address), 
7896 +                                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
7897 +                                      (unsigned int)((void *)&(ci->address) - (void *)cu_head));
7898 +                               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
7899 +                                                        (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4, 
7900 +                                                        (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
7901 +                               break;
7902 +                       } else 
7903 +                               off+=sizeof(struct client_info);
7904 +               }
7905 +       } else
7906 +               DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n", 
7907 +                      ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
7908 +}
7909 +
7910 +static unsigned int 
7911 +cuseeme_nat_help(struct ip_conntrack *ct,
7912 +                 struct ip_conntrack_expect *exp,
7913 +                 struct ip_nat_info *info,
7914 +                 enum ip_conntrack_info ctinfo,
7915 +                 unsigned int hooknum,
7916 +                 struct sk_buff **pskb)
7917 +{
7918 +       struct iphdr *iph = (*pskb)->nh.iph;
7919 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7920 +       int dir = CTINFO2DIR(ctinfo);
7921 +       unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
7922 +       char *data = (char *) &udph[1];
7923 +       
7924 +       DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
7925 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7926 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7927 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7928 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7929 +             );
7930 +       
7931 +       /* Only mangle things once: original direction in POST_ROUTING
7932 +          and reply direction on PRE_ROUTING. */
7933 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7934 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7935 +               DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
7936 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7937 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7938 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7939 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7940 +               return NF_ACCEPT;
7941 +       }
7942 +       
7943 +       if(datalen < sizeof(struct cu_header)) {
7944 +               /* packet too small */
7945 +               if (net_ratelimit())
7946 +                       printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n", 
7947 +                              datalen, sizeof(struct cu_header));
7948 +               return NF_ACCEPT;
7949 +       }
7950 +
7951 +
7952 +       /* In the debugging output, "outgoing" is from client to server, and
7953 +          "incoming" is from server to client */
7954 +       if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) 
7955 +               cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
7956 +       else 
7957 +               cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
7958 +
7959 +       return NF_ACCEPT;
7960 +}
7961 +
7962 +static struct ip_nat_helper cuseeme[MAX_PORTS];
7963 +static char cuseeme_names[MAX_PORTS][14];  /* cuseeme-65535 */
7964 +
7965 +static void fini(void)
7966 +{
7967 +       int i;
7968 +       
7969 +       for (i = 0 ; i < ports_c; i++) {
7970 +               DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
7971 +                      ip_nat_helper_unregister(&cuseeme[i]);
7972 +       }
7973 +}
7974 +
7975 +static int __init init(void)
7976 +{
7977 +       int i, ret = 0;
7978 +       char *tmpname;
7979 +
7980 +       if (!ports[0])
7981 +               ports[0] = CUSEEME_PORT;
7982 +               
7983 +       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7984 +               memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
7985 +
7986 +               cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
7987 +               cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
7988 +               cuseeme[i].mask.dst.protonum = 0xFFFF;
7989 +               cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
7990 +               cuseeme[i].help = cuseeme_nat_help;
7991 +               cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE + 
7992 +                                  IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
7993 +                                                             is stricly needed... */
7994 +               cuseeme[i].me = THIS_MODULE;
7995 +               cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
7996 +                       
7997 +               tmpname = &cuseeme_names[i][0];
7998 +               if (ports[i] == CUSEEME_PORT)
7999 +                       sprintf(tmpname, "cuseeme");
8000 +               else
8001 +                       sprintf(tmpname, "cuseeme-%d", ports[i]);
8002 +               cuseeme[i].name = tmpname;
8003 +                       
8004 +               DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
8005 +                      ports[i], cuseeme[i].name);
8006 +               ret = ip_nat_helper_register(&cuseeme[i]);
8007 +                       
8008 +               if (ret) {
8009 +                       printk("ip_nat_cuseeme: unable to register helper for port %d\n",
8010 +                              ports[i]);
8011 +                       fini();
8012 +                       return ret;
8013 +               }
8014 +               ports_c++;
8015 +       }
8016 +       return ret;
8017 +}
8018 +       
8019 +module_init(init);
8020 +module_exit(fini);
8021 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
8022 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_h323.c     1970-01-01 01:00:00.000000000 +0100
8023 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_h323.c 2003-12-11 10:23:51.336133696 +0100
8024 @@ -0,0 +1,419 @@
8025 +/* 
8026 + * H.323 'brute force' extension for NAT alteration. 
8027 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8028 + *
8029 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
8030 + * (http://www.coritel.it/projects/sofia/nat.html)
8031 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
8032 + * the unregistered helpers to the conntrack entries.
8033 + */
8034 +
8035 +
8036 +#include <linux/module.h>
8037 +#include <linux/netfilter.h>
8038 +#include <linux/ip.h>
8039 +#include <net/checksum.h>
8040 +#include <net/tcp.h>
8041 +
8042 +#include <linux/netfilter_ipv4/lockhelp.h>
8043 +#include <linux/netfilter_ipv4/ip_nat.h>
8044 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8045 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8046 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
8047 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8048 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
8049 +
8050 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8051 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
8052 +MODULE_LICENSE("GPL");
8053 +
8054 +DECLARE_LOCK_EXTERN(ip_h323_lock);
8055 +struct module *ip_nat_h323 = THIS_MODULE;
8056 +
8057 +#if 0
8058 +#define DEBUGP printk
8059 +#else
8060 +#define DEBUGP(format, args...)
8061 +#endif
8062 +
8063 +/* FIXME: Time out? --RR */
8064 +
8065 +static unsigned int 
8066 +h225_nat_expected(struct sk_buff **pskb,
8067 +                 unsigned int hooknum,
8068 +                 struct ip_conntrack *ct,
8069 +                 struct ip_nat_info *info);
8070 +
8071 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8072 +                                 struct ip_conntrack_expect *exp,
8073 +                                 struct ip_nat_info *info,
8074 +                                 enum ip_conntrack_info ctinfo,
8075 +                                 unsigned int hooknum,
8076 +                                 struct sk_buff **pskb);
8077 +                 
8078 +static struct ip_nat_helper h245 = 
8079 +       { { NULL, NULL },
8080 +          "H.245",                             /* name */
8081 +         0,                                    /* flags */
8082 +         NULL,                                 /* module */
8083 +         { { 0, { 0 } },                       /* tuple */
8084 +           { 0, { 0 }, IPPROTO_TCP } },
8085 +         { { 0, { 0xFFFF } },                  /* mask */
8086 +           { 0, { 0 }, 0xFFFF } },
8087 +         h225_nat_help,                        /* helper */
8088 +         h225_nat_expected                     /* expectfn */
8089 +       };
8090 +
8091 +static unsigned int
8092 +h225_nat_expected(struct sk_buff **pskb,
8093 +                 unsigned int hooknum,
8094 +                 struct ip_conntrack *ct,
8095 +                 struct ip_nat_info *info)
8096 +{
8097 +       struct ip_nat_multi_range mr;
8098 +       u_int32_t newdstip, newsrcip, newip;
8099 +       u_int16_t port;
8100 +       struct ip_ct_h225_expect *exp_info;
8101 +       struct ip_ct_h225_master *master_info;
8102 +       struct ip_conntrack *master = master_ct(ct);
8103 +       unsigned int is_h225, ret;
8104 +       
8105 +       IP_NF_ASSERT(info);
8106 +       IP_NF_ASSERT(master);
8107 +
8108 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8109 +
8110 +       DEBUGP("h225_nat_expected: We have a connection!\n");
8111 +       master_info = &ct->master->expectant->help.ct_h225_info;
8112 +       exp_info = &ct->master->help.exp_h225_info;
8113 +
8114 +       LOCK_BH(&ip_h323_lock);
8115 +
8116 +       DEBUGP("master: ");
8117 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8118 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
8119 +       DEBUGP("conntrack: ");
8120 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8121 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
8122 +               /* Make connection go to the client. */
8123 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8124 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8125 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
8126 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8127 +       } else {
8128 +               /* Make the connection go to the server */
8129 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8130 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8131 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
8132 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8133 +       }
8134 +       port = exp_info->port;
8135 +       is_h225 = master_info->is_h225 == H225_PORT;
8136 +       UNLOCK_BH(&ip_h323_lock);
8137 +       
8138 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8139 +               newip = newsrcip;
8140 +       else
8141 +               newip = newdstip;
8142 +
8143 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8144 +
8145 +       mr.rangesize = 1;
8146 +       /* We don't want to manip the per-protocol, just the IPs... */
8147 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8148 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8149 +
8150 +       /* ... unless we're doing a MANIP_DST, in which case, make
8151 +          sure we map to the correct port */
8152 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8153 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8154 +               mr.range[0].min = mr.range[0].max
8155 +                       = ((union ip_conntrack_manip_proto)
8156 +                               { .tcp = { port } });
8157 +       }
8158 +
8159 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
8160 +       
8161 +       if (is_h225) {
8162 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
8163 +               /* NAT expectfn called with ip_nat_lock write-locked */
8164 +               info->helper = &h245;
8165 +       }
8166 +       return ret;
8167 +}
8168 +
8169 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
8170 +                                    struct sk_buff **pskb,
8171 +                                    enum ip_conntrack_info ctinfo)
8172 +{
8173 +       struct iphdr *iph = (*pskb)->nh.iph;
8174 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8175 +       char *data = (char *) tcph + tcph->doff * 4;
8176 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8177 +       u_int32_t datalen = tcplen - tcph->doff*4;
8178 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
8179 +       u_int32_t newip;
8180 +       u_int16_t port;
8181 +       int i;
8182 +
8183 +       MUST_BE_LOCKED(&ip_h323_lock);
8184 +
8185 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
8186 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8187 +                       ? "yes" : "no",
8188 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8189 +                       ? "yes" : "no");
8190 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
8191 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
8192 +               return 1;
8193 +
8194 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
8195 +               info->offset[IP_CT_DIR_ORIGINAL], 
8196 +               info->offset[IP_CT_DIR_REPLY],
8197 +               tcplen);
8198 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8199 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8200 +
8201 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
8202 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
8203 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
8204 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
8205 +               if (!between(info->seq[i], ntohl(tcph->seq), 
8206 +                            ntohl(tcph->seq) + datalen))
8207 +                       continue;
8208 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
8209 +                            ntohl(tcph->seq) + datalen)) {
8210 +                       /* Partial retransmisison. It's a cracker being funky. */
8211 +                       if (net_ratelimit()) {
8212 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8213 +                                    info->seq[i],
8214 +                                    ntohl(tcph->seq),
8215 +                                    ntohl(tcph->seq) + datalen);
8216 +                       }
8217 +                       return 0;
8218 +               }
8219 +
8220 +               /* Change address inside packet to match way we're mapping
8221 +                  this connection. */
8222 +               if (i == IP_CT_DIR_ORIGINAL) {
8223 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
8224 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
8225 +               } else {
8226 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
8227 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
8228 +               }
8229 +
8230 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
8231 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
8232 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
8233 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8234 +
8235 +               /* Modify the packet */
8236 +               *(u_int32_t *)(data + info->offset[i]) = newip;
8237 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
8238 +       
8239 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
8240 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
8241 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
8242 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
8243 +       }
8244 +
8245 +       /* fix checksum information */
8246 +
8247 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8248 +                                    datalen, 0);
8249 +
8250 +       tcph->check = 0;
8251 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8252 +                                  csum_partial((char *)tcph, tcph->doff*4,
8253 +                                          (*pskb)->csum));
8254 +       ip_send_check(iph);
8255 +
8256 +       return 1;
8257 +}
8258 +
8259 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
8260 +                          struct ip_conntrack *ct,
8261 +                          struct sk_buff **pskb,
8262 +                          enum ip_conntrack_info ctinfo,
8263 +                          struct ip_conntrack_expect *expect)
8264 +{
8265 +       u_int32_t newip;
8266 +       u_int16_t port;
8267 +       struct ip_conntrack_tuple newtuple;
8268 +       struct iphdr *iph = (*pskb)->nh.iph;
8269 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
8270 +       char *data = (char *) tcph + tcph->doff * 4;
8271 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
8272 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
8273 +       int is_h225;
8274 +
8275 +       MUST_BE_LOCKED(&ip_h323_lock);
8276 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
8277 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
8278 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
8279 +
8280 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
8281 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
8282 +               /* Partial retransmisison. It's a cracker being funky. */
8283 +               if (net_ratelimit()) {
8284 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
8285 +                            expect->seq,
8286 +                            ntohl(tcph->seq),
8287 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
8288 +               }
8289 +               return 0;
8290 +       }
8291 +
8292 +       /* Change address inside packet to match way we're mapping
8293 +          this connection. */
8294 +       if (info->dir == IP_CT_DIR_REPLY) {
8295 +               /* Must be where client thinks server is */
8296 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8297 +               /* Expect something from client->server */
8298 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8299 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8300 +       } else {
8301 +               /* Must be where server thinks client is */
8302 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8303 +               /* Expect something from server->client */
8304 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8305 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8306 +       }
8307 +
8308 +       is_h225 = (master_info->is_h225 == H225_PORT);
8309 +
8310 +       if (is_h225) {
8311 +               newtuple.dst.protonum = IPPROTO_TCP;
8312 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
8313 +       } else {
8314 +               newtuple.dst.protonum = IPPROTO_UDP;
8315 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
8316 +       }
8317 +       
8318 +       /* Try to get same port: if not, try to change it. */
8319 +       for (port = ntohs(info->port); port != 0; port++) {
8320 +               if (is_h225)
8321 +                       newtuple.dst.u.tcp.port = htons(port);
8322 +               else
8323 +                       newtuple.dst.u.udp.port = htons(port);
8324 +
8325 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
8326 +                       break;
8327 +       }
8328 +       if (port == 0) {
8329 +               DEBUGP("h323_data_fixup: no free port found!\n");
8330 +               return 0;
8331 +       }
8332 +
8333 +       port = htons(port);
8334 +
8335 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
8336 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
8337 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
8338 +
8339 +       /* Modify the packet */
8340 +       *(u_int32_t *)(data + info->offset) = newip;
8341 +       *(u_int16_t *)(data + info->offset + 4) = port;
8342 +       
8343 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
8344 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
8345 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
8346 +
8347 +       /* fix checksum information  */
8348 +       /* FIXME: usually repeated multiple times in the case of H.245! */
8349 +
8350 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
8351 +                                    tcplen - tcph->doff*4, 0);
8352 +
8353 +       tcph->check = 0;
8354 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8355 +                                  csum_partial((char *)tcph, tcph->doff*4,
8356 +                                          (*pskb)->csum));
8357 +       ip_send_check(iph);
8358 +
8359 +       return 1;
8360 +}
8361 +
8362 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
8363 +                                 struct ip_conntrack_expect *exp,
8364 +                                 struct ip_nat_info *info,
8365 +                                 enum ip_conntrack_info ctinfo,
8366 +                                 unsigned int hooknum,
8367 +                                 struct sk_buff **pskb)
8368 +{
8369 +       int dir;
8370 +       struct ip_ct_h225_expect *exp_info;
8371 +       
8372 +       /* Only mangle things once: original direction in POST_ROUTING
8373 +          and reply direction on PRE_ROUTING. */
8374 +       dir = CTINFO2DIR(ctinfo);
8375 +       DEBUGP("nat_h323: dir %s at hook %s\n",
8376 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8377 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8378 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8379 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8380 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8381 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8382 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
8383 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8384 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8385 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8386 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8387 +               return NF_ACCEPT;
8388 +       }
8389 +
8390 +       if (!exp) {
8391 +               LOCK_BH(&ip_h323_lock);
8392 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
8393 +                       UNLOCK_BH(&ip_h323_lock);
8394 +                       return NF_DROP;
8395 +               }
8396 +               UNLOCK_BH(&ip_h323_lock);
8397 +               return NF_ACCEPT;
8398 +       }
8399 +               
8400 +       exp_info = &exp->help.exp_h225_info;
8401 +
8402 +       LOCK_BH(&ip_h323_lock);
8403 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
8404 +               UNLOCK_BH(&ip_h323_lock);
8405 +               return NF_DROP;
8406 +       }
8407 +       UNLOCK_BH(&ip_h323_lock);
8408 +
8409 +       return NF_ACCEPT;
8410 +}
8411 +
8412 +static struct ip_nat_helper h225 = 
8413 +       { { NULL, NULL },
8414 +         "H.225",                                      /* name */
8415 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
8416 +         THIS_MODULE,                                  /* module */
8417 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
8418 +           { 0, { 0 }, IPPROTO_TCP } },
8419 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
8420 +           { 0, { 0 }, 0xFFFF } },
8421 +         h225_nat_help,                                /* helper */
8422 +         h225_nat_expected                             /* expectfn */
8423 +       };
8424 +
8425 +static int __init init(void)
8426 +{
8427 +       int ret;
8428 +       
8429 +       ret = ip_nat_helper_register(&h225);
8430 +
8431 +       if (ret != 0)
8432 +               printk("ip_nat_h323: cannot initialize the module!\n");
8433 +
8434 +       return ret;
8435 +}
8436 +
8437 +static void __exit fini(void)
8438 +{
8439 +       ip_nat_helper_unregister(&h225);
8440 +}
8441 +
8442 +module_init(init);
8443 +module_exit(fini);
8444 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
8445 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_helper.c   2003-11-26 21:43:08.000000000 +0100
8446 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_helper.c       2003-12-11 10:23:57.173246320 +0100
8447 @@ -147,9 +147,19 @@
8448         return 1;
8449  }
8450  
8451 -/* Generic function for mangling variable-length address changes inside
8452 - * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
8453 - * command in FTP).
8454 +/**
8455 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
8456 + * @skb: pointer to skb of packet on which we operate
8457 + * @ct: conntrack of the connection to which this packet belongs
8458 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8459 + * @match_offset: offset in bytes where to-be-manipulated part starts
8460 + * @match_len: lenght of the to-be-manipulated part
8461 + * @rep_buffer: pointer to buffer containing replacement
8462 + * @rep_len: length of replacement
8463 + *
8464 + * Generic function for mangling fixed and variable-length changes inside
8465 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command 
8466 + * in FTP).
8467   *
8468   * Takes care about all the nasty sequence number changes, checksumming,
8469   * skb enlargement, ...
8470 @@ -195,16 +205,27 @@
8471         return 1;
8472  }
8473                         
8474 -/* Generic function for mangling variable-length address changes inside
8475 - * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8476 - * command in the Amanda protocol)
8477 +/**
8478 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
8479 + * @skb: pointer to skb of packet on which we operate
8480 + * @ct: conntrack of the connection to which this packet belongs
8481 + * @ctinfo: conntrack_info of the connection to which this packet belongs
8482 + * @match_offset: offset in bytes where to-be-manipulated part starts
8483 + * @match_len: lenght of the to-be-manipulated part
8484 + * @rep_buffer: pointer to buffer containing replacement
8485 + * @rep_len: length of replacement
8486 + *
8487 + * Generic function for mangling fixed and variable-length changes inside
8488 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
8489 + * commad in the Amanda protocol)
8490   *
8491   * Takes care about all the nasty sequence number changes, checksumming,
8492   * skb enlargement, ...
8493   *
8494 - * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
8495 - *       should be fairly easy to do.
8496 - */
8497 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
8498 + *
8499 + * */
8500 +
8501  int 
8502  ip_nat_mangle_udp_packet(struct sk_buff **pskb,
8503                          struct ip_conntrack *ct,
8504 @@ -402,6 +423,13 @@
8505         return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
8506  }
8507  
8508 +/**
8509 + * ip_nat_helper_register - Register NAT application helper
8510 + * @me: structure describing the helper
8511 + *
8512 + * This function is called by NAT application helpers to register
8513 + * themselves with the NAT core.
8514 + */
8515  int ip_nat_helper_register(struct ip_nat_helper *me)
8516  {
8517         int ret = 0;
8518 @@ -428,6 +456,13 @@
8519         return ret;
8520  }
8521  
8522 +/**
8523 + * ip_nat_helper_unregister - Unregister NAT application helper
8524 + * @me: structure describing the helper
8525 + *
8526 + * This function is called by NAT application helpers to unregister
8527 + * themselves from the NAT core.
8528 + */
8529  void ip_nat_helper_unregister(struct ip_nat_helper *me)
8530  {
8531         WRITE_LOCK(&ip_nat_lock);
8532 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
8533 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_mms.c      1970-01-01 01:00:00.000000000 +0100
8534 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_mms.c  2003-12-11 10:23:55.934434648 +0100
8535 @@ -0,0 +1,350 @@
8536 +/* MMS extension for TCP NAT alteration.
8537 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
8538 + * based on ip_nat_ftp.c and ip_nat_irc.c
8539 + *
8540 + * ip_nat_mms.c v0.3 2002-09-22
8541 + *
8542 + *      This program is free software; you can redistribute it and/or
8543 + *      modify it under the terms of the GNU General Public License
8544 + *      as published by the Free Software Foundation; either version
8545 + *      2 of the License, or (at your option) any later version.
8546 + *
8547 + *      Module load syntax:
8548 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
8549 + *
8550 + *      Please give the ports of all MMS servers You wish to connect to.
8551 + *      If you don't specify ports, the default will be TCP port 1755.
8552 + *
8553 + *      More info on MMS protocol, firewalls and NAT:
8554 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
8555 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
8556 + *
8557 + *      The SDP project people are reverse-engineering MMS:
8558 + *      http://get.to/sdp
8559 + */
8560 +
8561 +/* FIXME: issue with UDP & fragmentation with this URL: 
8562 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
8563 +   may be related to out-of-order first packets:
8564 +   basically the expectation is set up correctly, then the server sends
8565 +   a first UDP packet which is fragmented plus arrives out-of-order.
8566 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
8567 +   an ICMP unreachable back to the server */
8568 +
8569 +#include <linux/module.h>
8570 +#include <linux/netfilter_ipv4.h>
8571 +#include <linux/ip.h>
8572 +#include <linux/tcp.h>
8573 +#include <net/tcp.h>
8574 +#include <linux/netfilter_ipv4/ip_nat.h>
8575 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8576 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8577 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
8578 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8579 +
8580 +#if 0 
8581 +#define DEBUGP printk
8582 +#define DUMP_BYTES(address, counter)                                \
8583 +({                                                                  \
8584 +       int temp_counter;                                           \
8585 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
8586 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
8587 +       };                                                          \
8588 +       DEBUGP("\n");                                               \
8589 +})
8590 +#else
8591 +#define DEBUGP(format, args...)
8592 +#define DUMP_BYTES(address, counter)
8593 +#endif
8594 +
8595 +#define MAX_PORTS 8
8596 +static int ports[MAX_PORTS];
8597 +static int ports_c = 0;
8598 +
8599 +#ifdef MODULE_PARM
8600 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8601 +#endif
8602 +
8603 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
8604 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
8605 +MODULE_LICENSE("GPL");
8606 +
8607 +DECLARE_LOCK_EXTERN(ip_mms_lock);
8608 +
8609 +/* FIXME: Time out? --RR */
8610 +
8611 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
8612 +                          struct ip_conntrack *ct,
8613 +                          struct sk_buff **pskb,
8614 +                          enum ip_conntrack_info ctinfo,
8615 +                          struct ip_conntrack_expect *expect)
8616 +{
8617 +       u_int32_t newip;
8618 +       struct ip_conntrack_tuple t;
8619 +       struct iphdr *iph = (*pskb)->nh.iph;
8620 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8621 +       char *data = (char *)tcph + tcph->doff * 4;
8622 +       int i, j, k, port;
8623 +       u_int16_t mms_proto;
8624 +
8625 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
8626 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
8627 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
8628 +
8629 +       int zero_padding;
8630 +
8631 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
8632 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
8633 +       char proto_string[6];
8634 +       
8635 +       MUST_BE_LOCKED(&ip_mms_lock);
8636 +
8637 +       /* what was the protocol again ? */
8638 +       mms_proto = expect->tuple.dst.protonum;
8639 +       sprintf(proto_string, "%u", mms_proto);
8640 +       
8641 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
8642 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
8643 +              mms_proto == IPPROTO_UDP ? "UDP"
8644 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
8645 +       
8646 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8647 +
8648 +       /* Alter conntrack's expectations. */
8649 +       t = expect->tuple;
8650 +       t.dst.ip = newip;
8651 +       for (port = ct_mms_info->port; port != 0; port++) {
8652 +               t.dst.u.tcp.port = htons(port);
8653 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
8654 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
8655 +                       break;
8656 +               }
8657 +       }
8658 +       
8659 +       if(port == 0)
8660 +               return 0;
8661 +
8662 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
8663 +               NIPQUAD(newip),
8664 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
8665 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
8666 +               port);
8667 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
8668 +       
8669 +       memset(unicode_buffer, 0, sizeof(char)*75);
8670 +
8671 +       for (i=0; i<strlen(buffer); ++i)
8672 +               *(unicode_buffer+i*2)=*(buffer+i);
8673 +       
8674 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
8675 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
8676 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
8677 +       
8678 +       /* add end of packet to it */
8679 +       for (j=0; j<ct_mms_info->padding; ++j) {
8680 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
8681 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
8682 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
8683 +       }
8684 +
8685 +       /* pad with zeroes at the end ? see explanation of weird math below */
8686 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
8687 +       for (k=0; k<zero_padding; ++k)
8688 +               *(unicode_buffer+i*2+j+k)= (char)0;
8689 +       
8690 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
8691 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8692 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8693 +       
8694 +       /* explanation, before I forget what I did:
8695 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
8696 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
8697 +          but note that things may have to be padded with zeroes to align by 8 
8698 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
8699 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
8700 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
8701 +       *mms_messageLength = *mms_chunkLenLV*8;
8702 +       
8703 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
8704 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
8705 +       
8706 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
8707 +                                expect->seq - ntohl(tcph->seq),
8708 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
8709 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
8710 +       DUMP_BYTES(unicode_buffer, 60);
8711 +       
8712 +       return 1;
8713 +}
8714 +
8715 +static unsigned int
8716 +mms_nat_expected(struct sk_buff **pskb,
8717 +                 unsigned int hooknum,
8718 +                 struct ip_conntrack *ct,
8719 +                 struct ip_nat_info *info)
8720 +{
8721 +       struct ip_nat_multi_range mr;
8722 +       u_int32_t newdstip, newsrcip, newip;
8723 +
8724 +       struct ip_conntrack *master = master_ct(ct);
8725 +
8726 +       IP_NF_ASSERT(info);
8727 +       IP_NF_ASSERT(master);
8728 +
8729 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8730 +
8731 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
8732 +
8733 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8734 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8735 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
8736 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8737 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8738 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8739 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
8740 +
8741 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8742 +               newip = newsrcip;
8743 +       else
8744 +               newip = newdstip;
8745 +
8746 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
8747 +
8748 +       mr.rangesize = 1;
8749 +       /* We don't want to manip the per-protocol, just the IPs. */
8750 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8751 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8752 +
8753 +       return ip_nat_setup_info(ct, &mr, hooknum);
8754 +}
8755 +
8756 +
8757 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
8758 +                        struct ip_conntrack_expect *exp,
8759 +                        struct ip_nat_info *info,
8760 +                        enum ip_conntrack_info ctinfo,
8761 +                        unsigned int hooknum,
8762 +                        struct sk_buff **pskb)
8763 +{
8764 +       struct iphdr *iph = (*pskb)->nh.iph;
8765 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8766 +       unsigned int datalen;
8767 +       int dir;
8768 +       struct ip_ct_mms_expect *ct_mms_info;
8769 +
8770 +       if (!exp)
8771 +               DEBUGP("ip_nat_mms: no exp!!");
8772 +
8773 +       ct_mms_info = &exp->help.exp_mms_info;
8774 +       
8775 +       /* Only mangle things once: original direction in POST_ROUTING
8776 +          and reply direction on PRE_ROUTING. */
8777 +       dir = CTINFO2DIR(ctinfo);
8778 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8779 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8780 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
8781 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8782 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8783 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8784 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8785 +               return NF_ACCEPT;
8786 +       }
8787 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
8788 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8789 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8790 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8791 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8792 +       
8793 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
8794 +       
8795 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
8796 +              exp->seq + ct_mms_info->len,
8797 +              ntohl(tcph->seq),
8798 +              ntohl(tcph->seq) + datalen);
8799 +       
8800 +       LOCK_BH(&ip_mms_lock);
8801 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
8802 +       if (between(exp->seq + ct_mms_info->len,
8803 +           ntohl(tcph->seq),
8804 +           ntohl(tcph->seq) + datalen)) {
8805 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
8806 +                       UNLOCK_BH(&ip_mms_lock);
8807 +                       return NF_DROP;
8808 +               }
8809 +       } else {
8810 +               /* Half a match?  This means a partial retransmisison.
8811 +                  It's a cracker being funky. */
8812 +               if (net_ratelimit()) {
8813 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
8814 +                              exp->seq, ct_mms_info->len,
8815 +                              ntohl(tcph->seq),
8816 +                              ntohl(tcph->seq) + datalen);
8817 +               }
8818 +               UNLOCK_BH(&ip_mms_lock);
8819 +               return NF_DROP;
8820 +       }
8821 +       UNLOCK_BH(&ip_mms_lock);
8822 +       
8823 +       return NF_ACCEPT;
8824 +}
8825 +
8826 +static struct ip_nat_helper mms[MAX_PORTS];
8827 +static char mms_names[MAX_PORTS][10];
8828 +
8829 +/* Not __exit: called from init() */
8830 +static void fini(void)
8831 +{
8832 +       int i;
8833 +
8834 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8835 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
8836 +               ip_nat_helper_unregister(&mms[i]);
8837 +       }
8838 +}
8839 +
8840 +static int __init init(void)
8841 +{
8842 +       int i, ret = 0;
8843 +       char *tmpname;
8844 +
8845 +       if (ports[0] == 0)
8846 +               ports[0] = MMS_PORT;
8847 +
8848 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
8849 +
8850 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
8851 +
8852 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
8853 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
8854 +               mms[i].mask.dst.protonum = 0xFFFF;
8855 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
8856 +               mms[i].help = mms_nat_help;
8857 +               mms[i].me = THIS_MODULE;
8858 +               mms[i].flags = 0;
8859 +               mms[i].expect = mms_nat_expected;
8860 +
8861 +               tmpname = &mms_names[i][0];
8862 +               if (ports[i] == MMS_PORT)
8863 +                       sprintf(tmpname, "mms");
8864 +               else
8865 +                       sprintf(tmpname, "mms-%d", i);
8866 +               mms[i].name = tmpname;
8867 +
8868 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
8869 +                               ports[i]);
8870 +               ret = ip_nat_helper_register(&mms[i]);
8871 +
8872 +               if (ret) {
8873 +                       printk("ip_nat_mms: error registering "
8874 +                              "helper for port %d\n", ports[i]);
8875 +                       fini();
8876 +                       return ret;
8877 +               }
8878 +               ports_c++;
8879 +       }
8880 +
8881 +       return ret;
8882 +}
8883 +
8884 +module_init(init);
8885 +module_exit(fini);
8886 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
8887 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_pptp.c     1970-01-01 01:00:00.000000000 +0100
8888 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_pptp.c 2003-11-17 09:09:34.000000000 +0100
8889 @@ -0,0 +1,475 @@
8890 +/*
8891 + * ip_nat_pptp.c       - Version 1.5
8892 + *
8893 + * NAT support for PPTP (Point to Point Tunneling Protocol).
8894 + * PPTP is a a protocol for creating virtual private networks.
8895 + * It is a specification defined by Microsoft and some vendors
8896 + * working with Microsoft.  PPTP is built on top of a modified
8897 + * version of the Internet Generic Routing Encapsulation Protocol.
8898 + * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
8899 + * PPTP can be found in RFC 2637
8900 + *
8901 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
8902 + *
8903 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
8904 + *
8905 + * TODO: - Support for multiple calls within one session
8906 + *        (needs netfilter newnat code)
8907 + *      - NAT to a unique tuple, not to TCP source port
8908 + *        (needs netfilter tuple reservation)
8909 + *
8910 + * Changes:
8911 + *     2002-02-10 - Version 1.3
8912 + *       - Use ip_nat_mangle_tcp_packet() because of cloned skb's
8913 + *        in local connections (Philip Craig <philipc@snapgear.com>)
8914 + *       - add checks for magicCookie and pptp version
8915 + *       - make argument list of pptp_{out,in}bound_packet() shorter
8916 + *       - move to C99 style initializers
8917 + *       - print version number at module loadtime
8918 + *     2003-09-22 - Version 1.5
8919 + *       - use SNATed tcp sourceport as callid, since we get called before
8920 + *         TCP header is mangled (Philip Craig <philipc@snapgear.com>)
8921 + * 
8922 + */
8923 +
8924 +#include <linux/config.h>
8925 +#include <linux/module.h>
8926 +#include <linux/ip.h>
8927 +#include <linux/tcp.h>
8928 +#include <net/tcp.h>
8929 +#include <linux/netfilter_ipv4/ip_nat.h>
8930 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8931 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8932 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
8933 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8934 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
8935 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
8936 +
8937 +#define IP_NAT_PPTP_VERSION "1.5"
8938 +
8939 +MODULE_LICENSE("GPL");
8940 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
8941 +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
8942 +
8943 +
8944 +#if 0
8945 +#include "ip_conntrack_pptp_priv.h"
8946 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
8947 +                                      ": " format, ## args)
8948 +#else
8949 +#define DEBUGP(format, args...)
8950 +#endif
8951 +
8952 +static unsigned int
8953 +pptp_nat_expected(struct sk_buff **pskb,
8954 +                 unsigned int hooknum,
8955 +                 struct ip_conntrack *ct,
8956 +                 struct ip_nat_info *info)
8957 +{
8958 +       struct ip_conntrack *master = master_ct(ct);
8959 +       struct ip_nat_multi_range mr;
8960 +       struct ip_ct_pptp_master *ct_pptp_info;
8961 +       struct ip_nat_pptp *nat_pptp_info;
8962 +       u_int32_t newip, newcid;
8963 +       int ret;
8964 +
8965 +       IP_NF_ASSERT(info);
8966 +       IP_NF_ASSERT(master);
8967 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
8968 +
8969 +       DEBUGP("we have a connection!\n");
8970 +
8971 +       LOCK_BH(&ip_pptp_lock);
8972 +       ct_pptp_info = &master->help.ct_pptp_info;
8973 +       nat_pptp_info = &master->nat.help.nat_pptp_info;
8974 +
8975 +       /* need to alter GRE tuple because conntrack expectfn() used 'wrong'
8976 +        * (unmanipulated) values */
8977 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8978 +               DEBUGP("completing tuples with NAT info \n");
8979 +               /* we can do this, since we're unconfirmed */
8980 +               if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
8981 +                       htonl(ct_pptp_info->pac_call_id)) {     
8982 +                       /* assume PNS->PAC */
8983 +                       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8984 +                               htonl(nat_pptp_info->pns_call_id);
8985 +                       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8986 +                               htonl(nat_pptp_info->pns_call_id);
8987 +                       newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8988 +                       newcid = htonl(nat_pptp_info->pac_call_id);
8989 +               } else {
8990 +                       /* assume PAC->PNS */
8991 +                       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
8992 +                               htonl(nat_pptp_info->pac_call_id);
8993 +                       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
8994 +                               htonl(nat_pptp_info->pac_call_id);
8995 +                       newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8996 +                       newcid = htonl(nat_pptp_info->pns_call_id);
8997 +               }
8998 +       } else {
8999 +               if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
9000 +                       htonl(ct_pptp_info->pac_call_id)) {     
9001 +                       /* assume PNS->PAC */
9002 +                       newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9003 +                       newcid = htonl(ct_pptp_info->pns_call_id);
9004 +               }
9005 +               else {
9006 +                       /* assume PAC->PNS */
9007 +                       newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
9008 +                       newcid = htonl(ct_pptp_info->pac_call_id);
9009 +               }
9010 +       }
9011 +
9012 +       mr.rangesize = 1;
9013 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
9014 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
9015 +       mr.range[0].min = mr.range[0].max = 
9016 +               ((union ip_conntrack_manip_proto ) { newcid }); 
9017 +       DEBUGP("change ip to %u.%u.%u.%u\n", 
9018 +               NIPQUAD(newip));
9019 +       DEBUGP("change key to 0x%x\n", ntohl(newcid));
9020 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
9021 +
9022 +       UNLOCK_BH(&ip_pptp_lock);
9023 +
9024 +       return ret;
9025 +
9026 +}
9027 +
9028 +/* outbound packets == from PNS to PAC */
9029 +static inline unsigned int
9030 +pptp_outbound_pkt(struct sk_buff **pskb,
9031 +                 struct ip_conntrack *ct,
9032 +                 enum ip_conntrack_info ctinfo,
9033 +                 struct ip_conntrack_expect *exp)
9034 +
9035 +{
9036 +       struct iphdr *iph = (*pskb)->nh.iph;
9037 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9038 +       struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
9039 +                                       ((void *)tcph + tcph->doff*4);
9040 +
9041 +       struct PptpControlHeader *ctlh;
9042 +       union pptp_ctrl_union pptpReq;
9043 +       struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9044 +       struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9045 +
9046 +       u_int16_t msg, *cid = NULL, new_callid;
9047 +
9048 +       /* FIXME: size checks !!! */
9049 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9050 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9051 +
9052 +       new_callid = htons(ct_pptp_info->pns_call_id);
9053 +       
9054 +       switch (msg = ntohs(ctlh->messageType)) {
9055 +               case PPTP_OUT_CALL_REQUEST:
9056 +                       cid = &pptpReq.ocreq->callID;
9057 +                       /* FIXME: ideally we would want to reserve a call ID
9058 +                        * here.  current netfilter NAT core is not able to do
9059 +                        * this :( For now we use TCP source port. This breaks
9060 +                        * multiple calls within one control session */
9061 +
9062 +                       /* save original call ID in nat_info */
9063 +                       nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
9064 +
9065 +                       /* don't use tcph->source since we are at a DSTmanip
9066 +                        * hook (e.g. PREROUTING) and pkt is not mangled yet */
9067 +                       new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
9068 +
9069 +                       /* save new call ID in ct info */
9070 +                       ct_pptp_info->pns_call_id = ntohs(new_callid);
9071 +                       break;
9072 +               case PPTP_IN_CALL_REPLY:
9073 +                       cid = &pptpReq.icreq->callID;
9074 +                       break;
9075 +               case PPTP_CALL_CLEAR_REQUEST:
9076 +                       cid = &pptpReq.clrreq->callID;
9077 +                       break;
9078 +               default:
9079 +                       DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
9080 +                             (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9081 +                       /* fall through */
9082 +
9083 +               case PPTP_SET_LINK_INFO:
9084 +                       /* only need to NAT in case PAC is behind NAT box */
9085 +               case PPTP_START_SESSION_REQUEST:
9086 +               case PPTP_START_SESSION_REPLY:
9087 +               case PPTP_STOP_SESSION_REQUEST:
9088 +               case PPTP_STOP_SESSION_REPLY:
9089 +               case PPTP_ECHO_REQUEST:
9090 +               case PPTP_ECHO_REPLY:
9091 +                       /* no need to alter packet */
9092 +                       return NF_ACCEPT;
9093 +       }
9094 +
9095 +       IP_NF_ASSERT(cid);
9096 +
9097 +       DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9098 +               ntohs(*cid), ntohs(new_callid));
9099 +
9100 +       /* mangle packet */
9101 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
9102 +                                sizeof(new_callid), (char *)&new_callid,
9103 +                                sizeof(new_callid));
9104 +
9105 +       return NF_ACCEPT;
9106 +}
9107 +
9108 +/* inbound packets == from PAC to PNS */
9109 +static inline unsigned int
9110 +pptp_inbound_pkt(struct sk_buff **pskb,
9111 +                struct ip_conntrack *ct,
9112 +                enum ip_conntrack_info ctinfo,
9113 +                struct ip_conntrack_expect *oldexp)
9114 +{
9115 +       struct iphdr *iph = (*pskb)->nh.iph;
9116 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9117 +       struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
9118 +                                       ((void *)tcph + tcph->doff*4);
9119 +
9120 +       struct PptpControlHeader *ctlh;
9121 +       union pptp_ctrl_union pptpReq;
9122 +       struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
9123 +       struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
9124 +
9125 +       u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
9126 +       u_int32_t old_dst_ip;
9127 +
9128 +       struct ip_conntrack_tuple t, inv_t;
9129 +       struct ip_conntrack_tuple *orig_t, *reply_t;
9130 +
9131 +       /* FIXME: size checks !!! */
9132 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
9133 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
9134 +
9135 +       new_pcid = htons(nat_pptp_info->pns_call_id);
9136 +
9137 +       switch (msg = ntohs(ctlh->messageType)) {
9138 +       case PPTP_OUT_CALL_REPLY:
9139 +               pcid = &pptpReq.ocack->peersCallID;     
9140 +               cid = &pptpReq.ocack->callID;
9141 +               if (!oldexp) {
9142 +                       DEBUGP("outcall but no expectation\n");
9143 +                       break;
9144 +               }
9145 +               old_dst_ip = oldexp->tuple.dst.ip;
9146 +               t = oldexp->tuple;
9147 +               invert_tuplepr(&inv_t, &t);
9148 +
9149 +               /* save original PAC call ID in nat_info */
9150 +               nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
9151 +
9152 +               /* alter expectation */
9153 +               orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
9154 +               reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
9155 +               if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
9156 +                       /* expectation for PNS->PAC direction */
9157 +                       t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9158 +                       t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9159 +                       inv_t.src.ip = reply_t->src.ip;
9160 +                       inv_t.dst.ip = reply_t->dst.ip;
9161 +                       inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9162 +                       inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9163 +               } else {
9164 +                       /* expectation for PAC->PNS direction */
9165 +                       t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
9166 +                       t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
9167 +                       inv_t.src.ip = orig_t->src.ip;
9168 +                       inv_t.dst.ip = orig_t->dst.ip;
9169 +                       inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
9170 +                       inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
9171 +               }
9172 +
9173 +               if (!ip_conntrack_change_expect(oldexp, &t)) {
9174 +                       DEBUGP("successfully changed expect\n");
9175 +               } else {
9176 +                       DEBUGP("can't change expect\n");
9177 +               }
9178 +               ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
9179 +               ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
9180 +               break;
9181 +       case PPTP_IN_CALL_CONNECT:
9182 +               pcid = &pptpReq.iccon->peersCallID;
9183 +               if (!oldexp)
9184 +                       break;
9185 +               old_dst_ip = oldexp->tuple.dst.ip;
9186 +               t = oldexp->tuple;
9187 +
9188 +               /* alter expectation, no need for callID */
9189 +               if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
9190 +                       /* expectation for PNS->PAC direction */
9191 +                       t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9192 +               } else {
9193 +                       /* expectation for PAC->PNS direction */
9194 +                       t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9195 +               }
9196 +
9197 +               if (!ip_conntrack_change_expect(oldexp, &t)) {
9198 +                       DEBUGP("successfully changed expect\n");
9199 +               } else {
9200 +                       DEBUGP("can't change expect\n");
9201 +               }
9202 +               break;
9203 +       case PPTP_IN_CALL_REQUEST:
9204 +               /* only need to nat in case PAC is behind NAT box */
9205 +               break;
9206 +       case PPTP_WAN_ERROR_NOTIFY:
9207 +               pcid = &pptpReq.wanerr->peersCallID;
9208 +               break;
9209 +       case PPTP_CALL_DISCONNECT_NOTIFY:
9210 +               pcid = &pptpReq.disc->callID;
9211 +               break;
9212 +
9213 +       default:
9214 +               DEBUGP("unknown inbound packet %s\n",
9215 +                       (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
9216 +               /* fall through */
9217 +
9218 +       case PPTP_START_SESSION_REQUEST:
9219 +       case PPTP_START_SESSION_REPLY:
9220 +       case PPTP_STOP_SESSION_REQUEST:
9221 +       case PPTP_STOP_SESSION_REPLY:
9222 +       case PPTP_ECHO_REQUEST:
9223 +       case PPTP_ECHO_REPLY:
9224 +               /* no need to alter packet */
9225 +               return NF_ACCEPT;
9226 +       }
9227 +
9228 +       /* mangle packet */
9229 +       IP_NF_ASSERT(pcid);
9230 +       DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
9231 +               ntohs(*pcid), ntohs(new_pcid));
9232 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
9233 +                                sizeof(new_pcid), (char *)&new_pcid, 
9234 +                                sizeof(new_pcid));
9235 +
9236 +       if (new_cid) {
9237 +               IP_NF_ASSERT(cid);
9238 +               DEBUGP("altering call id from 0x%04x to 0x%04x\n",
9239 +                       ntohs(*cid), ntohs(new_cid));
9240 +               ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
9241 +                                        (void *)cid - (void *)pptph, 
9242 +                                        sizeof(new_cid), (char *)&new_cid, 
9243 +                                        sizeof(new_cid));
9244 +       }
9245 +
9246 +       /* great, at least we don't need to resize packets */
9247 +       return NF_ACCEPT;
9248 +}
9249 +
9250 +
9251 +static unsigned int tcp_help(struct ip_conntrack *ct,
9252 +                            struct ip_conntrack_expect *exp,
9253 +                            struct ip_nat_info *info,
9254 +                            enum ip_conntrack_info ctinfo,
9255 +                            unsigned int hooknum, struct sk_buff **pskb)
9256 +{
9257 +       struct iphdr *iph = (*pskb)->nh.iph;
9258 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
9259 +       unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
9260 +       struct pptp_pkt_hdr *pptph;
9261 +
9262 +       int dir;
9263 +
9264 +       DEBUGP("entering\n");
9265 +
9266 +       /* Only mangle things once: DST for original direction
9267 +          and SRC for reply direction. */
9268 +       dir = CTINFO2DIR(ctinfo);
9269 +       if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
9270 +            && dir == IP_CT_DIR_ORIGINAL)
9271 +             || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
9272 +                 && dir == IP_CT_DIR_REPLY))) {
9273 +               DEBUGP("Not touching dir %s at hook %s\n",
9274 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9275 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9276 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9277 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
9278 +                      : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
9279 +               return NF_ACCEPT;
9280 +       }
9281 +
9282 +       /* if packet is too small, just skip it */
9283 +       if (datalen < sizeof(struct pptp_pkt_hdr)+
9284 +                     sizeof(struct PptpControlHeader)) {
9285 +               DEBUGP("pptp packet too short\n");
9286 +               return NF_ACCEPT;       
9287 +       }
9288 +
9289 +       pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
9290 +
9291 +       /* if it's not a control message, we can't handle it */
9292 +       if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
9293 +           ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
9294 +               DEBUGP("not a pptp control packet\n");
9295 +               return NF_ACCEPT;
9296 +       }
9297 +
9298 +       LOCK_BH(&ip_pptp_lock);
9299 +
9300 +       if (dir == IP_CT_DIR_ORIGINAL) {
9301 +               /* reuqests sent by client to server (PNS->PAC) */
9302 +               pptp_outbound_pkt(pskb, ct, ctinfo, exp);
9303 +       } else {
9304 +               /* response from the server to the client (PAC->PNS) */
9305 +               pptp_inbound_pkt(pskb, ct, ctinfo, exp);
9306 +       }
9307 +
9308 +       UNLOCK_BH(&ip_pptp_lock);
9309 +
9310 +       return NF_ACCEPT;
9311 +}
9312 +
9313 +/* nat helper struct for control connection */
9314 +static struct ip_nat_helper pptp_tcp_helper = { 
9315 +       .list = { NULL, NULL },
9316 +       .name = "pptp", 
9317 +       .flags = IP_NAT_HELPER_F_ALWAYS, 
9318 +       .me = THIS_MODULE,
9319 +       .tuple = { .src = { .ip = 0, 
9320 +                           .u = { .tcp = { .port = 
9321 +                                       __constant_htons(PPTP_CONTROL_PORT) } 
9322 +                                } 
9323 +                         },
9324 +                  .dst = { .ip = 0, 
9325 +                           .u = { .all = 0 }, 
9326 +                           .protonum = IPPROTO_TCP 
9327 +                         } 
9328 +                },
9329 +
9330 +       .mask = { .src = { .ip = 0, 
9331 +                          .u = { .tcp = { .port = 0xFFFF } } 
9332 +                        },
9333 +                 .dst = { .ip = 0, 
9334 +                          .u = { .all = 0 }, 
9335 +                          .protonum = 0xFFFF 
9336 +                        } 
9337 +               },
9338 +       .help = tcp_help, 
9339 +       .expect = pptp_nat_expected 
9340 +};
9341 +
9342 +                         
9343 +static int __init init(void)
9344 +{
9345 +       DEBUGP("%s: registering NAT helper\n", __FILE__);
9346 +       if (ip_nat_helper_register(&pptp_tcp_helper)) {
9347 +               printk(KERN_ERR "Unable to register NAT application helper "
9348 +                               "for pptp\n");
9349 +               return -EIO;
9350 +       }
9351 +
9352 +       printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
9353 +       return 0;
9354 +}
9355 +
9356 +static void __exit fini(void)
9357 +{
9358 +       DEBUGP("cleanup_module\n" );
9359 +       ip_nat_helper_unregister(&pptp_tcp_helper);
9360 +       printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
9361 +}
9362 +
9363 +module_init(init);
9364 +module_exit(fini);
9365 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
9366 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_proto_gre.c        1970-01-01 01:00:00.000000000 +0100
9367 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_proto_gre.c    2003-11-17 09:09:34.000000000 +0100
9368 @@ -0,0 +1,225 @@
9369 +/*
9370 + * ip_nat_proto_gre.c - Version 1.2
9371 + *
9372 + * NAT protocol helper module for GRE.
9373 + *
9374 + * GRE is a generic encapsulation protocol, which is generally not very
9375 + * suited for NAT, as it has no protocol-specific part as port numbers.
9376 + *
9377 + * It has an optional key field, which may help us distinguishing two 
9378 + * connections between the same two hosts.
9379 + *
9380 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
9381 + *
9382 + * PPTP is built on top of a modified version of GRE, and has a mandatory
9383 + * field called "CallID", which serves us for the same purpose as the key
9384 + * field in plain GRE.
9385 + *
9386 + * Documentation about PPTP can be found in RFC 2637
9387 + *
9388 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
9389 + *
9390 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
9391 + *
9392 + */
9393 +
9394 +#include <linux/config.h>
9395 +#include <linux/module.h>
9396 +#include <linux/ip.h>
9397 +#include <linux/netfilter_ipv4/ip_nat.h>
9398 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9399 +#include <linux/netfilter_ipv4/ip_nat_protocol.h>
9400 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
9401 +
9402 +MODULE_LICENSE("GPL");
9403 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
9404 +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
9405 +
9406 +#if 0
9407 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
9408 +                                      ": " format, ## args)
9409 +#else
9410 +#define DEBUGP(x, args...)
9411 +#endif
9412 +
9413 +/* is key in given range between min and max */
9414 +static int
9415 +gre_in_range(const struct ip_conntrack_tuple *tuple,
9416 +            enum ip_nat_manip_type maniptype,
9417 +            const union ip_conntrack_manip_proto *min,
9418 +            const union ip_conntrack_manip_proto *max)
9419 +{
9420 +       u_int32_t key;
9421 +
9422 +       if (maniptype == IP_NAT_MANIP_SRC)
9423 +               key = tuple->src.u.gre.key;
9424 +       else
9425 +               key = tuple->dst.u.gre.key;
9426 +
9427 +       return ntohl(key) >= ntohl(min->gre.key)
9428 +               && ntohl(key) <= ntohl(max->gre.key);
9429 +}
9430 +
9431 +/* generate unique tuple ... */
9432 +static int 
9433 +gre_unique_tuple(struct ip_conntrack_tuple *tuple,
9434 +                const struct ip_nat_range *range,
9435 +                enum ip_nat_manip_type maniptype,
9436 +                const struct ip_conntrack *conntrack)
9437 +{
9438 +       u_int32_t min, i, range_size;
9439 +       u_int32_t key = 0, *keyptr;
9440 +
9441 +       if (maniptype == IP_NAT_MANIP_SRC)
9442 +               keyptr = &tuple->src.u.gre.key;
9443 +       else
9444 +               keyptr = &tuple->dst.u.gre.key;
9445 +
9446 +       if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
9447 +
9448 +               switch (tuple->dst.u.gre.version) {
9449 +               case 0:
9450 +                       DEBUGP("NATing GRE version 0 (ct=%p)\n",
9451 +                               conntrack);
9452 +                       min = 1;
9453 +                       range_size = 0xffffffff;
9454 +                       break;
9455 +               case GRE_VERSION_PPTP:
9456 +                       DEBUGP("%p: NATing GRE PPTP\n", 
9457 +                               conntrack);
9458 +                       min = 1;
9459 +                       range_size = 0xffff;
9460 +                       break;
9461 +               default:
9462 +                       printk(KERN_WARNING "nat_gre: unknown GRE version\n");
9463 +                       return 0;
9464 +                       break;
9465 +               }
9466 +
9467 +       } else {
9468 +               min = ntohl(range->min.gre.key);
9469 +               range_size = ntohl(range->max.gre.key) - min + 1;
9470 +       }
9471 +
9472 +       DEBUGP("min = %u, range_size = %u\n", min, range_size); 
9473 +
9474 +       for (i = 0; i < range_size; i++, key++) {
9475 +               *keyptr = htonl(min + key % range_size);
9476 +               if (!ip_nat_used_tuple(tuple, conntrack))
9477 +                       return 1;
9478 +       }
9479 +
9480 +       DEBUGP("%p: no NAT mapping\n", conntrack);
9481 +
9482 +       return 0;
9483 +}
9484 +
9485 +/* manipulate a GRE packet according to maniptype */
9486 +static void 
9487 +gre_manip_pkt(struct iphdr *iph, size_t len, 
9488 +             const struct ip_conntrack_manip *manip,
9489 +             enum ip_nat_manip_type maniptype)
9490 +{
9491 +       struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
9492 +       struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;
9493 +
9494 +       /* we only have destination manip of a packet, since 'source key' 
9495 +        * is not present in the packet itself */
9496 +       if (maniptype == IP_NAT_MANIP_DST) {
9497 +               /* key manipulation is always dest */
9498 +               switch (greh->version) {
9499 +               case 0:
9500 +                       if (!greh->key) {
9501 +                               DEBUGP("can't nat GRE w/o key\n");
9502 +                               break;
9503 +                       }
9504 +                       if (greh->csum) {
9505 +                               /* FIXME: Never tested this code... */
9506 +                               *(gre_csum(greh)) = 
9507 +                                       ip_nat_cheat_check(~*(gre_key(greh)),
9508 +                                                       manip->u.gre.key,
9509 +                                                       *(gre_csum(greh)));
9510 +                       }
9511 +                       *(gre_key(greh)) = manip->u.gre.key;
9512 +                       break;
9513 +               case GRE_VERSION_PPTP:
9514 +                       DEBUGP("call_id -> 0x%04x\n", 
9515 +                               ntohl(manip->u.gre.key));
9516 +                       pgreh->call_id = htons(ntohl(manip->u.gre.key));
9517 +                       break;
9518 +               default:
9519 +                       DEBUGP("can't nat unknown GRE version\n");
9520 +                       break;
9521 +               }
9522 +       }
9523 +}
9524 +
9525 +/* print out a nat tuple */
9526 +static unsigned int 
9527 +gre_print(char *buffer, 
9528 +         const struct ip_conntrack_tuple *match,
9529 +         const struct ip_conntrack_tuple *mask)
9530 +{
9531 +       unsigned int len = 0;
9532 +
9533 +       if (mask->dst.u.gre.version)
9534 +               len += sprintf(buffer + len, "version=%d ",
9535 +                               ntohs(match->dst.u.gre.version));
9536 +
9537 +       if (mask->dst.u.gre.protocol)
9538 +               len += sprintf(buffer + len, "protocol=0x%x ",
9539 +                               ntohs(match->dst.u.gre.protocol));
9540 +
9541 +       if (mask->src.u.gre.key)
9542 +               len += sprintf(buffer + len, "srckey=0x%x ", 
9543 +                               ntohl(match->src.u.gre.key));
9544 +
9545 +       if (mask->dst.u.gre.key)
9546 +               len += sprintf(buffer + len, "dstkey=0x%x ",
9547 +                               ntohl(match->src.u.gre.key));
9548 +
9549 +       return len;
9550 +}
9551 +
9552 +/* print a range of keys */
9553 +static unsigned int 
9554 +gre_print_range(char *buffer, const struct ip_nat_range *range)
9555 +{
9556 +       if (range->min.gre.key != 0 
9557 +           || range->max.gre.key != 0xFFFF) {
9558 +               if (range->min.gre.key == range->max.gre.key)
9559 +                       return sprintf(buffer, "key 0x%x ",
9560 +                                       ntohl(range->min.gre.key));
9561 +               else
9562 +                       return sprintf(buffer, "keys 0x%u-0x%u ",
9563 +                                       ntohl(range->min.gre.key),
9564 +                                       ntohl(range->max.gre.key));
9565 +       } else
9566 +               return 0;
9567 +}
9568 +
9569 +/* nat helper struct */
9570 +static struct ip_nat_protocol gre = 
9571 +       { { NULL, NULL }, "GRE", IPPROTO_GRE,
9572 +         gre_manip_pkt,
9573 +         gre_in_range,
9574 +         gre_unique_tuple,
9575 +         gre_print,
9576 +         gre_print_range 
9577 +       };
9578 +                                 
9579 +static int __init init(void)
9580 +{
9581 +        if (ip_nat_protocol_register(&gre))
9582 +                return -EIO;
9583 +
9584 +        return 0;
9585 +}
9586 +
9587 +static void __exit fini(void)
9588 +{
9589 +        ip_nat_protocol_unregister(&gre);
9590 +}
9591 +
9592 +module_init(init);
9593 +module_exit(fini);
9594 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
9595 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_quake3.c   1970-01-01 01:00:00.000000000 +0100
9596 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_quake3.c       2003-12-11 10:24:00.845688024 +0100
9597 @@ -0,0 +1,249 @@
9598 +/* Quake3 extension for UDP NAT alteration.
9599 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
9600 + * based on ip_nat_ftp.c and ip_nat_tftp.c
9601 + *
9602 + * ip_nat_quake3.c v0.0.3 2002-08-31
9603 + *
9604 + *      This program is free software; you can redistribute it and/or
9605 + *      modify it under the terms of the GNU General Public License
9606 + *      as published by the Free Software Foundation; either version
9607 + *      2 of the License, or (at your option) any later version.
9608 + *
9609 + *      Module load syntax:
9610 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
9611 + *
9612 + *      please give the ports of all Quake3 master servers You wish to
9613 + *      connect to. If you don't specify ports, the default will be UDP
9614 + *      port 27950.
9615 + *
9616 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
9617 + *
9618 + *      Notes: 
9619 + *      - If you're one of those people who would try anything to lower
9620 + *        latency while playing Quake (and who isn't :-) ), you may want to
9621 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
9622 + *        outgoing UDP traffic.
9623 + *        This will make ip_conntrack_quake3 add the necessary expectations,
9624 + *        but there will be no overhead for client->server UDP streams. If
9625 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
9626 + *        hook for every packet in the client->server UDP stream.
9627 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
9628 + *        The IP addresses in the master connection payload (=IP addresses
9629 + *        of Quake servers) have no relation with the master server so
9630 + *        DNAT'ing the master connection to a server should not change the
9631 + *        expected connections.
9632 + *      - Not tested due to lack of equipment:
9633 + *        - multiple Quake3 clients behind one MASQUERADE gateway
9634 + *        - what if Quake3 client is running on router too
9635 + */
9636 +
9637 +#include <linux/module.h>
9638 +#include <linux/netfilter_ipv4.h>
9639 +#include <linux/ip.h>
9640 +#include <linux/udp.h>
9641 +
9642 +#include <linux/netfilter.h>
9643 +#include <linux/netfilter_ipv4/ip_tables.h>
9644 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9645 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
9646 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9647 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9648 +
9649 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
9650 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
9651 +MODULE_LICENSE("GPL");
9652 +
9653 +#define MAX_PORTS 8
9654 +
9655 +static int ports[MAX_PORTS];
9656 +static int ports_c = 0;
9657 +#ifdef MODULE_PARM
9658 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
9659 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
9660 +#endif
9661 +
9662 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
9663 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
9664 +#if 0 
9665 +#define DEBUGP printk
9666 +#else
9667 +#define DEBUGP(format, args...)
9668 +#endif
9669 +
9670 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
9671 +
9672 +static unsigned int 
9673 +quake3_nat_help(struct ip_conntrack *ct,
9674 +                struct ip_conntrack_expect *exp,
9675 +                struct ip_nat_info *info,
9676 +                enum ip_conntrack_info ctinfo,
9677 +                unsigned int hooknum,
9678 +                struct sk_buff **pskb)
9679 +{
9680 +       struct iphdr *iph = (*pskb)->nh.iph;
9681 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
9682 +       struct ip_conntrack_tuple repl;
9683 +       int dir = CTINFO2DIR(ctinfo);
9684 +       int i;
9685 +       
9686 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
9687 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9688 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9689 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9690 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
9691 +             );
9692 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9693 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
9694 +       
9695 +       /* Only mangle things once: original direction in POST_ROUTING
9696 +          and reply direction on PRE_ROUTING. */
9697 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
9698 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
9699 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
9700 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
9701 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9702 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9703 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
9704 +               return NF_ACCEPT;
9705 +       }
9706 +
9707 +       if (!exp) {
9708 +               DEBUGP("no conntrack expectation to modify\n");
9709 +               return NF_ACCEPT;
9710 +       }
9711 +
9712 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
9713 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
9714 +                   i+6 < ntohs(udph->len);
9715 +                   i+=7) {
9716 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
9717 +                              i, ntohs(udph->len),
9718 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
9719 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
9720 +                       
9721 +                       memset(&repl, 0, sizeof(repl));
9722 +
9723 +                       repl.dst.protonum = IPPROTO_UDP;
9724 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
9725 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
9726 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
9727 +                       
9728 +                       ip_conntrack_change_expect(exp, &repl);
9729 +               }
9730 +       }
9731 +       return NF_ACCEPT;
9732 +}
9733 +
9734 +static unsigned int 
9735 +quake3_nat_expected(struct sk_buff **pskb,
9736 +                    unsigned int hooknum,
9737 +                    struct ip_conntrack *ct, 
9738 +                    struct ip_nat_info *info) 
9739 +{
9740 +       const struct ip_conntrack *master = ct->master->expectant;
9741 +       struct ip_nat_multi_range mr;
9742 +       u_int32_t newsrcip, newdstip, newip;
9743 +#if 0 
9744 +       const struct ip_conntrack_tuple *repl =
9745 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
9746 +       struct iphdr *iph = (*pskb)->nh.iph;
9747 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
9748 +#endif
9749 +
9750 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
9751 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
9752 +
9753 +       IP_NF_ASSERT(info);
9754 +       IP_NF_ASSERT(master);
9755 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
9756 +       
9757 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
9758 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
9759 +       
9760 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
9761 +               newip = newsrcip;
9762 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9763 +                      "newsrc: %u.%u.%u.%u\n",
9764 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9765 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9766 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9767 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9768 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9769 +                      NIPQUAD(newip));
9770 +               
9771 +       } else {
9772 +               newip = newdstip;
9773 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
9774 +                      "newdst: %u.%u.%u.%u\n",
9775 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
9776 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
9777 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
9778 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
9779 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
9780 +                      NIPQUAD(newip));
9781 +       }
9782 +       
9783 +       mr.rangesize = 1;
9784 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
9785 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
9786 +
9787 +       return ip_nat_setup_info(ct,&mr,hooknum);
9788 +}
9789 +
9790 +static struct ip_nat_helper quake3[MAX_PORTS];
9791 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
9792 +
9793 +static void fini(void)
9794 +{
9795 +       int i;
9796 +       
9797 +       for (i = 0 ; i < ports_c; i++) {
9798 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
9799 +                      ip_nat_helper_unregister(&quake3[i]);
9800 +       }
9801 +}
9802 +
9803 +static int __init init(void)
9804 +       {
9805 +               int i, ret = 0;
9806 +               char *tmpname;
9807 +
9808 +               if (!ports[0])
9809 +                       ports[0] = QUAKE3_MASTER_PORT;
9810 +               
9811 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
9812 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
9813 +
9814 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
9815 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
9816 +                       quake3[i].mask.dst.protonum = 0xFFFF;
9817 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
9818 +                       quake3[i].help = quake3_nat_help;
9819 +                       quake3[i].flags = 0;
9820 +                       quake3[i].me = THIS_MODULE;
9821 +                       quake3[i].expect = quake3_nat_expected;
9822 +                       
9823 +                       tmpname = &quake3_names[i][0];
9824 +                       if (ports[i] == QUAKE3_MASTER_PORT)
9825 +                               sprintf(tmpname, "quake3");
9826 +                       else
9827 +                               sprintf(tmpname, "quake3-%d", i);
9828 +                       quake3[i].name = tmpname;
9829 +                       
9830 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
9831 +                              ports[i], quake3[i].name);
9832 +                       ret = ip_nat_helper_register(&quake3[i]);
9833 +                       
9834 +                       if (ret) {
9835 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
9836 +                                      ports[i]);
9837 +                               fini();
9838 +                               return ret;
9839 +                       }
9840 +                       ports_c++;
9841 +               }
9842 +               return ret;
9843 +       }
9844 +       
9845 +module_init(init);
9846 +module_exit(fini);
9847 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
9848 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rtsp.c     1970-01-01 01:00:00.000000000 +0100
9849 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rtsp.c 2003-12-11 10:24:06.857774048 +0100
9850 @@ -0,0 +1,625 @@
9851 +/*
9852 + * RTSP extension for TCP NAT alteration
9853 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
9854 + * based on ip_nat_irc.c
9855 + *
9856 + *      This program is free software; you can redistribute it and/or
9857 + *      modify it under the terms of the GNU General Public License
9858 + *      as published by the Free Software Foundation; either version
9859 + *      2 of the License, or (at your option) any later version.
9860 + *
9861 + * Module load syntax:
9862 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
9863 + *                           stunaddr=<address>
9864 + *                           destaction=[auto|strip|none]
9865 + *
9866 + * If no ports are specified, the default will be port 554 only.
9867 + *
9868 + * stunaddr specifies the address used to detect that a client is using STUN.
9869 + * If this address is seen in the destination parameter, it is assumed that
9870 + * the client has already punched a UDP hole in the firewall, so we don't
9871 + * mangle the client_port.  If none is specified, it is autodetected.  It
9872 + * only needs to be set if you have multiple levels of NAT.  It should be
9873 + * set to the external address that the STUN clients detect.  Note that in
9874 + * this case, it will not be possible for clients to use UDP with servers
9875 + * between the NATs.
9876 + *
9877 + * If no destaction is specified, auto is used.
9878 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
9879 + *   destaction=strip: always strip destination parameter (not recommended).
9880 + *   destaction=none:  do not touch destination parameter (not recommended).
9881 + */
9882 +
9883 +#include <linux/module.h>
9884 +#include <linux/netfilter_ipv4.h>
9885 +#include <linux/ip.h>
9886 +#include <linux/tcp.h>
9887 +#include <linux/kernel.h>
9888 +#include <net/tcp.h>
9889 +#include <linux/netfilter_ipv4/ip_nat.h>
9890 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
9891 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9892 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
9893 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9894 +
9895 +#include <linux/inet.h>
9896 +#include <linux/ctype.h>
9897 +#define NF_NEED_STRNCASECMP
9898 +#define NF_NEED_STRTOU16
9899 +#include <linux/netfilter_helpers.h>
9900 +#define NF_NEED_MIME_NEXTLINE
9901 +#include <linux/netfilter_mime.h>
9902 +
9903 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
9904 +#ifdef IP_NF_RTSP_DEBUG
9905 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args);
9906 +#else
9907 +#define DEBUGP(args...)
9908 +#endif
9909 +
9910 +#define MAX_PORTS       8
9911 +#define DSTACT_AUTO     0
9912 +#define DSTACT_STRIP    1
9913 +#define DSTACT_NONE     2
9914 +
9915 +static int      ports[MAX_PORTS];
9916 +static char*    stunaddr = NULL;
9917 +static char*    destaction = NULL;
9918 +
9919 +static int       num_ports = 0;
9920 +static u_int32_t extip = 0;
9921 +static int       dstact = 0;
9922 +
9923 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
9924 +MODULE_DESCRIPTION("RTSP network address translation module");
9925 +MODULE_LICENSE("GPL");
9926 +#ifdef MODULE_PARM
9927 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9928 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
9929 +MODULE_PARM(stunaddr, "s");
9930 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
9931 +MODULE_PARM(destaction, "s");
9932 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
9933 +#endif
9934 +
9935 +/* protects rtsp part of conntracks */
9936 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
9937 +
9938 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
9939 +
9940 +/*** helper functions ***/
9941 +
9942 +static void
9943 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
9944 +{
9945 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
9946 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
9947 +
9948 +    *pptcpdata = (char*)tcph + tcph->doff*4;
9949 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
9950 +}
9951 +
9952 +/*** nat functions ***/
9953 +
9954 +/*
9955 + * Mangle the "Transport:" header:
9956 + *   - Replace all occurences of "client_port=<spec>"
9957 + *   - Handle destination parameter
9958 + *
9959 + * In:
9960 + *   ct, ctinfo = conntrack context
9961 + *   pskb       = packet
9962 + *   tranoff    = Transport header offset from TCP data
9963 + *   tranlen    = Transport header length (incl. CRLF)
9964 + *   rport_lo   = replacement low  port (host endian)
9965 + *   rport_hi   = replacement high port (host endian)
9966 + *
9967 + * Returns packet size difference.
9968 + *
9969 + * Assumes that a complete transport header is present, ending with CR or LF
9970 + */
9971 +static int
9972 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
9973 +                 struct ip_conntrack_expect* exp,
9974 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
9975 +{
9976 +    char*       ptcp;
9977 +    uint        tcplen;
9978 +    char*       ptran;
9979 +    char        rbuf1[16];      /* Replacement buffer (one port) */
9980 +    uint        rbuf1len;       /* Replacement len (one port) */
9981 +    char        rbufa[16];      /* Replacement buffer (all ports) */
9982 +    uint        rbufalen;       /* Replacement len (all ports) */
9983 +    u_int32_t   newip;
9984 +    u_int16_t   loport, hiport;
9985 +    uint        off = 0;
9986 +    uint        diff;           /* Number of bytes we removed */
9987 +
9988 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
9989 +    struct ip_conntrack_tuple t;
9990 +
9991 +    char    szextaddr[15+1];
9992 +    uint    extaddrlen;
9993 +    int     is_stun;
9994 +
9995 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
9996 +    ptran = ptcp+tranoff;
9997 +
9998 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
9999 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
10000 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
10001 +    {
10002 +        INFOP("sanity check failed\n");
10003 +        return 0;
10004 +    }
10005 +    off += 10;
10006 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
10007 +
10008 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10009 +    t = exp->tuple;
10010 +    t.dst.ip = newip;
10011 +
10012 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
10013 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
10014 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
10015 +
10016 +    rbuf1len = rbufalen = 0;
10017 +    switch (prtspexp->pbtype)
10018 +    {
10019 +    case pb_single:
10020 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10021 +        {
10022 +            t.dst.u.udp.port = htons(loport);
10023 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10024 +            {
10025 +                DEBUGP("using port %hu\n", loport);
10026 +                break;
10027 +            }
10028 +        }
10029 +        if (loport != 0)
10030 +        {
10031 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
10032 +            rbufalen = sprintf(rbufa, "%hu", loport);
10033 +        }
10034 +        break;
10035 +    case pb_range:
10036 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
10037 +        {
10038 +            t.dst.u.udp.port = htons(loport);
10039 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10040 +            {
10041 +                hiport = loport + ~exp->mask.dst.u.udp.port;
10042 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
10043 +                break;
10044 +            }
10045 +        }
10046 +        if (loport != 0)
10047 +        {
10048 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
10049 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
10050 +        }
10051 +        break;
10052 +    case pb_discon:
10053 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
10054 +        {
10055 +            t.dst.u.udp.port = htons(loport);
10056 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10057 +            {
10058 +                DEBUGP("using port %hu (1 of 2)\n", loport);
10059 +                break;
10060 +            }
10061 +        }
10062 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
10063 +        {
10064 +            t.dst.u.udp.port = htons(hiport);
10065 +            if (ip_conntrack_change_expect(exp, &t) == 0)
10066 +            {
10067 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
10068 +                break;
10069 +            }
10070 +        }
10071 +        if (loport != 0 && hiport != 0)
10072 +        {
10073 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
10074 +            if (hiport == loport+1)
10075 +            {
10076 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
10077 +            }
10078 +            else
10079 +            {
10080 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
10081 +            }
10082 +        }
10083 +        break;
10084 +    default:
10085 +        /* oops */
10086 +    }
10087 +
10088 +    if (rbuf1len == 0)
10089 +    {
10090 +        return 0;   /* cannot get replacement port(s) */
10091 +    }
10092 +
10093 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
10094 +    while (off < tranlen)
10095 +    {
10096 +        uint        saveoff;
10097 +        const char* pparamend;
10098 +        uint        nextparamoff;
10099 +
10100 +        pparamend = memchr(ptran+off, ',', tranlen-off);
10101 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
10102 +        nextparamoff = pparamend-ptcp;
10103 +
10104 +        /*
10105 +         * We pass over each param twice.  On the first pass, we look for a
10106 +         * destination= field.  It is handled by the security policy.  If it
10107 +         * is present, allowed, and equal to our external address, we assume
10108 +         * that STUN is being used and we leave the client_port= field alone.
10109 +         */
10110 +        is_stun = 0;
10111 +        saveoff = off;
10112 +        while (off < nextparamoff)
10113 +        {
10114 +            const char* pfieldend;
10115 +            uint        nextfieldoff;
10116 +
10117 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10118 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10119 +
10120 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
10121 +            {
10122 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
10123 +                {
10124 +                    is_stun = 1;
10125 +                }
10126 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
10127 +                {
10128 +                    diff = nextfieldoff-off;
10129 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10130 +                                                         off, diff, NULL, 0))
10131 +                    {
10132 +                        /* mangle failed, all we can do is bail */
10133 +                        return 0;
10134 +                    }
10135 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10136 +                    ptran = ptcp+tranoff;
10137 +                    tranlen -= diff;
10138 +                    nextparamoff -= diff;
10139 +                    nextfieldoff -= diff;
10140 +                }
10141 +            }
10142 +
10143 +            off = nextfieldoff;
10144 +        }
10145 +        if (is_stun)
10146 +        {
10147 +            continue;
10148 +        }
10149 +        off = saveoff;
10150 +        while (off < nextparamoff)
10151 +        {
10152 +            const char* pfieldend;
10153 +            uint        nextfieldoff;
10154 +
10155 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
10156 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
10157 +
10158 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
10159 +            {
10160 +                u_int16_t   port;
10161 +                uint        numlen;
10162 +                uint        origoff;
10163 +                uint        origlen;
10164 +                char*       rbuf    = rbuf1;
10165 +                uint        rbuflen = rbuf1len;
10166 +
10167 +                off += 12;
10168 +                origoff = (ptran-ptcp)+off;
10169 +                origlen = 0;
10170 +                numlen = nf_strtou16(ptran+off, &port);
10171 +                off += numlen;
10172 +                origlen += numlen;
10173 +                if (port != prtspexp->loport)
10174 +                {
10175 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
10176 +                }
10177 +                else
10178 +                {
10179 +                    if (ptran[off] == '-' || ptran[off] == '/')
10180 +                    {
10181 +                        off++;
10182 +                        origlen++;
10183 +                        numlen = nf_strtou16(ptran+off, &port);
10184 +                        off += numlen;
10185 +                        origlen += numlen;
10186 +                        rbuf = rbufa;
10187 +                        rbuflen = rbufalen;
10188 +                    }
10189 +
10190 +                    /*
10191 +                     * note we cannot just memcpy() if the sizes are the same.
10192 +                     * the mangle function does skb resizing, checks for a
10193 +                     * cloned skb, and updates the checksums.
10194 +                     *
10195 +                     * parameter 4 below is offset from start of tcp data.
10196 +                     */
10197 +                    diff = origlen-rbuflen;
10198 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
10199 +                                              origoff, origlen, rbuf, rbuflen))
10200 +                    {
10201 +                        /* mangle failed, all we can do is bail */
10202 +                        return 0;
10203 +                    }
10204 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10205 +                    ptran = ptcp+tranoff;
10206 +                    tranlen -= diff;
10207 +                    nextparamoff -= diff;
10208 +                    nextfieldoff -= diff;
10209 +                }
10210 +            }
10211 +
10212 +            off = nextfieldoff;
10213 +        }
10214 +
10215 +        off = nextparamoff;
10216 +    }
10217 +
10218 +    return 1;
10219 +}
10220 +
10221 +static unsigned int
10222 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
10223 +{
10224 +    struct ip_nat_multi_range mr;
10225 +    u_int32_t newdstip, newsrcip, newip;
10226 +
10227 +    struct ip_conntrack *master = master_ct(ct);
10228 +
10229 +    IP_NF_ASSERT(info);
10230 +    IP_NF_ASSERT(master);
10231 +
10232 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
10233 +
10234 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10235 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10236 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
10237 +
10238 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
10239 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
10240 +
10241 +    mr.rangesize = 1;
10242 +    /* We don't want to manip the per-protocol, just the IPs. */
10243 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10244 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
10245 +
10246 +    return ip_nat_setup_info(ct, &mr, hooknum);
10247 +}
10248 +
10249 +static uint
10250 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10251 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10252 +{
10253 +    char*   ptcp;
10254 +    uint    tcplen;
10255 +    uint    hdrsoff;
10256 +    uint    hdrslen;
10257 +    uint    lineoff;
10258 +    uint    linelen;
10259 +    uint    off;
10260 +
10261 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
10262 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
10263 +
10264 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
10265 +
10266 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10267 +
10268 +    hdrsoff = exp->seq - ntohl(tcph->seq);
10269 +    hdrslen = prtspexp->len;
10270 +    off = hdrsoff;
10271 +
10272 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
10273 +    {
10274 +        if (linelen == 0)
10275 +        {
10276 +            break;
10277 +        }
10278 +        if (off > hdrsoff+hdrslen)
10279 +        {
10280 +            INFOP("!! overrun !!");
10281 +            break;
10282 +        }
10283 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10284 +
10285 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
10286 +        {
10287 +            uint oldtcplen = tcplen;
10288 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
10289 +            {
10290 +                break;
10291 +            }
10292 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
10293 +            hdrslen -= (oldtcplen-tcplen);
10294 +            off -= (oldtcplen-tcplen);
10295 +            lineoff -= (oldtcplen-tcplen);
10296 +            linelen -= (oldtcplen-tcplen);
10297 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
10298 +        }
10299 +    }
10300 +
10301 +    return NF_ACCEPT;
10302 +}
10303 +
10304 +static uint
10305 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
10306 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
10307 +{
10308 +    /* XXX: unmangle */
10309 +    return NF_ACCEPT;
10310 +}
10311 +
10312 +static uint
10313 +help(struct ip_conntrack* ct,
10314 +     struct ip_conntrack_expect* exp,
10315 +     struct ip_nat_info* info,
10316 +     enum ip_conntrack_info ctinfo,
10317 +     unsigned int hooknum,
10318 +     struct sk_buff** pskb)
10319 +{
10320 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
10321 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
10322 +    uint datalen;
10323 +    int dir;
10324 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
10325 +    int rc = NF_ACCEPT;
10326 +
10327 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
10328 +    {
10329 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
10330 +        return NF_ACCEPT;
10331 +    }
10332 +
10333 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
10334 +
10335 +    /*
10336 +     * Only mangle things once: original direction in POST_ROUTING
10337 +     * and reply direction on PRE_ROUTING.
10338 +     */
10339 +    dir = CTINFO2DIR(ctinfo);
10340 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10341 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
10342 +    {
10343 +        DEBUGP("Not touching dir %s at hook %s\n",
10344 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10345 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10346 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10347 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10348 +        return NF_ACCEPT;
10349 +    }
10350 +    DEBUGP("got beyond not touching\n");
10351 +
10352 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
10353 +
10354 +    LOCK_BH(&ip_rtsp_lock);
10355 +    /* Ensure the packet contains all of the marked data */
10356 +    if (!between(exp->seq + ct_rtsp_info->len,
10357 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
10358 +    {
10359 +        /* Partial retransmission?  Probably a hacker. */
10360 +        if (net_ratelimit())
10361 +        {
10362 +            INFOP("partial packet %u/%u in %u/%u\n",
10363 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
10364 +        }
10365 +        UNLOCK_BH(&ip_rtsp_lock);
10366 +        return NF_DROP;
10367 +    }
10368 +
10369 +    switch (dir)
10370 +    {
10371 +    case IP_CT_DIR_ORIGINAL:
10372 +        rc = help_out(ct, ctinfo, exp, pskb);
10373 +        break;
10374 +    case IP_CT_DIR_REPLY:
10375 +        rc = help_in(ct, ctinfo, exp, pskb);
10376 +        break;
10377 +    default:
10378 +        /* oops */
10379 +    }
10380 +    UNLOCK_BH(&ip_rtsp_lock);
10381 +
10382 +    return rc;
10383 +}
10384 +
10385 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
10386 +static char rtsp_names[MAX_PORTS][10];
10387 +
10388 +/* This function is intentionally _NOT_ defined as  __exit */
10389 +static void
10390 +fini(void)
10391 +{
10392 +    int i;
10393 +
10394 +    for (i = 0; i < num_ports; i++)
10395 +    {
10396 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
10397 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
10398 +    }
10399 +}
10400 +
10401 +static int __init
10402 +init(void)
10403 +{
10404 +    int ret = 0;
10405 +    int i;
10406 +    struct ip_nat_helper* hlpr;
10407 +    char* tmpname;
10408 +
10409 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
10410 +
10411 +    if (ports[0] == 0)
10412 +    {
10413 +        ports[0] = RTSP_PORT;
10414 +    }
10415 +
10416 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
10417 +    {
10418 +        hlpr = &ip_nat_rtsp_helpers[i];
10419 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
10420 +
10421 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
10422 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
10423 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
10424 +        hlpr->mask.dst.protonum = 0xFFFF;
10425 +        hlpr->help = help;
10426 +        hlpr->flags = 0;
10427 +        hlpr->me = THIS_MODULE;
10428 +        hlpr->expect = expected;
10429 +
10430 +        tmpname = &rtsp_names[i][0];
10431 +        if (ports[i] == RTSP_PORT)
10432 +        {
10433 +                sprintf(tmpname, "rtsp");
10434 +        }
10435 +        else
10436 +        {
10437 +                sprintf(tmpname, "rtsp-%d", i);
10438 +        }
10439 +        hlpr->name = tmpname;
10440 +
10441 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
10442 +        ret = ip_nat_helper_register(hlpr);
10443 +
10444 +        if (ret)
10445 +        {
10446 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
10447 +            fini();
10448 +            return 1;
10449 +        }
10450 +        num_ports++;
10451 +    }
10452 +    if (stunaddr != NULL)
10453 +    {
10454 +        extip = in_aton(stunaddr);
10455 +    }
10456 +    if (destaction != NULL)
10457 +    {
10458 +        if (strcmp(destaction, "auto") == 0)
10459 +        {
10460 +            dstact = DSTACT_AUTO;
10461 +        }
10462 +        if (strcmp(destaction, "strip") == 0)
10463 +        {
10464 +            dstact = DSTACT_STRIP;
10465 +        }
10466 +        if (strcmp(destaction, "none") == 0)
10467 +        {
10468 +            dstact = DSTACT_NONE;
10469 +        }
10470 +    }
10471 +    return ret;
10472 +}
10473 +
10474 +module_init(init);
10475 +module_exit(fini);
10476 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
10477 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_rule.c     2003-11-26 21:43:38.000000000 +0100
10478 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_rule.c 2003-12-11 10:23:17.227319024 +0100
10479 @@ -67,7 +67,7 @@
10480                 0,
10481                 sizeof(struct ipt_entry),
10482                 sizeof(struct ipt_standard),
10483 -               0, { 0, 0 }, { } },
10484 +               0, NULL, 0, { 0, 0 }, { } },
10485               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10486                 -NF_ACCEPT - 1 } },
10487             /* POST_ROUTING */
10488 @@ -75,7 +75,7 @@
10489                 0,
10490                 sizeof(struct ipt_entry),
10491                 sizeof(struct ipt_standard),
10492 -               0, { 0, 0 }, { } },
10493 +               0, NULL, 0, { 0, 0 }, { } },
10494               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10495                 -NF_ACCEPT - 1 } },
10496             /* LOCAL_OUT */
10497 @@ -83,7 +83,7 @@
10498                 0,
10499                 sizeof(struct ipt_entry),
10500                 sizeof(struct ipt_standard),
10501 -               0, { 0, 0 }, { } },
10502 +               0, NULL, 0, { 0, 0 }, { } },
10503               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
10504                 -NF_ACCEPT - 1 } }
10505      },
10506 @@ -92,7 +92,7 @@
10507         0,
10508         sizeof(struct ipt_entry),
10509         sizeof(struct ipt_error),
10510 -       0, { 0, 0 }, { } },
10511 +       0, NULL, 0, { 0, 0 }, { } },
10512        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
10513           { } },
10514         "ERROR"
10515 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
10516 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_standalone.c       2003-11-26 21:45:10.000000000 +0100
10517 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_standalone.c   2003-12-11 10:23:57.173246320 +0100
10518 @@ -260,7 +260,13 @@
10519  };
10520  #endif
10521  
10522 -/* Protocol registration. */
10523 +/**
10524 + * ip_nat_protocol_register - Register a layer 4 protocol helper
10525 + * @proto: structure describing this helper
10526 + * 
10527 + * This function is called by NAT layer 4 protocol helpers to register
10528 + * themselvers with the NAT core.
10529 + */
10530  int ip_nat_protocol_register(struct ip_nat_protocol *proto)
10531  {
10532         int ret = 0;
10533 @@ -281,9 +287,16 @@
10534         return ret;
10535  }
10536  
10537 -/* Noone stores the protocol anywhere; simply delete it. */
10538 +/**
10539 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
10540 + * @proto: sturcture describing the helper
10541 + *
10542 + * This function is called by NAT layer 4 protocol helpers to
10543 + * unregister themselves from the NAT core.
10544 + */
10545  void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
10546  {
10547 +       /* Noone stores the protocol anywhere; simply delete it. */
10548         WRITE_LOCK(&ip_nat_lock);
10549         LIST_DELETE(&protos, proto);
10550         WRITE_UNLOCK(&ip_nat_lock);
10551 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
10552 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_talk.c     1970-01-01 01:00:00.000000000 +0100
10553 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_talk.c 2003-12-11 10:24:09.250410312 +0100
10554 @@ -0,0 +1,473 @@
10555 +/* 
10556 + * talk extension for UDP NAT alteration. 
10557 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10558 + *
10559 + *      This program is free software; you can redistribute it and/or
10560 + *      modify it under the terms of the GNU General Public License
10561 + *      as published by the Free Software Foundation; either version
10562 + *      2 of the License, or (at your option) any later version.
10563 + **
10564 + *     Module load syntax:
10565 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
10566 + *
10567 + *             talk=[0|1]      disable|enable old talk support
10568 + *            ntalk=[0|1]      disable|enable ntalk support
10569 + *           ntalk2=[0|1]      disable|enable ntalk2 support
10570 + *
10571 + *     The default is talk=1 ntalk=1 ntalk2=1
10572 + *
10573 + *  
10574 + */
10575 +#include <linux/module.h>
10576 +#include <linux/netfilter_ipv4.h>
10577 +#include <linux/ip.h>
10578 +#include <linux/udp.h>
10579 +#include <linux/kernel.h>
10580 +#include <net/tcp.h>
10581 +#include <net/udp.h>
10582 +
10583 +#include <linux/netfilter_ipv4/ip_nat.h>
10584 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
10585 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
10586 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
10587 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
10588 +
10589 +/* Default all talk protocols are supported */
10590 +static int talk   = 1;
10591 +static int ntalk  = 1;
10592 +static int ntalk2 = 1;
10593 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
10594 +MODULE_DESCRIPTION("talk network address translation module");
10595 +#ifdef MODULE_PARM
10596 +MODULE_PARM(talk, "i");
10597 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
10598 +MODULE_PARM(ntalk, "i");
10599 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
10600 +MODULE_PARM(ntalk2, "i");
10601 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
10602 +#endif
10603 +
10604 +#if 0
10605 +#define DEBUGP printk
10606 +#define IP_NAT_TALK_DEBUG
10607 +#else
10608 +#define DEBUGP(format, args...)
10609 +#endif
10610 +
10611 +/* FIXME: Time out? --RR */
10612 +
10613 +static int
10614 +mangle_packet(struct sk_buff **pskb,
10615 +             struct ip_conntrack *ct,
10616 +             u_int32_t newip,
10617 +             u_int16_t port,
10618 +             struct talk_addr *addr,
10619 +             struct talk_addr *ctl_addr)
10620 +{
10621 +       struct iphdr *iph = (*pskb)->nh.iph;
10622 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
10623 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
10624 +
10625 +       /* Fortunately talk sends a structure with the address and
10626 +          port in it. The size of the packet won't change. */
10627 +
10628 +       if (ctl_addr == NULL) {
10629 +               /* response */
10630 +               if (addr->ta_addr == INADDR_ANY)
10631 +                       return 1;
10632 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
10633 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10634 +                      NIPQUAD(newip), ntohs(port));
10635 +               addr->ta_addr = newip;
10636 +               addr->ta_port = port;
10637 +       } else {
10638 +               /* message */
10639 +               if (addr->ta_addr != INADDR_ANY) {
10640 +                       /* Change address inside packet to match way we're mapping
10641 +                          this connection. */
10642 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
10643 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10644 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
10645 +                              ntohs(addr->ta_port));
10646 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10647 +               }
10648 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
10649 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10650 +                      NIPQUAD(newip), ntohs(port));
10651 +               ctl_addr->ta_addr = newip;
10652 +               ctl_addr->ta_port = port;
10653 +       }
10654 +
10655 +       /* Fix checksums */
10656 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
10657 +       udph->check = 0;
10658 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
10659 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
10660 +               
10661 +       ip_send_check(iph);
10662 +       return 1;
10663 +}
10664 +
10665 +static int talk_help_msg(struct ip_conntrack *ct,
10666 +                        struct sk_buff **pskb,
10667 +                        u_char type,
10668 +                        struct talk_addr *addr,
10669 +                        struct talk_addr *ctl_addr)
10670 +{
10671 +       u_int32_t newip;
10672 +       u_int16_t port;
10673 +       
10674 +       unsigned int verdict = NF_ACCEPT;
10675 +
10676 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
10677 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10678 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
10679 +               type);
10680 +
10681 +       /* Change address inside packet to match way we're mapping
10682 +          this connection. */
10683 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10684 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
10685 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
10686 +               NIPQUAD(newip), ntohs(port));
10687 +
10688 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
10689 +               verdict = NF_DROP;
10690 +
10691 +       return verdict;
10692 +}
10693 +
10694 +static int talk_help_response(struct ip_conntrack *ct,
10695 +                             struct ip_conntrack_expect *exp,
10696 +                             struct sk_buff **pskb,
10697 +                             u_char type,
10698 +                             u_char answer,
10699 +                             struct talk_addr *addr)
10700 +{
10701 +       u_int32_t newip;
10702 +       u_int16_t port;
10703 +       struct ip_conntrack_tuple t;
10704 +       struct ip_ct_talk_expect *ct_talk_info;
10705 +
10706 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
10707 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10708 +               type, answer);
10709 +       
10710 +       LOCK_BH(&ip_talk_lock);
10711 +       ct_talk_info = &exp->help.exp_talk_info;
10712 +
10713 +       if (!(answer == SUCCESS 
10714 +             && (type == LOOK_UP || type == ANNOUNCE)
10715 +             && exp != NULL)) {
10716 +               UNLOCK_BH(&ip_talk_lock);
10717 +               return NF_ACCEPT;
10718 +       }
10719 +               
10720 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
10721 +               ntohs(ct_talk_info->port), 
10722 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
10723 +
10724 +       /* Change address inside packet to match way we're mapping
10725 +          this connection. */
10726 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
10727 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
10728 +       /* We can read expect here without conntrack lock, since it's
10729 +          only set in ip_conntrack_talk , with ip_talk_lock held
10730 +          writable */ 
10731 +       t = exp->tuple;
10732 +       t.dst.ip = newip;
10733 +
10734 +       /* Try to get same port: if not, try to change it. */
10735 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
10736 +               if (type == LOOK_UP)
10737 +                       t.dst.u.tcp.port = htons(port);
10738 +               else
10739 +                       t.dst.u.udp.port = htons(port);
10740 +
10741 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
10742 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
10743 +                       break;
10744 +               }
10745 +       }
10746 +       UNLOCK_BH(&ip_talk_lock);
10747 +
10748 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
10749 +               return NF_DROP;
10750 +       
10751 +       return NF_ACCEPT;
10752 +}
10753 +
10754 +static unsigned int talk_help(struct ip_conntrack *ct,
10755 +                             struct ip_conntrack_expect *exp,
10756 +                             struct ip_nat_info *info,
10757 +                             enum ip_conntrack_info ctinfo,
10758 +                             unsigned int hooknum,
10759 +                             struct sk_buff **pskb,
10760 +                             int talk_port)
10761 +{
10762 +       struct iphdr *iph = (*pskb)->nh.iph;
10763 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
10764 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
10765 +       char *data = (char *)udph + sizeof(struct udphdr);
10766 +       int dir;
10767 +
10768 +       /* Only mangle things once: original direction in POST_ROUTING
10769 +          and reply direction on PRE_ROUTING. */
10770 +       dir = CTINFO2DIR(ctinfo);
10771 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10772 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
10773 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
10774 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10775 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10776 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10777 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
10778 +               return NF_ACCEPT;
10779 +       }
10780 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
10781 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10782 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10783 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10784 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10785 +              NIPQUAD(iph->saddr), ntohs(udph->source),
10786 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
10787 +              talk_port);
10788 +
10789 +       /* Because conntrack does not drop packets, checking must be repeated here... */
10790 +       if (talk_port == TALK_PORT) {
10791 +               if (dir == IP_CT_DIR_ORIGINAL
10792 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
10793 +                       return talk_help_msg(ct, pskb,
10794 +                                            ((struct talk_msg *)data)->type, 
10795 +                                            &(((struct talk_msg *)data)->addr),
10796 +                                            &(((struct talk_msg *)data)->ctl_addr));
10797 +               else if (dir == IP_CT_DIR_REPLY
10798 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
10799 +                       return talk_help_response(ct, exp, pskb,
10800 +                                                 ((struct talk_response *)data)->type, 
10801 +                                                 ((struct talk_response *)data)->answer,
10802 +                                                 &(((struct talk_response *)data)->addr));
10803 +               else {  
10804 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
10805 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
10806 +                              (unsigned)udplen - sizeof(struct udphdr), 
10807 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
10808 +                       return NF_DROP;
10809 +               }
10810 +       } else {
10811 +               if (dir == IP_CT_DIR_ORIGINAL) {
10812 +                       if (ntalk
10813 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
10814 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
10815 +                               return talk_help_msg(ct, pskb,
10816 +                                                    ((struct ntalk_msg *)data)->type, 
10817 +                                                    &(((struct ntalk_msg *)data)->addr),
10818 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
10819 +                       else if (ntalk2
10820 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
10821 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
10822 +                                && udplen == sizeof(struct udphdr) 
10823 +                                             + sizeof(struct ntalk2_msg) 
10824 +                                             + ((struct ntalk2_msg *)data)->extended)
10825 +                               return talk_help_msg(ct, pskb,
10826 +                                                    ((struct ntalk2_msg *)data)->type, 
10827 +                                                    &(((struct ntalk2_msg *)data)->addr),
10828 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
10829 +                       else {
10830 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
10831 +                                      (unsigned)udplen - sizeof(struct udphdr), 
10832 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
10833 +                               return NF_DROP;
10834 +                       }
10835 +               } else {
10836 +                       if (ntalk
10837 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
10838 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
10839 +                               return talk_help_response(ct, exp, pskb,
10840 +                                                         ((struct ntalk_response *)data)->type, 
10841 +                                                         ((struct ntalk_response *)data)->answer,
10842 +                                                         &(((struct ntalk_response *)data)->addr));
10843 +                       else if (ntalk2
10844 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
10845 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
10846 +                               return talk_help_response(ct, exp, pskb,
10847 +                                                         ((struct ntalk2_response *)data)->type, 
10848 +                                                         ((struct ntalk2_response *)data)->answer,
10849 +                                                         &(((struct ntalk2_response *)data)->addr));
10850 +                       else {
10851 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
10852 +                                      (unsigned)udplen - sizeof(struct udphdr), 
10853 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
10854 +                               return NF_DROP;
10855 +                       }
10856 +               }
10857 +       }
10858 +}
10859 +
10860 +static unsigned int help(struct ip_conntrack *ct,
10861 +                        struct ip_conntrack_expect *exp,
10862 +                        struct ip_nat_info *info,
10863 +                        enum ip_conntrack_info ctinfo,
10864 +                        unsigned int hooknum,
10865 +                        struct sk_buff **pskb)
10866 +{
10867 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
10868 +}
10869 +
10870 +static unsigned int nhelp(struct ip_conntrack *ct,
10871 +                         struct ip_conntrack_expect *exp,
10872 +                         struct ip_nat_info *info,
10873 +                         enum ip_conntrack_info ctinfo,
10874 +                         unsigned int hooknum,
10875 +                         struct sk_buff **pskb)
10876 +{
10877 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
10878 +}
10879 +
10880 +static unsigned int
10881 +talk_nat_expected(struct sk_buff **pskb,
10882 +                 unsigned int hooknum,
10883 +                 struct ip_conntrack *ct,
10884 +                 struct ip_nat_info *info);
10885 +
10886 +static struct ip_nat_helper talk_helpers[2] = 
10887 +       { { { NULL, NULL },
10888 +            "talk",                                    /* name */
10889 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
10890 +            THIS_MODULE,                               /* module */
10891 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
10892 +              { 0, { 0 }, IPPROTO_UDP } },
10893 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
10894 +              { 0, { 0 }, 0xFFFF } },
10895 +            help,                                      /* helper */
10896 +            talk_nat_expected },                       /* expectfn */
10897 +         { { NULL, NULL },
10898 +            "ntalk",                                   /* name */
10899 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
10900 +            THIS_MODULE,                                       /* module */
10901 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
10902 +              { 0, { 0 }, IPPROTO_UDP } },
10903 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
10904 +              { 0, { 0 }, 0xFFFF } },
10905 +            nhelp,                                     /* helper */
10906 +            talk_nat_expected }                                /* expectfn */
10907 +       };
10908 +          
10909 +static unsigned int
10910 +talk_nat_expected(struct sk_buff **pskb,
10911 +                 unsigned int hooknum,
10912 +                 struct ip_conntrack *ct,
10913 +                 struct ip_nat_info *info)
10914 +{
10915 +       struct ip_nat_multi_range mr;
10916 +       u_int32_t newdstip, newsrcip, newip;
10917 +       u_int16_t port;
10918 +       unsigned int ret;
10919 +       
10920 +       struct ip_conntrack *master = master_ct(ct);
10921 +
10922 +       IP_NF_ASSERT(info);
10923 +       IP_NF_ASSERT(master);
10924 +
10925 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
10926 +
10927 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
10928 +
10929 +       LOCK_BH(&ip_talk_lock);
10930 +       port = ct->master->help.exp_talk_info.port;
10931 +       UNLOCK_BH(&ip_talk_lock);
10932 +
10933 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
10934 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10935 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10936 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10937 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
10938 +              ct, master);
10939 +
10940 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10941 +               /* Callee client -> caller server */
10942 +#ifdef IP_NAT_TALK_DEBUG
10943 +               struct iphdr *iph = (*pskb)->nh.iph;
10944 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
10945 +
10946 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10947 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
10948 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
10949 +#endif
10950 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10951 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
10952 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10953 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
10954 +       } else {
10955 +               /* Callee client -> caller client */
10956 +#ifdef IP_NAT_TALK_DEBUG
10957 +               struct iphdr *iph = (*pskb)->nh.iph;
10958 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
10959 +
10960 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10961 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
10962 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
10963 +#endif
10964 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
10965 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10966 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
10967 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
10968 +       }
10969 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
10970 +               newip = newsrcip;
10971 +       else
10972 +               newip = newdstip;
10973 +
10974 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
10975 +
10976 +       mr.rangesize = 1;
10977 +       /* We don't want to manip the per-protocol, just the IPs... */
10978 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10979 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
10980 +       
10981 +       /* ... unless we're doing a MANIP_DST, in which case, make
10982 +          sure we map to the correct port */
10983 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
10984 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
10985 +               mr.range[0].min = mr.range[0].max
10986 +                       = ((union ip_conntrack_manip_proto)
10987 +                               { .udp = { port } });
10988 +       }
10989 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
10990 +
10991 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
10992 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
10993 +               /* NAT expectfn called with ip_nat_lock write-locked */
10994 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
10995 +       }
10996 +       return ret;
10997 +}
10998 +
10999 +static int __init init(void)
11000 +{
11001 +       int ret = 0;
11002 +
11003 +       if (talk > 0) {
11004 +               ret = ip_nat_helper_register(&talk_helpers[0]);
11005 +
11006 +               if (ret != 0)
11007 +                       return ret;
11008 +       }
11009 +       if (ntalk > 0 || ntalk2 > 0) {
11010 +               ret = ip_nat_helper_register(&talk_helpers[1]);
11011 +
11012 +               if (ret != 0 && talk > 0)
11013 +                       ip_nat_helper_unregister(&talk_helpers[0]);
11014 +       }
11015 +       return ret;
11016 +}
11017 +
11018 +static void __exit fini(void)
11019 +{
11020 +       if (talk > 0)
11021 +               ip_nat_helper_unregister(&talk_helpers[0]);
11022 +       if (ntalk > 0 || ntalk2 > 0)
11023 +               ip_nat_helper_unregister(&talk_helpers[1]);
11024 +}
11025 +
11026 +module_init(init);
11027 +module_exit(fini);
11028 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
11029 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_nat_tftp.c     2003-11-26 21:43:31.000000000 +0100
11030 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_nat_tftp.c 2003-12-11 10:23:13.893825792 +0100
11031 @@ -164,8 +164,6 @@
11032                 ports[0] = TFTP_PORT;
11033  
11034         for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
11035 -               memset(&tftp[i], 0, sizeof(struct ip_nat_helper));
11036 -
11037                 tftp[i].tuple.dst.protonum = IPPROTO_UDP;
11038                 tftp[i].tuple.src.u.udp.port = htons(ports[i]);
11039                 tftp[i].mask.dst.protonum = 0xFFFF;
11040 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
11041 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
11042 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_pool.c     2003-12-11 10:23:32.944929584 +0100
11043 @@ -0,0 +1,332 @@
11044 +/* Kernel module for IP pool management */
11045 +
11046 +#include <linux/module.h>
11047 +#include <linux/ip.h>
11048 +#include <linux/skbuff.h>
11049 +#include <linux/netfilter_ipv4/ip_tables.h>
11050 +#include <linux/netfilter_ipv4/ip_pool.h>
11051 +#include <linux/errno.h>
11052 +#include <asm/uaccess.h>
11053 +#include <asm/bitops.h>
11054 +#include <linux/interrupt.h>
11055 +#include <linux/spinlock.h>
11056 +
11057 +#if 0
11058 +#define DP printk
11059 +#else
11060 +#define DP(format, args...)
11061 +#endif
11062 +
11063 +MODULE_LICENSE("GPL");
11064 +
11065 +#define NR_POOL 16
11066 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
11067 +
11068 +struct ip_pool {
11069 +       u_int32_t first_ip;     /* host byte order, included in range */
11070 +       u_int32_t last_ip;      /* host byte order, included in range */
11071 +       void *members;          /* the bitmap proper */
11072 +       int nr_use;             /* total nr. of tests through this */
11073 +       int nr_match;           /* total nr. of matches through this */
11074 +       rwlock_t lock;
11075 +};
11076 +
11077 +static struct ip_pool *POOL;
11078 +
11079 +static inline struct ip_pool *lookup(ip_pool_t index)
11080 +{
11081 +       if (index < 0 || index >= nr_pool) {
11082 +               DP("ip_pool:lookup: bad index %d\n", index);
11083 +               return 0;
11084 +       }
11085 +       return POOL+index;
11086 +}
11087 +
11088 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
11089 +{
11090 +        struct ip_pool *pool = lookup(index);
11091 +       int res = 0;
11092 +
11093 +       if (!pool || !pool->members)
11094 +               return 0;
11095 +       read_lock_bh(&pool->lock);
11096 +       if (pool->members) {
11097 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
11098 +                       addr -= pool->first_ip;
11099 +                       if (test_bit(addr, pool->members)) {
11100 +                               res = 1;
11101 +#ifdef CONFIG_IP_POOL_STATISTICS
11102 +                               pool->nr_match++;
11103 +#endif
11104 +                       }
11105 +               }
11106 +#ifdef CONFIG_IP_POOL_STATISTICS
11107 +               pool->nr_use++;
11108 +#endif
11109 +       }
11110 +       read_unlock_bh(&pool->lock);
11111 +       return res;
11112 +}
11113 +
11114 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
11115 +{
11116 +       struct ip_pool *pool;
11117 +       int res = -1;
11118 +
11119 +       pool = lookup(index);
11120 +       if (    !pool || !pool->members
11121 +            || addr < pool->first_ip || addr > pool->last_ip)
11122 +               return -1;
11123 +       read_lock_bh(&pool->lock);
11124 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
11125 +               addr -= pool->first_ip;
11126 +               res = isdel
11127 +                       ? (0 != test_and_clear_bit(addr, pool->members))
11128 +                       : (0 != test_and_set_bit(addr, pool->members));
11129 +       }
11130 +       read_unlock_bh(&pool->lock);
11131 +       return res;
11132 +}
11133 +
11134 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
11135 +{
11136 +       int res = pool_change(index,addr,isdel);
11137 +
11138 +       if (!isdel) res = !res;
11139 +       return res;
11140 +}
11141 +
11142 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
11143 +{
11144 +       return 4*((((b-a+8)/8)+3)/4);
11145 +}
11146 +
11147 +static inline int poolbytes(ip_pool_t index)
11148 +{
11149 +       struct ip_pool *pool = lookup(index);
11150 +
11151 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
11152 +}
11153 +
11154 +static int setpool(
11155 +       struct sock *sk,
11156 +       int optval,
11157 +       void *user,
11158 +       unsigned int len
11159 +) {
11160 +       struct ip_pool_request req;
11161 +
11162 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
11163 +       if (!capable(CAP_NET_ADMIN))
11164 +               return -EPERM;
11165 +       if (optval != SO_IP_POOL)
11166 +               return -EBADF;
11167 +       if (len != sizeof(req))
11168 +               return -EINVAL;
11169 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
11170 +               return -EFAULT;
11171 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
11172 +       return -EINVAL;
11173 +}
11174 +
11175 +static int getpool(
11176 +       struct sock *sk,
11177 +       int optval,
11178 +       void *user,
11179 +       int *len
11180 +) {
11181 +       struct ip_pool_request req;
11182 +       struct ip_pool *pool;
11183 +       ip_pool_t i;
11184 +       int newbytes;
11185 +       void *newmembers;
11186 +       int res;
11187 +
11188 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
11189 +       if (!capable(CAP_NET_ADMIN))
11190 +               return -EINVAL;
11191 +       if (optval != SO_IP_POOL)
11192 +               return -EINVAL;
11193 +       if (*len != sizeof(req)) {
11194 +               return -EFAULT;
11195 +       }
11196 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
11197 +               return -EFAULT;
11198 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
11199 +       if (req.op < IP_POOL_BAD001) {
11200 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
11201 +               return -EFAULT;
11202 +       }
11203 +       switch(req.op) {
11204 +       case IP_POOL_HIGH_NR:
11205 +               DP("ip_pool HIGH_NR\n");
11206 +               req.index = IP_POOL_NONE;
11207 +               for (i=0; i<nr_pool; i++)
11208 +                       if (POOL[i].members)
11209 +                               req.index = i;
11210 +               return copy_to_user(user, &req, sizeof(req));
11211 +       case IP_POOL_LOOKUP:
11212 +               DP("ip_pool LOOKUP\n");
11213 +               pool = lookup(req.index);
11214 +               if (!pool)
11215 +                       return -EINVAL;
11216 +               if (!pool->members)
11217 +                       return -EBADF;
11218 +               req.addr = htonl(pool->first_ip);
11219 +               req.addr2 = htonl(pool->last_ip);
11220 +               return copy_to_user(user, &req, sizeof(req));
11221 +       case IP_POOL_USAGE:
11222 +               DP("ip_pool USE\n");
11223 +               pool = lookup(req.index);
11224 +               if (!pool)
11225 +                       return -EINVAL;
11226 +               if (!pool->members)
11227 +                       return -EBADF;
11228 +               req.addr = pool->nr_use;
11229 +               req.addr2 = pool->nr_match;
11230 +               return copy_to_user(user, &req, sizeof(req));
11231 +       case IP_POOL_TEST_ADDR:
11232 +               DP("ip_pool TEST 0x%08x\n", req.addr);
11233 +               pool = lookup(req.index);
11234 +               if (!pool)
11235 +                       return -EINVAL;
11236 +               res = 0;
11237 +               read_lock_bh(&pool->lock);
11238 +               if (!pool->members) {
11239 +                       DP("ip_pool TEST_ADDR no members in pool\n");
11240 +                       res = -EBADF;
11241 +                       goto unlock_and_return_res;
11242 +               }
11243 +               req.addr = ntohl(req.addr);
11244 +               if (req.addr < pool->first_ip) {
11245 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
11246 +                       res = -ERANGE;
11247 +                       goto unlock_and_return_res;
11248 +               }
11249 +               if (req.addr > pool->last_ip) {
11250 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
11251 +                       res = -ERANGE;
11252 +                       goto unlock_and_return_res;
11253 +               }
11254 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
11255 +                                       pool->members));
11256 +               read_unlock_bh(&pool->lock);
11257 +               return copy_to_user(user, &req, sizeof(req));
11258 +       case IP_POOL_FLUSH:
11259 +               DP("ip_pool FLUSH not yet implemented.\n");
11260 +               return -EBUSY;
11261 +       case IP_POOL_DESTROY:
11262 +               DP("ip_pool DESTROY not yet implemented.\n");
11263 +               return -EBUSY;
11264 +       case IP_POOL_INIT:
11265 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
11266 +               pool = lookup(req.index);
11267 +               if (!pool)
11268 +                       return -EINVAL;
11269 +               req.addr = ntohl(req.addr);
11270 +               req.addr2 = ntohl(req.addr2);
11271 +               if (req.addr > req.addr2) {
11272 +                       DP("ip_pool INIT bad ip range\n");
11273 +                       return -EINVAL;
11274 +               }
11275 +               newbytes = bitmap_bytes(req.addr, req.addr2);
11276 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
11277 +               if (!newmembers) {
11278 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
11279 +                       return -ENOMEM;
11280 +               }
11281 +               memset(newmembers, 0, newbytes);
11282 +               write_lock_bh(&pool->lock);
11283 +               if (pool->members) {
11284 +                       DP("ip_pool INIT pool %d exists\n", req.index);
11285 +                       kfree(newmembers);
11286 +                       res = -EBUSY;
11287 +                       goto unlock_and_return_res;
11288 +               }
11289 +               pool->first_ip = req.addr;
11290 +               pool->last_ip = req.addr2;
11291 +               pool->nr_use = 0;
11292 +               pool->nr_match = 0;
11293 +               pool->members = newmembers;
11294 +               write_unlock_bh(&pool->lock);
11295 +               return 0;
11296 +       case IP_POOL_ADD_ADDR:
11297 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
11298 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
11299 +               return copy_to_user(user, &req, sizeof(req));
11300 +       case IP_POOL_DEL_ADDR:
11301 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
11302 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
11303 +               return copy_to_user(user, &req, sizeof(req));
11304 +       default:
11305 +               DP("ip_pool:getpool bad op %d\n", req.op);
11306 +               return -EINVAL;
11307 +       }
11308 +       return -EINVAL;
11309 +
11310 +unlock_and_return_res:
11311 +       if (pool)
11312 +               read_unlock_bh(&pool->lock);
11313 +       return res;
11314 +}
11315 +
11316 +static struct nf_sockopt_ops so_pool
11317 += { { NULL, NULL }, PF_INET,
11318 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
11319 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
11320 +    0, NULL };
11321 +
11322 +MODULE_PARM(nr_pool, "i");
11323 +
11324 +static int __init init(void)
11325 +{
11326 +       ip_pool_t i;
11327 +       int res;
11328 +
11329 +       if (nr_pool < 1) {
11330 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
11331 +               return -EINVAL;
11332 +       }
11333 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
11334 +       if (!POOL) {
11335 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
11336 +                       nr_pool);
11337 +               return -ENOMEM;
11338 +       }
11339 +       for (i=0; i<nr_pool; i++) {
11340 +               POOL[i].first_ip = 0;
11341 +               POOL[i].last_ip = 0;
11342 +               POOL[i].members = 0;
11343 +               POOL[i].nr_use = 0;
11344 +               POOL[i].nr_match = 0;
11345 +               POOL[i].lock = RW_LOCK_UNLOCKED;
11346 +       }
11347 +       res = nf_register_sockopt(&so_pool);
11348 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
11349 +       if (res != 0) {
11350 +               kfree(POOL);
11351 +               POOL = 0;
11352 +       }
11353 +       return res;
11354 +}
11355 +
11356 +static void __exit fini(void)
11357 +{
11358 +       ip_pool_t i;
11359 +
11360 +       DP("ip_pool:fini BYEBYE\n");
11361 +       nf_unregister_sockopt(&so_pool);
11362 +       for (i=0; i<nr_pool; i++) {
11363 +               if (POOL[i].members) {
11364 +                       kfree(POOL[i].members);
11365 +                       POOL[i].members = 0;
11366 +               }
11367 +       }
11368 +       kfree(POOL);
11369 +       POOL = 0;
11370 +       DP("ip_pool:fini these are the famous last words\n");
11371 +       return;
11372 +}
11373 +
11374 +module_init(init);
11375 +module_exit(fini);
11376 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
11377 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_queue.c        2003-11-26 21:46:12.000000000 +0100
11378 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_queue.c    2003-12-11 10:24:12.845863720 +0100
11379 @@ -417,6 +417,33 @@
11380  }
11381  
11382  static int
11383 +ipq_set_vwmark(struct ipq_vwmark_msg *vmsg, unsigned int len)
11384 +{
11385 +       struct ipq_queue_entry *entry;
11386 +
11387 +       if (vmsg->value > NF_MAX_VERDICT)
11388 +               return -EINVAL;
11389 +
11390 +       entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
11391 +       if (entry == NULL)
11392 +               return -ENOENT;
11393 +       else {
11394 +               int verdict = vmsg->value;
11395 +               
11396 +               if (vmsg->data_len && vmsg->data_len == len)
11397 +                       if (ipq_mangle_ipv4((ipq_verdict_msg_t *)vmsg, entry) < 0)
11398 +                               verdict = NF_DROP;
11399 +
11400 +               /* set mark of associated skb */
11401 +               entry->skb->nfmark = vmsg->nfmark;
11402 +               
11403 +               ipq_issue_verdict(entry, verdict);
11404 +               return 0;
11405 +       }
11406 +}
11407 +
11408 +
11409 +static int
11410  ipq_receive_peer(struct ipq_peer_msg *pmsg,
11411                   unsigned char type, unsigned int len)
11412  {
11413 @@ -438,6 +465,14 @@
11414                         status = ipq_set_verdict(&pmsg->msg.verdict,
11415                                                  len - sizeof(*pmsg));
11416                         break;
11417 +        case IPQM_VWMARK:
11418 +               if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
11419 +                       status = -EINVAL;
11420 +               else
11421 +                       status = ipq_set_vwmark(&pmsg->msg.vwmark,
11422 +                                                len - sizeof(*pmsg));
11423 +                       break;
11424 +
11425         default:
11426                 status = -EINVAL;
11427         }
11428 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
11429 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_filter.c  2003-11-26 21:43:35.000000000 +0100
11430 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_filter.c      2003-12-11 10:23:17.230318568 +0100
11431 @@ -52,7 +52,7 @@
11432                 0,
11433                 sizeof(struct ipt_entry),
11434                 sizeof(struct ipt_standard),
11435 -               0, { 0, 0 }, { } },
11436 +               0, NULL, 0, { 0, 0 }, { } },
11437               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11438                 -NF_ACCEPT - 1 } },
11439             /* FORWARD */
11440 @@ -60,7 +60,7 @@
11441                 0,
11442                 sizeof(struct ipt_entry),
11443                 sizeof(struct ipt_standard),
11444 -               0, { 0, 0 }, { } },
11445 +               0, NULL, 0, { 0, 0 }, { } },
11446               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11447                 -NF_ACCEPT - 1 } },
11448             /* LOCAL_OUT */
11449 @@ -68,7 +68,7 @@
11450                 0,
11451                 sizeof(struct ipt_entry),
11452                 sizeof(struct ipt_standard),
11453 -               0, { 0, 0 }, { } },
11454 +               0, NULL, 0, { 0, 0 }, { } },
11455               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11456                 -NF_ACCEPT - 1 } }
11457      },
11458 @@ -77,7 +77,7 @@
11459         0,
11460         sizeof(struct ipt_entry),
11461         sizeof(struct ipt_error),
11462 -       0, { 0, 0 }, { } },
11463 +       0, NULL, 0, { 0, 0 }, { } },
11464        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11465           { } },
11466         "ERROR"
11467 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
11468 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_mangle.c  2003-11-26 21:45:28.000000000 +0100
11469 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_mangle.c      2003-12-11 10:23:17.230318568 +0100
11470 @@ -69,7 +69,7 @@
11471                 0,
11472                 sizeof(struct ipt_entry),
11473                 sizeof(struct ipt_standard),
11474 -               0, { 0, 0 }, { } },
11475 +               0, NULL, 0, { 0, 0 }, { } },
11476               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11477                 -NF_ACCEPT - 1 } },
11478             /* LOCAL_IN */
11479 @@ -77,7 +77,7 @@
11480                 0,
11481                 sizeof(struct ipt_entry),
11482                 sizeof(struct ipt_standard),
11483 -               0, { 0, 0 }, { } },
11484 +               0, NULL, 0, { 0, 0 }, { } },
11485               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11486                 -NF_ACCEPT - 1 } },
11487             /* FORWARD */
11488 @@ -85,7 +85,7 @@
11489                 0,
11490                 sizeof(struct ipt_entry),
11491                 sizeof(struct ipt_standard),
11492 -               0, { 0, 0 }, { } },
11493 +               0, NULL, 0, { 0, 0 }, { } },
11494               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11495                 -NF_ACCEPT - 1 } },
11496             /* LOCAL_OUT */
11497 @@ -93,7 +93,7 @@
11498                 0,
11499                 sizeof(struct ipt_entry),
11500                 sizeof(struct ipt_standard),
11501 -               0, { 0, 0 }, { } },
11502 +               0, NULL, 0, { 0, 0 }, { } },
11503               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11504                 -NF_ACCEPT - 1 } },
11505             /* POST_ROUTING */
11506 @@ -101,7 +101,7 @@
11507                 0,
11508                 sizeof(struct ipt_entry),
11509                 sizeof(struct ipt_standard),
11510 -               0, { 0, 0 }, { } },
11511 +               0, NULL, 0, { 0, 0 }, { } },
11512               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11513                 -NF_ACCEPT - 1 } },
11514      },
11515 @@ -110,7 +110,7 @@
11516         0,
11517         sizeof(struct ipt_entry),
11518         sizeof(struct ipt_error),
11519 -       0, { 0, 0 }, { } },
11520 +       0, NULL, 0, { 0, 0 }, { } },
11521        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11522           { } },
11523         "ERROR"
11524 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
11525 --- linux-2.6.0-test11.org/net/ipv4/netfilter/iptable_raw.c     1970-01-01 01:00:00.000000000 +0100
11526 +++ linux-2.6.0-test11/net/ipv4/netfilter/iptable_raw.c 2003-12-11 10:23:17.231318416 +0100
11527 @@ -0,0 +1,153 @@
11528 +/* 
11529 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
11530 + *
11531 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
11532 + */
11533 +#include <linux/module.h>
11534 +#include <linux/netfilter_ipv4/ip_tables.h>
11535 +
11536 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
11537 +
11538 +/* Standard entry. */
11539 +struct ipt_standard
11540 +{
11541 +       struct ipt_entry entry;
11542 +       struct ipt_standard_target target;
11543 +};
11544 +
11545 +struct ipt_error_target
11546 +{
11547 +       struct ipt_entry_target target;
11548 +       char errorname[IPT_FUNCTION_MAXNAMELEN];
11549 +};
11550 +
11551 +struct ipt_error
11552 +{
11553 +       struct ipt_entry entry;
11554 +       struct ipt_error_target target;
11555 +};
11556 +
11557 +static struct
11558 +{
11559 +       struct ipt_replace repl;
11560 +       struct ipt_standard entries[2];
11561 +       struct ipt_error term;
11562 +} initial_table __initdata
11563 += { { "raw", RAW_VALID_HOOKS, 3,
11564 +      sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
11565 +      { [NF_IP_PRE_ROUTING] 0,
11566 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11567 +      { [NF_IP_PRE_ROUTING] 0,
11568 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
11569 +      0, NULL, { } },
11570 +    {
11571 +           /* PRE_ROUTING */
11572 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11573 +               0,
11574 +               sizeof(struct ipt_entry),
11575 +               sizeof(struct ipt_standard),
11576 +               0, NULL, 0, { 0, 0 }, { } },
11577 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11578 +               -NF_ACCEPT - 1 } },
11579 +           /* LOCAL_OUT */
11580 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11581 +               0,
11582 +               sizeof(struct ipt_entry),
11583 +               sizeof(struct ipt_standard),
11584 +               0, NULL, 0, { 0, 0 }, { } },
11585 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11586 +               -NF_ACCEPT - 1 } }
11587 +    },
11588 +    /* ERROR */
11589 +    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
11590 +       0,
11591 +       sizeof(struct ipt_entry),
11592 +       sizeof(struct ipt_error),
11593 +       0, NULL, 0, { 0, 0 }, { } },
11594 +      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11595 +         { } },
11596 +       "ERROR"
11597 +      }
11598 +    }
11599 +};
11600 +
11601 +static struct ipt_table packet_raw = {
11602 +       .name = "raw",
11603 +       .table = &initial_table.repl,
11604 +       .valid_hooks =  RAW_VALID_HOOKS,
11605 +       .lock = RW_LOCK_UNLOCKED,
11606 +       .me = THIS_MODULE,
11607 +};
11608 +
11609 +/* The work comes in here from netfilter.c. */
11610 +static unsigned int
11611 +ipt_hook(unsigned int hook,
11612 +        struct sk_buff **pskb,
11613 +        const struct net_device *in,
11614 +        const struct net_device *out,
11615 +        int (*okfn)(struct sk_buff *))
11616 +{
11617 +       return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
11618 +}
11619 +
11620 +/* 'raw' is the very first table. */
11621 +static struct nf_hook_ops ipt_ops[] = {
11622 +       {       /* PRE_ROUTING hook */
11623 +               .hook           = ipt_hook, 
11624 +               .owner          = THIS_MODULE,
11625 +               .pf             = PF_INET, 
11626 +               .hooknum        = NF_IP_PRE_ROUTING, 
11627 +               .priority       = NF_IP_PRI_RAW,
11628 +       },
11629 +       {       /* LOCAL_OUT hook */
11630 +               .hook           = ipt_hook,
11631 +               .owner          = THIS_MODULE,
11632 +               .pf             = PF_INET,
11633 +               .hooknum        = NF_IP_LOCAL_OUT,
11634 +               .priority       = NF_IP_PRI_RAW,
11635 +       },
11636 +};
11637 +
11638 +static int __init init(void)
11639 +{
11640 +       int ret;
11641 +
11642 +       /* Register table */
11643 +       ret = ipt_register_table(&packet_raw);
11644 +       if (ret < 0)
11645 +               return ret;
11646 +
11647 +       /* Register hooks */
11648 +       ret = nf_register_hook(&ipt_ops[0]);
11649 +       if (ret < 0)
11650 +               goto cleanup_table;
11651 +
11652 +       ret = nf_register_hook(&ipt_ops[1]);
11653 +       if (ret < 0)
11654 +               goto cleanup_hook0;
11655 +
11656 +       return ret;
11657 +
11658 + cleanup_hook0:
11659 +       nf_unregister_hook(&ipt_ops[0]);
11660 + cleanup_table:
11661 +       ipt_unregister_table(&packet_raw);
11662 +
11663 +       return ret;
11664 +}
11665 +
11666 +static void __exit fini(void)
11667 +{
11668 +       unsigned int i;
11669 +
11670 +       for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
11671 +               nf_unregister_hook(&ipt_ops[i]);
11672 +
11673 +       ipt_unregister_table(&packet_raw);
11674 +}
11675 +
11676 +module_init(init);
11677 +module_exit(fini);
11678 +MODULE_LICENSE("GPL");
11679 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11680 +MODULE_DESCRIPTION("IPv4 raw table");
11681 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
11682 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ip_tables.c       2003-11-26 21:43:25.000000000 +0100
11683 +++ linux-2.6.0-test11/net/ipv4/netfilter/ip_tables.c   2003-12-11 10:23:53.624785768 +0100
11684 @@ -4,6 +4,10 @@
11685   * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11686   * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
11687   *
11688 + *  6 Mar 2002 Robert Olsson <robban@robtex.com>
11689 + * 17 Apr 2003 Chris  Wilson <chris@netservers.co.uk>
11690 + *     - mark_source_chains speedup for complex chains
11691 + *
11692   * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
11693   *     - increase module usage count as soon as we have rules inside
11694   *       a table
11695 @@ -11,6 +15,7 @@
11696  #include <linux/config.h>
11697  #include <linux/cache.h>
11698  #include <linux/skbuff.h>
11699 +#include <linux/socket.h>
11700  #include <linux/kmod.h>
11701  #include <linux/vmalloc.h>
11702  #include <linux/netdevice.h>
11703 @@ -23,8 +28,17 @@
11704  #include <asm/semaphore.h>
11705  #include <linux/proc_fs.h>
11706  
11707 +#include <linux/netfilter.h>
11708  #include <linux/netfilter_ipv4/ip_tables.h>
11709  
11710 +static const char *hooknames[] = { 
11711 +       [NF_IP_PRE_ROUTING] "PREROUTING",
11712 +       [NF_IP_LOCAL_IN] "INPUT",
11713 +       [NF_IP_FORWARD] "FORWARD",
11714 +       [NF_IP_LOCAL_OUT] "OUTPUT",
11715 +       [NF_IP_POST_ROUTING] "POSTROUTING",
11716 +};
11717
11718  MODULE_LICENSE("GPL");
11719  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
11720  MODULE_DESCRIPTION("IPv4 packet filter");
11721 @@ -322,6 +336,12 @@
11722  
11723                         t = ipt_get_target(e);
11724                         IP_NF_ASSERT(t->u.kernel.target);
11725 +
11726 +                       /* The packet traced and the rule isn't an unconditional return/END. */
11727 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {       
11728 +                               nf_log_packet(AF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
11729 +                                                table->name, e->chainname, e->rulenum);
11730 +                       }
11731                         /* Standard target? */
11732                         if (!t->u.kernel.target->target) {
11733                                 int v;
11734 @@ -474,6 +494,29 @@
11735         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
11736  }
11737  
11738 +static inline int
11739 +find_error_target(struct ipt_entry *s, 
11740 +                 struct ipt_entry *e,
11741 +                 char **chainname)
11742 +{
11743 +       struct ipt_entry_target *t;
11744 +       static struct ipt_entry *found = NULL;
11745 +
11746 +       if (s == e) {
11747 +               if (!found)
11748 +                       return 0;
11749 +               t = ipt_get_target(found);
11750 +               if (strcmp(t->u.user.name, 
11751 +                          IPT_ERROR_TARGET) == 0) {
11752 +                       *chainname = t->data;
11753 +                       return 1;
11754 +               }
11755 +       } else
11756 +               found = s;
11757 +       
11758 +       return 0;
11759 +}
11760 +
11761  /* All zeroes == unconditional rule. */
11762  static inline int
11763  unconditional(const struct ipt_ip *ip)
11764 @@ -493,6 +536,11 @@
11765  mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
11766  {
11767         unsigned int hook;
11768 +       char *chainname = NULL;
11769 +       u_int32_t rulenum;
11770 +
11771 +       /* keep track of where we have been: */
11772 +       unsigned char *been = vmalloc(newinfo->size);
11773  
11774         /* No recursion; use packet counter to save back ptrs (reset
11775            to 0 as we leave), and comefrom to save source hook bitmask */
11776 @@ -506,6 +554,9 @@
11777  
11778                 /* Set initial back pointer. */
11779                 e->counters.pcnt = pos;
11780 +               memset(been, 0, newinfo->size);
11781 +               rulenum = 1;
11782 +               chainname = (char *) hooknames[hook];
11783  
11784                 for (;;) {
11785                         struct ipt_standard_target *t
11786 @@ -514,10 +565,13 @@
11787                         if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
11788                                 printk("iptables: loop hook %u pos %u %08X.\n",
11789                                        hook, pos, e->comefrom);
11790 +                               vfree(been);
11791                                 return 0;
11792                         }
11793                         e->comefrom
11794                                 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
11795 +                       e->rulenum = rulenum++;
11796 +                       e->chainname = chainname;
11797  
11798                         /* Unconditional return/END. */
11799                         if (e->target_offset == sizeof(struct ipt_entry)
11800 @@ -527,6 +581,10 @@
11801                             && unconditional(&e->ip)) {
11802                                 unsigned int oldpos, size;
11803  
11804 +                               /* Set unconditional rulenum to zero. */
11805 +                               e->rulenum = 0;
11806 +                               e->counters.bcnt = 0;
11807 +
11808                                 /* Return: backtrack through the last
11809                                    big jump. */
11810                                 do {
11811 @@ -552,6 +610,11 @@
11812                                                 (newinfo->entries + pos);
11813                                 } while (oldpos == pos + e->next_offset);
11814  
11815 +                               /* Restore chainname, rulenum. */
11816 +                               chainname = e->chainname;
11817 +                               rulenum = e->counters.bcnt;
11818 +                               e->counters.bcnt = 0;
11819 +
11820                                 /* Move along one */
11821                                 size = e->next_offset;
11822                                 e = (struct ipt_entry *)
11823 @@ -561,12 +624,27 @@
11824                         } else {
11825                                 int newpos = t->verdict;
11826  
11827 -                               if (strcmp(t->target.u.user.name,
11828 +                               if ( (pos < 0 || pos >= newinfo->size
11829 +                                     || !been[pos]) 
11830 +                                   && strcmp(t->target.u.user.name,
11831                                            IPT_STANDARD_TARGET) == 0
11832                                     && newpos >= 0) {
11833                                         /* This a jump; chase it. */
11834 +                                       if (pos >= 0 && pos < newinfo->size)
11835 +                                               been[pos]++;
11836                                         duprintf("Jump rule %u -> %u\n",
11837                                                  pos, newpos);
11838 +                                       e->counters.bcnt = rulenum++;
11839 +                                       rulenum = 1;
11840 +                                       e = (struct ipt_entry *)
11841 +                                               (newinfo->entries + newpos);
11842 +                                       if (IPT_ENTRY_ITERATE(newinfo->entries,
11843 +                                                             newinfo->size,
11844 +                                                             find_error_target,
11845 +                                                             e, &chainname) == 0) {
11846 +                                               printk("ip_tables: table screwed up!\n");
11847 +                                               return 0;
11848 +                                       }
11849                                 } else {
11850                                         /* ... this is a fallthru */
11851                                         newpos = pos + e->next_offset;
11852 @@ -580,6 +658,7 @@
11853                 next:
11854                 duprintf("Finished chain %u\n", hook);
11855         }
11856 +       vfree(been);
11857         return 1;
11858  }
11859  
11860 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
11861 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_addrtype.c    1970-01-01 01:00:00.000000000 +0100
11862 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_addrtype.c        2003-12-11 10:23:44.237212896 +0100
11863 @@ -0,0 +1,65 @@
11864 +/*
11865 + *  iptables module to match inet_addr_type() of an ip.
11866 + */
11867 +
11868 +#include <linux/module.h>
11869 +#include <linux/skbuff.h>
11870 +#include <linux/netdevice.h>
11871 +#include <net/route.h>
11872 +
11873 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
11874 +#include <linux/netfilter_ipv4/ip_tables.h>
11875 +
11876 +MODULE_LICENSE("GPL");
11877 +
11878 +static inline int match_type(u_int32_t addr, u_int16_t mask)
11879 +{
11880 +       return !!(mask & (1 << inet_addr_type(addr)));
11881 +}
11882 +
11883 +static int match(const struct sk_buff *skb, const struct net_device *in,
11884 +                const struct net_device *out, const void *matchinfo,
11885 +                int offset, const void *hdr, u_int16_t datalen,
11886 +                int *hotdrop)
11887 +{
11888 +       const struct ipt_addrtype_info *info = matchinfo;
11889 +       const struct iphdr *iph = skb->nh.iph;
11890 +       int ret = 1;
11891 +
11892 +       if (info->source)
11893 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
11894 +       if (info->dest)
11895 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
11896 +       
11897 +       return ret;
11898 +}
11899 +
11900 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
11901 +                     void *matchinfo, unsigned int matchsize,
11902 +                     unsigned int hook_mask)
11903 +{
11904 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
11905 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
11906 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
11907 +               return 0;
11908 +       }
11909 +
11910 +       return 1;
11911 +}
11912 +
11913 +static struct ipt_match addrtype_match = { { NULL, NULL }, "addrtype", &match,
11914 +               &checkentry, NULL, THIS_MODULE };
11915 +
11916 +static int __init init(void)
11917 +{
11918 +       return ipt_register_match(&addrtype_match);
11919 +}
11920 +
11921 +static void __exit fini(void)
11922 +{
11923 +       ipt_unregister_match(&addrtype_match);
11924 +
11925 +}
11926 +
11927 +module_init(init);
11928 +module_exit(fini);
11929 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
11930 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_condition.c   1970-01-01 01:00:00.000000000 +0100
11931 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_condition.c       2003-12-11 10:23:46.622850224 +0100
11932 @@ -0,0 +1,256 @@
11933 +/*-------------------------------------------*\
11934 +|          Netfilter Condition Module         |
11935 +|                                             |
11936 +|  Description: This module allows firewall   |
11937 +|    rules to match using condition variables |
11938 +|    stored in /proc files.                   |
11939 +|                                             |
11940 +|  Author: Stephane Ouellette     2002-10-22  |
11941 +|          <ouellettes@videotron.ca>          |
11942 +|                                             |
11943 +|  History:                                   |
11944 +|    2003-02-10  Second version with improved |
11945 +|                locking and simplified code. |
11946 +|                                             |
11947 +|  This software is distributed under the     |
11948 +|  terms of the GNU GPL.                      |
11949 +\*-------------------------------------------*/
11950 +
11951 +#include<linux/module.h>
11952 +#include<linux/proc_fs.h>
11953 +#include<linux/spinlock.h>
11954 +#include<linux/string.h>
11955 +#include<asm/atomic.h>
11956 +#include<linux/netfilter_ipv4/ip_tables.h>
11957 +#include<linux/netfilter_ipv4/ipt_condition.h>
11958 +
11959 +
11960 +#ifndef CONFIG_PROC_FS
11961 +#error  "Proc file system support is required for this module"
11962 +#endif
11963 +
11964 +
11965 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
11966 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
11967 +MODULE_LICENSE("GPL");
11968 +
11969 +
11970 +struct condition_variable {
11971 +       struct condition_variable *next;
11972 +       struct proc_dir_entry *status_proc;
11973 +       atomic_t refcount;
11974 +        int enabled;   /* TRUE == 1, FALSE == 0 */
11975 +};
11976 +
11977 +
11978 +static rwlock_t list_lock;
11979 +static struct condition_variable *head = NULL;
11980 +static struct proc_dir_entry *proc_net_condition = NULL;
11981 +
11982 +
11983 +static int
11984 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
11985 +                       int length, int *eof, void *data)
11986 +{
11987 +       struct condition_variable *var =
11988 +           (struct condition_variable *) data;
11989 +
11990 +       if (offset == 0) {
11991 +               *start = buffer;
11992 +               buffer[0] = (var->enabled) ? '1' : '0';
11993 +               buffer[1] = '\n';
11994 +               return 2;
11995 +       }
11996 +
11997 +       *eof = 1;
11998 +       return 0;
11999 +}
12000 +
12001 +
12002 +static int
12003 +ipt_condition_write_info(struct file *file, const char *buffer,
12004 +                        unsigned long length, void *data)
12005 +{
12006 +       struct condition_variable *var =
12007 +           (struct condition_variable *) data;
12008 +
12009 +       if (length) {
12010 +               /* Match only on the first character */
12011 +               switch (buffer[0]) {
12012 +               case '0':
12013 +                       var->enabled = 0;
12014 +                       break;
12015 +               case '1':
12016 +                       var->enabled = 1;
12017 +               }
12018 +       }
12019 +
12020 +       return (int) length;
12021 +}
12022 +
12023 +
12024 +static int
12025 +match(const struct sk_buff *skb, const struct net_device *in,
12026 +      const struct net_device *out, const void *matchinfo, int offset,
12027 +      const void *hdr, u_int16_t datalen, int *hotdrop)
12028 +{
12029 +       const struct condition_info *info =
12030 +           (const struct condition_info *) matchinfo;
12031 +       struct condition_variable *var;
12032 +       int condition_status = 0;
12033 +
12034 +       read_lock(&list_lock);
12035 +
12036 +       for (var = head; var; var = var->next) {
12037 +               if (strcmp(info->name, var->status_proc->name) == 0) {
12038 +                       condition_status = var->enabled;
12039 +                       break;
12040 +               }
12041 +       }
12042 +
12043 +       read_unlock(&list_lock);
12044 +
12045 +       return condition_status ^ info->invert;
12046 +}
12047 +
12048 +
12049 +
12050 +static int
12051 +checkentry(const char *tablename, const struct ipt_ip *ip,
12052 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
12053 +{
12054 +       struct condition_info *info = (struct condition_info *) matchinfo;
12055 +       struct condition_variable *var, *newvar;
12056 +
12057 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12058 +               return 0;
12059 +
12060 +       /* The first step is to check if the condition variable already exists. */
12061 +       /* Here, a read lock is sufficient because we won't change the list */
12062 +       read_lock(&list_lock);
12063 +
12064 +       for (var = head; var; var = var->next) {
12065 +               if (strcmp(info->name, var->status_proc->name) == 0) {
12066 +                       atomic_inc(&var->refcount);
12067 +                       read_unlock(&list_lock);
12068 +                       return 1;
12069 +               }
12070 +       }
12071 +
12072 +       read_unlock(&list_lock);
12073 +
12074 +       /* At this point, we need to allocate a new condition variable */
12075 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
12076 +
12077 +       if (!newvar)
12078 +               return -ENOMEM;
12079 +
12080 +       /* Create the condition variable's proc file entry */
12081 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
12082 +
12083 +       if (!newvar->status_proc) {
12084 +         /*
12085 +          * There are two possibilities:
12086 +          *  1- Another condition variable with the same name has been created, which is valid.
12087 +          *  2- There was a memory allocation error.
12088 +          */
12089 +               kfree(newvar);
12090 +               read_lock(&list_lock);
12091 +
12092 +               for (var = head; var; var = var->next) {
12093 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
12094 +                               atomic_inc(&var->refcount);
12095 +                               read_unlock(&list_lock);
12096 +                               return 1;
12097 +                       }
12098 +               }
12099 +
12100 +               read_unlock(&list_lock);
12101 +               return -ENOMEM;
12102 +       }
12103 +
12104 +       atomic_set(&newvar->refcount, 1);
12105 +       newvar->enabled = 0;
12106 +       newvar->status_proc->owner = THIS_MODULE;
12107 +       newvar->status_proc->data = newvar;
12108 +       wmb();
12109 +       newvar->status_proc->read_proc = ipt_condition_read_info;
12110 +       newvar->status_proc->write_proc = ipt_condition_write_info;
12111 +
12112 +       write_lock(&list_lock);
12113 +
12114 +       newvar->next = head;
12115 +       head = newvar;
12116 +
12117 +       write_unlock(&list_lock);
12118 +
12119 +       return 1;
12120 +}
12121 +
12122 +
12123 +static void
12124 +destroy(void *matchinfo, unsigned int matchsize)
12125 +{
12126 +       struct condition_info *info = (struct condition_info *) matchinfo;
12127 +       struct condition_variable *var, *prev = NULL;
12128 +
12129 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
12130 +               return;
12131 +
12132 +       write_lock(&list_lock);
12133 +
12134 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
12135 +            prev = var, var = var->next);
12136 +
12137 +       if (var && atomic_dec_and_test(&var->refcount)) {
12138 +               if (prev)
12139 +                       prev->next = var->next;
12140 +               else
12141 +                       head = var->next;
12142 +
12143 +               write_unlock(&list_lock);
12144 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
12145 +               kfree(var);
12146 +       } else
12147 +               write_unlock(&list_lock);
12148 +}
12149 +
12150 +
12151 +static struct ipt_match condition_match = {
12152 +       .name = "condition",
12153 +       .match = &match,
12154 +       .checkentry = &checkentry,
12155 +       .destroy = &destroy,
12156 +       .me = THIS_MODULE
12157 +};
12158 +
12159 +
12160 +static int __init
12161 +init(void)
12162 +{
12163 +       int errorcode;
12164 +
12165 +       rwlock_init(&list_lock);
12166 +       proc_net_condition = proc_mkdir("ipt_condition", proc_net);
12167 +
12168 +       if (proc_net_condition) {
12169 +               errorcode = ipt_register_match(&condition_match);
12170 +
12171 +               if (errorcode)
12172 +                       remove_proc_entry("ipt_condition", proc_net);
12173 +       } else
12174 +               errorcode = -EACCES;
12175 +
12176 +       return errorcode;
12177 +}
12178 +
12179 +
12180 +static void __exit
12181 +fini(void)
12182 +{
12183 +       ipt_unregister_match(&condition_match);
12184 +       remove_proc_entry("ipt_condition", proc_net);
12185 +}
12186 +
12187 +module_init(init);
12188 +module_exit(fini);
12189 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
12190 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connlimit.c   1970-01-01 01:00:00.000000000 +0100
12191 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connlimit.c       2003-12-11 12:50:01.556857488 +0100
12192 @@ -0,0 +1,227 @@
12193 +/*
12194 + * netfilter module to limit the number of parallel tcp
12195 + * connections per IP address.
12196 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
12197 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
12198 + *             only ignore TIME_WAIT or gone connections
12199 + *
12200 + * based on ...
12201 + *
12202 + * Kernel module to match connection tracking information.
12203 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
12204 + */
12205 +#include <linux/module.h>
12206 +#include <linux/skbuff.h>
12207 +#include <linux/list.h>
12208 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12209 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
12210 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
12211 +#include <linux/netfilter_ipv4/ip_tables.h>
12212 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
12213 +
12214 +#define DEBUG 0
12215 +
12216 +MODULE_LICENSE("GPL");
12217 +
12218 +/* we'll save the tuples of all connections we care about */
12219 +struct ipt_connlimit_conn
12220 +{
12221 +        struct list_head list;
12222 +       struct ip_conntrack_tuple tuple;
12223 +};
12224 +
12225 +struct ipt_connlimit_data {
12226 +       spinlock_t lock;
12227 +       struct list_head iphash[256];
12228 +};
12229 +
12230 +static int ipt_iphash(u_int32_t addr)
12231 +{
12232 +       int hash;
12233 +
12234 +       hash  =  addr        & 0xff;
12235 +       hash ^= (addr >>  8) & 0xff;
12236 +       hash ^= (addr >> 16) & 0xff;
12237 +       hash ^= (addr >> 24) & 0xff;
12238 +       return hash;
12239 +}
12240 +
12241 +static int count_them(struct ipt_connlimit_data *data,
12242 +                     u_int32_t addr, u_int32_t mask,
12243 +                     struct ip_conntrack *ct)
12244 +{
12245 +#if DEBUG
12246 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
12247 +                                    "fin_wait", "time_wait", "close", "close_wait",
12248 +                                    "last_ack", "listen" };
12249 +#endif
12250 +       int addit = 1, matches = 0;
12251 +       struct ip_conntrack_tuple tuple;
12252 +       struct ip_conntrack_tuple_hash *found;
12253 +       struct ipt_connlimit_conn *conn;
12254 +       struct list_head *hash,*lh;
12255 +
12256 +       spin_lock(&data->lock);
12257 +       tuple = ct->tuplehash[0].tuple;
12258 +       hash = &data->iphash[ipt_iphash(addr & mask)];
12259 +
12260 +       /* check the saved connections */
12261 +       for (lh = hash->next; lh != hash; lh = lh->next) {
12262 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
12263 +               found = ip_conntrack_find_get(&conn->tuple,ct);
12264 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
12265 +                   found != NULL &&
12266 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
12267 +                       /* Just to be sure we have it only once in the list.
12268 +                          We should'nt see tuples twice unless someone hooks this
12269 +                          into a table without "-p tcp --syn" */
12270 +                       addit = 0;
12271 +               }
12272 +#if DEBUG
12273 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
12274 +                      ipt_iphash(addr & mask),
12275 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
12276 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
12277 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
12278 +#endif
12279 +               if (NULL == found) {
12280 +                       /* this one is gone */
12281 +                       lh = lh->prev;
12282 +                       list_del(lh->next);
12283 +                       kfree(conn);
12284 +                       continue;
12285 +               }
12286 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
12287 +                       /* we don't care about connections which are
12288 +                          closed already -> ditch it */
12289 +                       lh = lh->prev;
12290 +                       list_del(lh->next);
12291 +                       kfree(conn);
12292 +                       nf_conntrack_put(&found->ctrack->infos[0]);
12293 +                       continue;
12294 +               }
12295 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
12296 +                       /* same source IP address -> be counted! */
12297 +                       matches++;
12298 +               }
12299 +               nf_conntrack_put(&found->ctrack->infos[0]);
12300 +       }
12301 +       if (addit) {
12302 +               /* save the new connection in our list */
12303 +#if DEBUG
12304 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
12305 +                      ipt_iphash(addr & mask),
12306 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
12307 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
12308 +#endif
12309 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
12310 +               if (NULL == conn)
12311 +                       return -1;
12312 +               memset(conn,0,sizeof(*conn));
12313 +               INIT_LIST_HEAD(&conn->list);
12314 +               conn->tuple = tuple;
12315 +               list_add(&conn->list,hash);
12316 +               matches++;
12317 +       }
12318 +       spin_unlock(&data->lock);
12319 +       return matches;
12320 +}
12321 +
12322 +static int
12323 +match(const struct sk_buff *skb,
12324 +      const struct net_device *in,
12325 +      const struct net_device *out,
12326 +      const void *matchinfo,
12327 +      int offset,
12328 +      const void *hdr,
12329 +      u_int16_t datalen,
12330 +      int *hotdrop)
12331 +{
12332 +       const struct ipt_connlimit_info *info = matchinfo;
12333 +       int connections, match;
12334 +       struct ip_conntrack *ct;
12335 +       enum ip_conntrack_info ctinfo;
12336 +
12337 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12338 +       if (NULL == ct) {
12339 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
12340 +               *hotdrop = 1;
12341 +               return 0;
12342 +       }
12343 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
12344 +       if (-1 == connections) {
12345 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
12346 +               *hotdrop = 1; /* let's free some memory :-) */
12347 +               return 0;
12348 +       }
12349 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
12350 +#if DEBUG
12351 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
12352 +              "connections=%d limit=%d match=%s\n",
12353 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
12354 +              connections, info->limit, match ? "yes" : "no");
12355 +#endif
12356 +
12357 +       return match;
12358 +}
12359 +
12360 +static int check(const char *tablename,
12361 +                const struct ipt_ip *ip,
12362 +                void *matchinfo,
12363 +                unsigned int matchsize,
12364 +                unsigned int hook_mask)
12365 +{
12366 +       struct ipt_connlimit_info *info = matchinfo;
12367 +       int i;
12368 +
12369 +       /* verify size */
12370 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
12371 +               return 0;
12372 +
12373 +       /* refuse anything but tcp */
12374 +       if (ip->proto != IPPROTO_TCP)
12375 +               return 0;
12376 +
12377 +       /* init private data */
12378 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
12379 +       spin_lock_init(&(info->data->lock));
12380 +       for (i = 0; i < 256; i++)
12381 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
12382 +       
12383 +       return 1;
12384 +}
12385 +
12386 +static void destroy(void *matchinfo, unsigned int matchinfosize)
12387 +{
12388 +       struct ipt_connlimit_info *info = matchinfo;
12389 +       struct ipt_connlimit_conn *conn;
12390 +       struct list_head *hash;
12391 +       int i;
12392 +
12393 +       /* cleanup */
12394 +       for (i = 0; i < 256; i++) {
12395 +               hash = &(info->data->iphash[i]);
12396 +               while (hash != hash->next) {
12397 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
12398 +                       list_del(hash->next);
12399 +                       kfree(conn);
12400 +               }
12401 +       }
12402 +       kfree(info->data);
12403 +}
12404 +
12405 +static struct ipt_match connlimit_match
12406 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
12407 +
12408 +static int __init init(void)
12409 +{
12410 +       return ipt_register_match(&connlimit_match);
12411 +}
12412 +
12413 +static void __exit fini(void)
12414 +{
12415 +       ipt_unregister_match(&connlimit_match);
12416 +}
12417 +
12418 +module_init(init);
12419 +module_exit(fini);
12420 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
12421 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_connmark.c    1970-01-01 01:00:00.000000000 +0100
12422 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_connmark.c        2003-12-11 10:23:47.827667064 +0100
12423 @@ -0,0 +1,55 @@
12424 +/* Kernel module to match connection mark values. */
12425 +#include <linux/module.h>
12426 +#include <linux/skbuff.h>
12427 +
12428 +#include <linux/netfilter_ipv4/ip_tables.h>
12429 +#include <linux/netfilter_ipv4/ipt_connmark.h>
12430 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12431 +
12432 +static int
12433 +match(const struct sk_buff *skb,
12434 +      const struct net_device *in,
12435 +      const struct net_device *out,
12436 +      const void *matchinfo,
12437 +      int offset,
12438 +      const void *hdr,
12439 +      u_int16_t datalen,
12440 +      int *hotdrop)
12441 +{
12442 +       const struct ipt_connmark_info *info = matchinfo;
12443 +       enum ip_conntrack_info ctinfo;
12444 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12445 +       if (!ct)
12446 +           return 0;
12447 +
12448 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
12449 +}
12450 +
12451 +static int
12452 +checkentry(const char *tablename,
12453 +           const struct ipt_ip *ip,
12454 +           void *matchinfo,
12455 +           unsigned int matchsize,
12456 +           unsigned int hook_mask)
12457 +{
12458 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
12459 +               return 0;
12460 +
12461 +       return 1;
12462 +}
12463 +
12464 +static struct ipt_match connmark_match
12465 += { { NULL, NULL }, "connmark", &match, &checkentry, NULL, THIS_MODULE };
12466 +
12467 +static int __init init(void)
12468 +{
12469 +       return ipt_register_match(&connmark_match);
12470 +}
12471 +
12472 +static void __exit fini(void)
12473 +{
12474 +       ipt_unregister_match(&connmark_match);
12475 +}
12476 +
12477 +module_init(init);
12478 +module_exit(fini);
12479 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
12480 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_CONNMARK.c    1970-01-01 01:00:00.000000000 +0100
12481 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_CONNMARK.c        2003-12-11 10:23:47.828666912 +0100
12482 @@ -0,0 +1,87 @@
12483 +/* This is a module which is used for setting/remembering the mark field of
12484 + * an connection, or optionally restore it to the skb
12485 + */
12486 +#include <linux/module.h>
12487 +#include <linux/skbuff.h>
12488 +#include <linux/ip.h>
12489 +#include <net/checksum.h>
12490 +
12491 +#include <linux/netfilter_ipv4/ip_tables.h>
12492 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
12493 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12494 +
12495 +static unsigned int
12496 +target(struct sk_buff **pskb,
12497 +       unsigned int hooknum,
12498 +       const struct net_device *in,
12499 +       const struct net_device *out,
12500 +       const void *targinfo,
12501 +       void *userinfo)
12502 +{
12503 +       const struct ipt_connmark_target_info *markinfo = targinfo;
12504 +
12505 +       enum ip_conntrack_info ctinfo;
12506 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
12507 +       if (ct) {
12508 +           switch(markinfo->mode) {
12509 +           case IPT_CONNMARK_SET:
12510 +               ct->mark = markinfo->mark;
12511 +               break;
12512 +           case IPT_CONNMARK_SAVE:
12513 +               ct->mark = (*pskb)->nfmark;
12514 +               break;
12515 +           case IPT_CONNMARK_RESTORE:
12516 +               if (ct->mark != (*pskb)->nfmark) {
12517 +                   (*pskb)->nfmark = ct->mark;
12518 +                   (*pskb)->nfcache |= NFC_ALTERED;
12519 +               }
12520 +               break;
12521 +           }
12522 +       }
12523 +
12524 +       return IPT_CONTINUE;
12525 +}
12526 +
12527 +static int
12528 +checkentry(const char *tablename,
12529 +          const struct ipt_entry *e,
12530 +           void *targinfo,
12531 +           unsigned int targinfosize,
12532 +           unsigned int hook_mask)
12533 +{
12534 +       struct ipt_connmark_target_info *matchinfo = targinfo;
12535 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
12536 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
12537 +                      targinfosize,
12538 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
12539 +               return 0;
12540 +       }
12541 +
12542 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
12543 +           if (strcmp(tablename, "mangle") != 0) {
12544 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
12545 +                   return 0;
12546 +           }
12547 +       }
12548 +
12549 +       return 1;
12550 +}
12551 +
12552 +static struct ipt_target ipt_connmark_reg
12553 += { { NULL, NULL }, "CONNMARK", target, checkentry, NULL, THIS_MODULE };
12554 +
12555 +static int __init init(void)
12556 +{
12557 +       if (ipt_register_target(&ipt_connmark_reg))
12558 +               return -EINVAL;
12559 +
12560 +       return 0;
12561 +}
12562 +
12563 +static void __exit fini(void)
12564 +{
12565 +       ipt_unregister_target(&ipt_connmark_reg);
12566 +}
12567 +
12568 +module_init(init);
12569 +module_exit(fini);
12570 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
12571 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_conntrack.c   2003-11-26 21:45:34.000000000 +0100
12572 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_conntrack.c       2003-12-11 10:23:17.229318720 +0100
12573 @@ -29,7 +29,9 @@
12574  
12575  #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
12576  
12577 -       if (ct)
12578 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
12579 +               statebit = IPT_CONNTRACK_STATE_UNTRACKED;
12580 +       else if (ct)
12581                 statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
12582         else
12583                 statebit = IPT_CONNTRACK_STATE_INVALID;
12584 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
12585 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_dstlimit.c    1970-01-01 01:00:00.000000000 +0100
12586 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_dstlimit.c        2003-12-11 10:23:20.528817120 +0100
12587 @@ -0,0 +1,623 @@
12588 +/* iptables match extension to limit the number of packets per second
12589 + * seperately for each destination.
12590 + *
12591 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
12592 + *
12593 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
12594 + *
12595 + * based on ipt_limit.c by:
12596 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
12597 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
12598 + * Rusty Russell       <rusty@rustcorp.com.au>
12599 + *
12600 + * The general idea is to create a hash table for every dstip and have a
12601 + * seperate limit counter per tuple.  This way you can do something like 'limit
12602 + * the number of syn packets for each of my internal addresses.
12603 + *
12604 + * Ideally this would just be implemented as a general 'hash' match, which would
12605 + * allow us to attach any iptables target to it's hash buckets.  But this is
12606 + * not possible in the current iptables architecture.  As always, pkttables for
12607 + * 2.7.x will help ;)
12608 + */
12609 +#include <linux/module.h>
12610 +#include <linux/skbuff.h>
12611 +#include <linux/spinlock.h>
12612 +#include <linux/random.h>
12613 +#include <linux/jhash.h>
12614 +#include <linux/slab.h>
12615 +#include <linux/vmalloc.h>
12616 +#include <linux/tcp.h>
12617 +#include <linux/udp.h>
12618 +#include <linux/proc_fs.h>
12619 +#include <linux/seq_file.h>
12620 +
12621 +#define ASSERT_READ_LOCK(x) 
12622 +#define ASSERT_WRITE_LOCK(x) 
12623 +#include <linux/netfilter_ipv4/lockhelp.h>
12624 +#include <linux/netfilter_ipv4/listhelp.h>
12625 +
12626 +#include <linux/netfilter_ipv4/ip_tables.h>
12627 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
12628 +
12629 +/* FIXME: this is just for IP_NF_ASSERRT */
12630 +#include <linux/netfilter_ipv4/ip_conntrack.h>
12631 +
12632 +#define MS2JIFFIES(x) ((x*HZ)/1000)
12633 +
12634 +MODULE_LICENSE("GPL");
12635 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
12636 +MODULE_DESCRIPTION("iptables match for limiting per destination");
12637 +
12638 +/* need to declare this at the top */
12639 +static struct proc_dir_entry *dstlimit_procdir;
12640 +static struct file_operations dl_file_ops;
12641 +
12642 +/* hash table crap */
12643 +
12644 +struct dsthash_dst {
12645 +       u_int32_t src_ip;
12646 +       u_int32_t dst_ip;
12647 +       u_int16_t port;
12648 +};
12649 +
12650 +struct dsthash_ent {
12651 +       /* static / read-only parts in the beginning */
12652 +       struct list_head list;
12653 +       struct dsthash_dst dst;
12654 +
12655 +       /* modified structure members in the end */
12656 +       unsigned long expires;          /* precalculated expiry time */
12657 +       struct {
12658 +               unsigned long prev;     /* last modification */
12659 +               u_int32_t credit;
12660 +               u_int32_t credit_cap, cost;
12661 +       } rateinfo;
12662 +};
12663 +
12664 +struct ipt_dstlimit_htable {
12665 +       struct ipt_dstlimit_info *minfo; /* public structure */
12666 +
12667 +       /* used internally */
12668 +       spinlock_t lock;                /* lock for list_head */
12669 +       u_int32_t rnd;                  /* random seed for hash */
12670 +       struct timer_list timer;        /* timer for gc */
12671 +       atomic_t count;                 /* number entries in table */
12672 +
12673 +       /* seq_file stuff */
12674 +       struct proc_dir_entry *pde;
12675 +
12676 +       struct list_head hash[0];       /* hashtable itself */
12677 +};
12678 +
12679 +static kmem_cache_t *dstlimit_cachep;
12680 +
12681 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
12682 +{
12683 +       return (ent->dst.dst_ip == b->dst_ip 
12684 +               && ent->dst.port == b->port
12685 +               && ent->dst.src_ip == b->src_ip);
12686 +}
12687 +
12688 +static inline u_int32_t
12689 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
12690 +{
12691 +       return (jhash_3words(dst->dst_ip, dst->port, 
12692 +                            dst->src_ip, ht->rnd) % ht->minfo->size);
12693 +}
12694 +
12695 +static inline struct dsthash_ent *
12696 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12697 +{
12698 +       struct dsthash_ent *ent;
12699 +       u_int32_t hash = hash_dst(ht, dst);
12700 +       MUST_BE_LOCKED(&ht->lock);
12701 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
12702 +       return ent;
12703 +}
12704 +
12705 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
12706 +static struct dsthash_ent *
12707 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
12708 +{
12709 +       struct dsthash_ent *ent;
12710 +
12711 +       /* initialize hash with random val at the time we allocate
12712 +        * the first hashtable entry */
12713 +       if (!ht->rnd)
12714 +               get_random_bytes(&ht->rnd, 4);
12715 +
12716 +       if (ht->minfo->max &&
12717 +           atomic_read(&ht->count) >= ht->minfo->max) {
12718 +               /* FIXME: do something. question is what.. */
12719 +               if (net_ratelimit())
12720 +                       printk("max count of %u reached\n", ht->minfo->max);
12721 +               return NULL;
12722 +       }
12723 +
12724 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
12725 +       if (!ent) {
12726 +               if (net_ratelimit())
12727 +                       printk("Can't allocate dsthash_ent\n");
12728 +               return NULL;
12729 +       }
12730 +
12731 +       atomic_inc(&ht->count);
12732 +
12733 +       ent->dst.dst_ip = dst->dst_ip;
12734 +       ent->dst.port = dst->port;
12735 +       ent->dst.src_ip = dst->src_ip;
12736 +
12737 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
12738 +
12739 +       return ent;
12740 +}
12741 +
12742 +static inline void 
12743 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
12744 +{
12745 +       MUST_BE_LOCKED(&ht->lock);
12746 +
12747 +       list_del(&ent->list);
12748 +       kmem_cache_free(dstlimit_cachep, ent);
12749 +       atomic_dec(&ht->count);
12750 +}
12751 +
12752 +static void htable_gc(unsigned long htlong);
12753 +
12754 +static int htable_create(struct ipt_dstlimit_info *minfo)
12755 +{
12756 +       int i;
12757 +       struct ipt_dstlimit_htable *hinfo;
12758 +
12759 +       if (!minfo->size) {
12760 +               minfo->size = (((num_physpages << PAGE_SHIFT) / 16384)
12761 +                           / sizeof(struct list_head));
12762 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
12763 +                       minfo->size = 8192;
12764 +               if (minfo->size < 16)
12765 +                       minfo->size = 16;
12766 +       }
12767 +       if (!minfo->max)
12768 +               minfo->max = 8 * minfo->size;
12769 +       else if (minfo->max < minfo->size)
12770 +               minfo->max = minfo->size;
12771 +
12772 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
12773 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
12774 +                       + (sizeof(struct list_head) * minfo->size));
12775 +       if (!hinfo) {
12776 +               printk(KERN_ERR "Unable to create ipt_dstlimit hash\n");
12777 +               return -1;
12778 +       }
12779 +
12780 +       for (i = 0; i < minfo->size; i++)
12781 +               INIT_LIST_HEAD(&hinfo->hash[i]);
12782 +
12783 +       minfo->hinfo = hinfo;
12784 +
12785 +       hinfo->minfo = minfo;
12786 +       atomic_set(&hinfo->count, 0);
12787 +       hinfo->rnd = 0;
12788 +
12789 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
12790 +
12791 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
12792 +       if (!hinfo->pde) {
12793 +               vfree(hinfo);
12794 +               return -1;
12795 +       }
12796 +       hinfo->pde->proc_fops = &dl_file_ops;
12797 +       hinfo->pde->data = hinfo;
12798 +
12799 +       init_timer(&hinfo->timer);
12800 +       hinfo->timer.expires = jiffies + MS2JIFFIES(minfo->gc_interval);
12801 +       hinfo->timer.data = (unsigned long )hinfo;
12802 +       hinfo->timer.function = htable_gc;
12803 +       add_timer(&hinfo->timer);
12804 +
12805 +       return 0;
12806 +}
12807 +
12808 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12809 +{
12810 +       return 1;
12811 +}
12812 +
12813 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
12814 +{
12815 +       return (jiffies >= he->expires);
12816 +}
12817 +
12818 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
12819 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
12820 +                                             struct dsthash_ent *he))
12821 +{
12822 +       int i;
12823 +
12824 +       IP_NF_ASSERT(ht->minfo->size && ht->minfo->max);
12825 +
12826 +       /* lock hash table and iterate over it */
12827 +       LOCK_BH(&ht->lock);
12828 +       for (i = 0; i < ht->minfo->size; i++) {
12829 +               struct dsthash_ent *dh, *n;
12830 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
12831 +                       if ((*select)(ht, dh))
12832 +                               __dsthash_free(ht, dh);
12833 +               }
12834 +       }
12835 +       UNLOCK_BH(&ht->lock);
12836 +}
12837 +
12838 +/* hash table garbage collector, run by timer */
12839 +static void htable_gc(unsigned long htlong)
12840 +{
12841 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
12842 +
12843 +       htable_selective_cleanup(ht, select_gc);
12844 +
12845 +       /* re-add the timer accordingly */
12846 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->minfo->gc_interval);
12847 +       add_timer(&ht->timer);
12848 +}
12849 +
12850 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
12851 + * see net/sched/sch_tbf.c in the linux source tree
12852 + */
12853 +
12854 +/* Rusty: This is my (non-mathematically-inclined) understanding of
12855 +   this algorithm.  The `average rate' in jiffies becomes your initial
12856 +   amount of credit `credit' and the most credit you can ever have
12857 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
12858 +   test, `cost'.
12859 +
12860 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
12861 +   If you get credit balance more than this, the extra credit is
12862 +   discarded.  Every time the match passes, you lose `cost' credits;
12863 +   if you don't have that many, the test fails.
12864 +
12865 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
12866 +
12867 +   To get the maximum range, we multiply by this factor (ie. you get N
12868 +   credits per jiffy).  We want to allow a rate as low as 1 per day
12869 +   (slowest userspace tool allows), which means
12870 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
12871 +*/
12872 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
12873 +
12874 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
12875 + * us the power of 2 below the theoretical max, so GCC simply does a
12876 + * shift. */
12877 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
12878 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
12879 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
12880 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
12881 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
12882 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
12883 +
12884 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
12885 +
12886 +/* Precision saver. */
12887 +static inline u_int32_t
12888 +user2credits(u_int32_t user)
12889 +{
12890 +       /* If multiplying would overflow... */
12891 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
12892 +               /* Divide first. */
12893 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
12894 +
12895 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
12896 +}
12897 +
12898 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
12899 +{
12900 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
12901 +                                       * CREDITS_PER_JIFFY;
12902 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
12903 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
12904 +}
12905 +
12906 +static int
12907 +dstlimit_match(const struct sk_buff *skb,
12908 +               const struct net_device *in,
12909 +               const struct net_device *out,
12910 +               const void *matchinfo,
12911 +               int offset,
12912 +               const void *hdr,
12913 +               u_int16_t datalen,
12914 +               int *hotdrop)
12915 +{
12916 +       struct ipt_dstlimit_info *r = 
12917 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
12918 +       unsigned long now = jiffies;
12919 +       struct dsthash_ent *dh;
12920 +       struct dsthash_dst dst;
12921 +
12922 +       memset(&dst, 0, sizeof(dst));
12923 +
12924 +       /* dest ip is always in hash */
12925 +       dst.dst_ip = skb->nh.iph->daddr;
12926 +
12927 +       /* source ip only if respective hashmode, otherwise set to
12928 +        * zero */
12929 +       if (r->mode & IPT_DSTLIMIT_HASH_SIP)
12930 +               dst.src_ip = skb->nh.iph->saddr;
12931 +
12932 +       /* dest port only if respective mode */
12933 +       if (r->mode & IPT_DSTLIMIT_HASH_DPT) {
12934 +               switch (skb->nh.iph->protocol) {
12935 +                       struct tcphdr *th;
12936 +                       struct udphdr *uh;
12937 +               case IPPROTO_TCP:
12938 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12939 +                       dst.port = th->dest;
12940 +                       break;
12941 +               case IPPROTO_UDP:
12942 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
12943 +                       dst.port = uh->dest;
12944 +                       break;
12945 +               default:
12946 +                       break;
12947 +               }
12948 +       } 
12949 +
12950 +       LOCK_BH(&r->hinfo->lock);
12951 +       dh = __dsthash_find(r->hinfo, &dst);
12952 +       if (!dh) {
12953 +               dh = __dsthash_alloc_init(r->hinfo, &dst);
12954 +
12955 +               if (!dh) {
12956 +                       /* enomem... don't match == DROP */
12957 +                       if (net_ratelimit())
12958 +                               printk("%s: ENOMEM\n", __FUNCTION__);
12959 +                       UNLOCK_BH(&r->hinfo->lock);
12960 +                       return 0;
12961 +               }
12962 +
12963 +               dh->expires = jiffies + MS2JIFFIES(r->expire);
12964 +
12965 +               dh->rateinfo.prev = jiffies;
12966 +               dh->rateinfo.credit = user2credits(r->avg * r->burst);
12967 +               dh->rateinfo.credit_cap = user2credits(r->avg * r->burst);
12968 +               dh->rateinfo.cost = user2credits(r->avg);
12969 +
12970 +               UNLOCK_BH(&r->hinfo->lock);
12971 +               return 0;
12972 +       }
12973 +
12974 +       /* update expiration timeout */
12975 +       dh->expires = now + MS2JIFFIES(r->expire);
12976 +
12977 +       rateinfo_recalc(dh, now);
12978 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
12979 +               /* We're underlimit. */
12980 +               dh->rateinfo.credit -= dh->rateinfo.cost;
12981 +               UNLOCK_BH(&r->hinfo->lock);
12982 +               return 1;
12983 +       }
12984 +
12985 +               UNLOCK_BH(&r->hinfo->lock);
12986 +
12987 +       /* default case: we're overlimit, thus don't match */
12988 +       return 0;
12989 +}
12990 +
12991 +static int
12992 +dstlimit_checkentry(const char *tablename,
12993 +                    const struct ipt_ip *ip,
12994 +                    void *matchinfo,
12995 +                    unsigned int matchsize,
12996 +                    unsigned int hook_mask)
12997 +{
12998 +       struct ipt_dstlimit_info *r = matchinfo;
12999 +
13000 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
13001 +               return 0;
13002 +
13003 +       /* Check for overflow. */
13004 +       if (r->burst == 0
13005 +           || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
13006 +               printk("Overflow in ipt_dstlimit, try lower: %u/%u\n",
13007 +                      r->avg, r->burst);
13008 +               return 0;
13009 +       }
13010 +
13011 +       if (r->mode == 0 
13012 +           || r->mode > (IPT_DSTLIMIT_HASH_DPT
13013 +                         |IPT_DSTLIMIT_HASH_DIP
13014 +                         |IPT_DSTLIMIT_HASH_SIP))
13015 +               return 0;
13016 +
13017 +       if (!r->gc_interval)
13018 +               return 0;
13019 +       
13020 +       if (!r->expire)
13021 +               return 0;
13022 +
13023 +       if (htable_create(r) != 0) {
13024 +               printk("Unable to create dstlimit htable\n");
13025 +               return 0;
13026 +       }
13027 +
13028 +       /* Ugly hack: For SMP, we only want to use one set */
13029 +       r->u.master = r;
13030 +
13031 +       return 1;
13032 +}
13033 +
13034 +static void
13035 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
13036 +{
13037 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
13038 +
13039 +       r = r->u.master;
13040 +
13041 +       /* remove timer, if it is pending */
13042 +       if (timer_pending(&r->hinfo->timer))
13043 +               del_timer(&r->hinfo->timer);
13044 +
13045 +       /* remove proc entry */
13046 +       remove_proc_entry(r->name, dstlimit_procdir);
13047 +
13048 +       htable_selective_cleanup(r->hinfo, select_all);
13049 +       vfree(&r->hinfo);
13050 +}
13051 +
13052 +static struct ipt_match ipt_dstlimit = { 
13053 +       .list = { .prev = NULL, .next = NULL }, 
13054 +       .name = "dstlimit", 
13055 +       .match = dstlimit_match, 
13056 +       .checkentry = dstlimit_checkentry, 
13057 +       .destroy = dstlimit_destroy,
13058 +       .me = THIS_MODULE 
13059 +};
13060 +
13061 +/* PROC stuff */
13062 +
13063 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
13064 +{
13065 +       struct proc_dir_entry *pde = s->private;
13066 +       struct ipt_dstlimit_htable *htable = pde->data;
13067 +       unsigned int *bucket;
13068 +
13069 +       LOCK_BH(&htable->lock);
13070 +       if (*pos >= htable->minfo->size)
13071 +               return NULL;
13072 +
13073 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
13074 +       if (!bucket)
13075 +               return ERR_PTR(-ENOMEM);
13076 +
13077 +       *bucket = *pos;
13078 +       return bucket;
13079 +}
13080 +
13081 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
13082 +{
13083 +       struct proc_dir_entry *pde = s->private;
13084 +       struct ipt_dstlimit_htable *htable = pde->data;
13085 +       unsigned int *bucket = (unsigned int *)v;
13086 +
13087 +       *pos = ++(*bucket);
13088 +       if (*pos >= htable->minfo->size) {
13089 +               kfree(v);
13090 +               return NULL;
13091 +       }
13092 +       return bucket;
13093 +}
13094 +
13095 +static void dl_seq_stop(struct seq_file *s, void *v)
13096 +{
13097 +       struct proc_dir_entry *pde = s->private;
13098 +       struct ipt_dstlimit_htable *htable = pde->data;
13099 +
13100 +       UNLOCK_BH(&htable->lock);
13101 +}
13102 +
13103 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
13104 +{
13105 +       /* recalculate to show accurate numbers */
13106 +       rateinfo_recalc(ent, jiffies);
13107 +
13108 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
13109 +                       (ent->expires - jiffies)/HZ,
13110 +                       NIPQUAD(ent->dst.src_ip),
13111 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
13112 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
13113 +                       ent->rateinfo.cost);
13114 +}
13115 +
13116 +static int dl_seq_show(struct seq_file *s, void *v)
13117 +{
13118 +       struct proc_dir_entry *pde = s->private;
13119 +       struct ipt_dstlimit_htable *htable = pde->data;
13120 +       unsigned int *bucket = (unsigned int *)v;
13121 +
13122 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
13123 +                     struct dsthash_ent *, s)) {
13124 +               /* buffer was filled and unable to print that tuple */
13125 +               return 1;
13126 +       }
13127 +       return 0;
13128 +}
13129 +
13130 +static struct seq_operations dl_seq_ops = {
13131 +       .start = dl_seq_start,
13132 +       .next  = dl_seq_next,
13133 +       .stop  = dl_seq_stop,
13134 +       .show  = dl_seq_show
13135 +};
13136 +
13137 +static int dl_proc_open(struct inode *inode, struct file *file)
13138 +{
13139 +       int ret = seq_open(file, &dl_seq_ops);
13140 +
13141 +       if (!ret) {
13142 +               struct seq_file *sf = file->private_data;
13143 +               sf->private = PDE(inode);
13144 +       }
13145 +       return ret;
13146 +}
13147 +
13148 +static struct file_operations dl_file_ops = {
13149 +       .owner   = THIS_MODULE,
13150 +       .open    = dl_proc_open,
13151 +       .read    = seq_read,
13152 +       .llseek  = seq_lseek,
13153 +       .release = seq_release
13154 +};
13155 +
13156 +static int init_or_fini(int fini)
13157 +{
13158 +       int ret = 0;
13159 +
13160 +       if (fini)
13161 +               goto cleanup;
13162 +
13163 +       if (ipt_register_match(&ipt_dstlimit)) {
13164 +               ret = -EINVAL;
13165 +               goto cleanup_nothing;
13166 +       }
13167 +
13168 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
13169 +        * quite small ? */
13170 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
13171 +                                           sizeof(struct dsthash_ent), 0,
13172 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
13173 +       if (!dstlimit_cachep) {
13174 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
13175 +               ret = -ENOMEM;
13176 +               goto cleanup_unreg_match;
13177 +       }
13178 +
13179 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
13180 +       if (!dstlimit_procdir) {
13181 +               printk(KERN_ERR "Unable to create proc dir entry\n");
13182 +               ret = -ENOMEM;
13183 +               goto cleanup_free_slab;
13184 +       }
13185 +
13186 +       return ret;
13187 +
13188 +cleanup:
13189 +       remove_proc_entry("ipt_dstlimit", proc_net);
13190 +cleanup_free_slab:
13191 +       kmem_cache_destroy(dstlimit_cachep);
13192 +cleanup_unreg_match:
13193 +       ipt_unregister_match(&ipt_dstlimit);
13194 +cleanup_nothing:
13195 +       return ret;
13196 +       
13197 +}
13198 +
13199 +static int __init init(void)
13200 +{
13201 +       return init_or_fini(0);
13202 +}
13203 +
13204 +static void __exit fini(void)
13205 +{
13206 +       init_or_fini(1);
13207 +}
13208 +
13209 +module_init(init);
13210 +module_exit(fini);
13211 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
13212 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_fuzzy.c       1970-01-01 01:00:00.000000000 +0100
13213 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_fuzzy.c   2003-12-11 10:23:22.735481656 +0100
13214 @@ -0,0 +1,190 @@
13215 +/*
13216 + *  This module implements a simple TSK FLC 
13217 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
13218 + * to limit , in an adaptive and flexible way , the packet rate crossing 
13219 + * a given stream . It serves as an initial and very simple (but effective)
13220 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
13221 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
13222 + * into our code in a precise , adaptive and efficient manner. 
13223 + *  The goal is very similar to that of "limit" match , but using techniques of
13224 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
13225 + * avoiding over and undershoots - and stuff like that .
13226 + *
13227 + *
13228 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
13229 + * 2002-08-17  : Changed to eliminate floating point operations .
13230 + * 2002-08-23  : Coding style changes .
13231 +*/
13232 +
13233 +#include <linux/module.h>
13234 +#include <linux/skbuff.h>
13235 +#include <linux/ip.h>
13236 +#include <linux/random.h>
13237 +#include <net/tcp.h>
13238 +#include <linux/spinlock.h>
13239 +#include <linux/netfilter_ipv4/ip_tables.h>
13240 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
13241 +
13242 +/*
13243 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
13244 + Expressed in percentage
13245 +*/
13246 +
13247 +#define PAR_LOW                1/100
13248 +#define PAR_HIGH       1
13249 +
13250 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
13251 +
13252 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
13253 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
13254 +MODULE_LICENSE("GPL");
13255 +
13256 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13257 +{
13258 +       if (tx >= maxi) return 100;
13259 +
13260 +       if (tx <= mini) return 0;
13261 +
13262 +       return ( (100*(tx-mini)) / (maxi-mini) ) ;
13263 +}
13264 +
13265 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
13266 +{
13267 +       if (tx <= mini) return 100;
13268 +
13269 +       if (tx >= maxi) return 0;
13270 +
13271 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) ) ;
13272 +
13273 +}
13274 +
13275 +static int
13276 +ipt_fuzzy_match(const struct sk_buff *pskb,
13277 +              const struct net_device *in,
13278 +              const struct net_device *out,
13279 +              const void *matchinfo,
13280 +              int offset,
13281 +              const void *hdr,
13282 +              u_int16_t datalen,
13283 +              int *hotdrop)
13284 +{
13285 +       /* From userspace */
13286 +       
13287 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
13288 +
13289 +       u_int8_t random_number;
13290 +       unsigned long amount ;
13291 +       u_int8_t howhigh , howlow ;
13292 +       
13293 +
13294 +       spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
13295 +
13296 +       info->bytes_total += pskb->len ;
13297 +       info->packets_total++ ;
13298 +
13299 +       info->present_time = jiffies ;
13300 +       
13301 +       if ( info->present_time >= info->previous_time )
13302 +               amount = info->present_time - info->previous_time ;
13303 +       else { 
13304 +               /* There was a transition : I choose to re-sample 
13305 +                  and keep the old acceptance rate...
13306 +               */
13307 +
13308 +               amount = 0 ;
13309 +               info->previous_time = info->present_time ;
13310 +               info->bytes_total = info->packets_total = 0;
13311 +            };
13312 +       
13313 +       if (  amount > HZ/10 ) /* More than 100 ms elapsed ... */
13314 +               {
13315 +
13316 +       info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total )  \
13317 +                                       / amount ) ;
13318 +
13319 +               info->previous_time = info->present_time ;
13320 +               info->bytes_total = info->packets_total = 0 ;
13321 +
13322 +       howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
13323 +       howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
13324 +
13325 +    info->acceptance_rate = (u_int8_t) \
13326 +                          ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
13327 +
13328 +    /* In fact , the above defuzzification would require a denominator
13329 +       proportional to (howhigh+howlow) but , in this particular case ,
13330 +       that expression is constant .
13331 +        An imediate consequence is that it isn't necessary to call 
13332 +       both mf_high and mf_low - but to keep things understandable ,
13333 +       I did so .
13334 +     */ 
13335 +
13336 +               }
13337 +       
13338 +       spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
13339 +
13340 +
13341 +       if ( info->acceptance_rate < 100 )
13342 +       {                
13343 +               get_random_bytes((void *)(&random_number), 1);
13344 +
13345 +               /*  If within the acceptance , it can pass => don't match */
13346 +               if ( random_number <= (255 * info->acceptance_rate) / 100 )
13347 +                       return 0 ;
13348 +               else
13349 +                       return 1; /* It can't pass ( It matches ) */
13350 +       } ;
13351 +
13352 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
13353 +       
13354 +}
13355 +
13356 +static int
13357 +ipt_fuzzy_checkentry(const char *tablename,
13358 +                  const struct ipt_ip *e,
13359 +                  void *matchinfo,
13360 +                  unsigned int matchsize,
13361 +                  unsigned int hook_mask)
13362 +{
13363 +       
13364 +       const struct ipt_fuzzy_info *info = matchinfo;
13365 +
13366 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
13367 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
13368 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
13369 +               return 0;
13370 +       }
13371 +
13372 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
13373 +       || (info->minimum_rate >= info->maximum_rate ))
13374 +               {
13375 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
13376 +               return 0;
13377 +               }
13378 +
13379 +       return 1;
13380 +}
13381 +
13382 +static struct ipt_match ipt_fuzzy_reg = { 
13383 +       {NULL, NULL},
13384 +       "fuzzy",
13385 +       ipt_fuzzy_match,
13386 +       ipt_fuzzy_checkentry,
13387 +       NULL,
13388 +       THIS_MODULE };
13389 +
13390 +static int __init init(void)
13391 +{
13392 +       if (ipt_register_match(&ipt_fuzzy_reg))
13393 +               return -EINVAL;
13394 +
13395 +       return 0;
13396 +}
13397 +
13398 +static void __exit fini(void)
13399 +{
13400 +       ipt_unregister_match(&ipt_fuzzy_reg);
13401 +}
13402 +
13403 +module_init(init);
13404 +module_exit(fini);
13405 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
13406 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPMARK.c      1970-01-01 01:00:00.000000000 +0100
13407 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPMARK.c  2003-12-11 10:23:52.557947952 +0100
13408 @@ -0,0 +1,88 @@
13409 +/* This is a module which is used for setting the NFMARK field of an skb. */
13410 +#include <linux/module.h>
13411 +#include <linux/skbuff.h>
13412 +#include <linux/ip.h>
13413 +#include <net/checksum.h>
13414 +
13415 +#include <linux/netfilter_ipv4/ip_tables.h>
13416 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
13417 +
13418 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
13419 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
13420 +MODULE_LICENSE("GPL");
13421 +
13422 +static unsigned int
13423 +target(struct sk_buff **pskb,
13424 +       unsigned int hooknum,
13425 +       const struct net_device *in,
13426 +       const struct net_device *out,
13427 +       const void *targinfo,
13428 +       void *userinfo)
13429 +{
13430 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
13431 +
13432 +       struct iphdr *iph = (*pskb)->nh.iph;
13433 +
13434 +       unsigned long mark;
13435 +       char *a, t;
13436 +
13437 +       if(ipmarkinfo->addr == IPT_IPMARK_SRC)
13438 +         mark = (unsigned long) iph->saddr;
13439 +       else
13440 +         mark = (unsigned long) iph->daddr;
13441 +
13442 +// mark has ip address in little indian, we have to change the byte order:
13443 +       a = (char *) &mark;
13444 +       t = *a; *a=*(a+3); *(a+3)=t;
13445 +       t=*(a+1); *(a+1)=*(a+2); *(a+2)=t;
13446 +
13447 +       mark &= ipmarkinfo->andmask;
13448 +       mark |= ipmarkinfo->ormask;
13449 +       
13450 +       if((*pskb)->nfmark != mark) {
13451 +               (*pskb)->nfmark = mark;
13452 +               (*pskb)->nfcache |= NFC_ALTERED;
13453 +       }
13454 +       return IPT_CONTINUE;
13455 +}
13456 +
13457 +static int
13458 +checkentry(const char *tablename,
13459 +          const struct ipt_entry *e,
13460 +           void *targinfo,
13461 +           unsigned int targinfosize,
13462 +           unsigned int hook_mask)
13463 +{
13464 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
13465 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
13466 +                      targinfosize,
13467 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
13468 +               return 0;
13469 +       }
13470 +
13471 +       if (strcmp(tablename, "mangle") != 0) {
13472 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13473 +               return 0;
13474 +       }
13475 +
13476 +       return 1;
13477 +}
13478 +
13479 +static struct ipt_target ipt_ipmark_reg
13480 += { { NULL, NULL }, "IPMARK", target, checkentry, NULL, THIS_MODULE };
13481 +
13482 +static int __init init(void)
13483 +{
13484 +       if (ipt_register_target(&ipt_ipmark_reg))
13485 +               return -EINVAL;
13486 +
13487 +       return 0;
13488 +}
13489 +
13490 +static void __exit fini(void)
13491 +{
13492 +       ipt_unregister_target(&ipt_ipmark_reg);
13493 +}
13494 +
13495 +module_init(init);
13496 +module_exit(fini);
13497 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
13498 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
13499 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ipv4options.c     2003-12-11 10:23:25.055129016 +0100
13500 @@ -0,0 +1,170 @@
13501 +/*
13502 +  This is a module which is used to match ipv4 options.
13503 +  This file is distributed under the terms of the GNU General Public
13504 +  License (GPL). Copies of the GPL can be obtained from:
13505 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
13506 +
13507 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
13508 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
13509 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
13510 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
13511 +*/
13512 +
13513 +#include <linux/module.h>
13514 +#include <linux/skbuff.h>
13515 +#include <net/ip.h>
13516 +
13517 +#include <linux/netfilter_ipv4/ip_tables.h>
13518 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
13519 +
13520 +MODULE_LICENSE("GPL");
13521 +
13522 +static int
13523 +match(const struct sk_buff *skb,
13524 +      const struct net_device *in,
13525 +      const struct net_device *out,
13526 +      const void *matchinfo,
13527 +      int offset,
13528 +      const void *hdr,
13529 +      u_int16_t datalen,
13530 +      int *hotdrop)
13531 +{
13532 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
13533 +       const struct iphdr *iph = skb->nh.iph;
13534 +       const struct ip_options *opt;
13535 +
13536 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
13537 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
13538 +
13539 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
13540 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13541 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13542 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13543 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13544 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
13545 +                       return 0;
13546 +               return 1;
13547 +       }
13548 +       else {
13549 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
13550 +                       /* there are options, and we don't need to care which one */
13551 +                       return 1;
13552 +               else {
13553 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
13554 +                               /* there are options but we don't want any ! */
13555 +                               return 0;
13556 +               }
13557 +       }
13558 +
13559 +       opt = &(IPCB(skb)->opt);
13560 +
13561 +       /* source routing */
13562 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
13563 +               if (!((opt->srr) & (opt->is_strictroute)))
13564 +                       return 0;
13565 +       }
13566 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
13567 +               if (!((opt->srr) & (!opt->is_strictroute)))
13568 +                       return 0;
13569 +       }
13570 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
13571 +               if (opt->srr)
13572 +                       return 0;
13573 +       }
13574 +       /* record route */
13575 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
13576 +               if (!opt->rr)
13577 +                       return 0;
13578 +       }
13579 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
13580 +               if (opt->rr)
13581 +                       return 0;
13582 +       }
13583 +       /* timestamp */
13584 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
13585 +               if (!opt->ts)
13586 +                       return 0;
13587 +       }
13588 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
13589 +               if (opt->ts)
13590 +                       return 0;
13591 +       }
13592 +       /* router-alert option  */
13593 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
13594 +               if (!opt->router_alert)
13595 +                       return 0;
13596 +       }
13597 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
13598 +               if (opt->router_alert)
13599 +                       return 0;
13600 +       }
13601 +
13602 +       /* we match ! */
13603 +       return 1;
13604 +}
13605 +
13606 +static int
13607 +checkentry(const char *tablename,
13608 +          const struct ipt_ip *ip,
13609 +          void *matchinfo,
13610 +          unsigned int matchsize,
13611 +          unsigned int hook_mask)
13612 +{
13613 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
13614 +       /* Check the size */
13615 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
13616 +               return 0;
13617 +       /* Now check the coherence of the data ... */
13618 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
13619 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
13620 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
13621 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
13622 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
13623 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
13624 +               return 0; /* opposites */
13625 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
13626 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
13627 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13628 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
13629 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
13630 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
13631 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
13632 +               return 0; /* opposites */
13633 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
13634 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
13635 +               return 0; /* cannot match in the same time loose and strict source routing */
13636 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
13637 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
13638 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
13639 +               return 0; /* opposites */
13640 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
13641 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
13642 +               return 0; /* opposites */
13643 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
13644 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
13645 +               return 0; /* opposites */
13646 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
13647 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
13648 +               return 0; /* opposites */
13649 +
13650 +       /* everything looks ok. */
13651 +       return 1;
13652 +}
13653 +
13654 +static struct ipt_match ipv4options_match
13655 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
13656 +
13657 +static int __init init(void)
13658 +{
13659 +       printk("ipt_ipv4options loading\n");
13660 +       return ipt_register_match(&ipv4options_match);
13661 +}
13662 +
13663 +static void __exit fini(void)
13664 +{
13665 +       ipt_unregister_match(&ipv4options_match);
13666 +       printk("ipt_ipv4options unloaded\n");
13667 +}
13668 +
13669 +module_init(init);
13670 +module_exit(fini);
13671 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
13672 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c       1970-01-01 01:00:00.000000000 +0100
13673 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c   2003-12-11 10:23:26.189956496 +0100
13674 @@ -0,0 +1,84 @@
13675 +/**
13676 + * Strip all IP options in the IP packet header.
13677 + *
13678 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
13679 + * This software is distributed under GNU GPL v2, 1991
13680 + */
13681 +
13682 +#include <linux/module.h>
13683 +#include <linux/skbuff.h>
13684 +#include <linux/ip.h>
13685 +#include <net/checksum.h>
13686 +
13687 +#include <linux/netfilter_ipv4/ip_tables.h>
13688 +
13689 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
13690 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
13691 +MODULE_LICENSE("GPL");
13692 +
13693 +static unsigned int
13694 +target(struct sk_buff **pskb,
13695 +       unsigned int hooknum,
13696 +       const struct net_device *in,
13697 +       const struct net_device *out,
13698 +       const void *targinfo,
13699 +       void *userinfo)
13700 +{
13701 +       struct iphdr *iph = (*pskb)->nh.iph;
13702 +       struct sk_buff *skb = (*pskb);
13703 +       struct ip_options * opt;
13704 +       unsigned char * optiph = skb->nh.raw;
13705 +       int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
13706 +       
13707 +
13708 +       /* if no options in packet then nothing to clear. */
13709 +       if (iph->ihl * 4 == sizeof(struct iphdr))
13710 +               return IPT_CONTINUE;
13711 +
13712 +       /* else clear all options */
13713 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
13714 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
13715 +       opt = &(IPCB(skb)->opt);
13716 +       opt->is_data = 0;
13717 +       opt->optlen = l;
13718 +
13719 +       skb->nfcache |= NFC_ALTERED;
13720 +
13721 +        return IPT_CONTINUE;
13722 +}
13723 +
13724 +static int
13725 +checkentry(const char *tablename,
13726 +          const struct ipt_entry *e,
13727 +           void *targinfo,
13728 +           unsigned int targinfosize,
13729 +           unsigned int hook_mask)
13730 +{
13731 +       if (strcmp(tablename, "mangle")) {
13732 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
13733 +               return 0;
13734 +       }
13735 +       /* nothing else to check because no parameters */
13736 +       return 1;
13737 +}
13738 +
13739 +static struct ipt_target ipt_ipv4optsstrip_reg
13740 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
13741 +
13742 +static int __init init(void)
13743 +{
13744 +       if (ipt_register_target(&ipt_ipv4optsstrip_reg))
13745 +               return -EINVAL;
13746 +       printk("ipt_IPV4OPTSSTRIP loaded\n");
13747 +
13748 +       return 0;
13749 +}
13750 +
13751 +static void __exit fini(void)
13752 +{
13753 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
13754 +       printk("ipt_IPV4OPTSSTRIP unloaded\n");
13755 +}
13756 +
13757 +module_init(init);
13758 +module_exit(fini);
13759 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
13760 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_LOG.c 2003-11-26 21:45:28.000000000 +0100
13761 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_LOG.c     2003-12-11 10:23:14.922669384 +0100
13762 @@ -4,12 +4,14 @@
13763  #include <linux/module.h>
13764  #include <linux/spinlock.h>
13765  #include <linux/skbuff.h>
13766 +#include <linux/socket.h>
13767  #include <linux/ip.h>
13768  #include <net/icmp.h>
13769  #include <net/udp.h>
13770  #include <net/tcp.h>
13771  #include <net/route.h>
13772  
13773 +#include <linux/netfilter.h>
13774  #include <linux/netfilter_ipv4/ip_tables.h>
13775  #include <linux/netfilter_ipv4/ipt_LOG.h>
13776  
13777 @@ -17,6 +19,10 @@
13778  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
13779  MODULE_DESCRIPTION("iptables syslog logging module");
13780  
13781 +static unsigned int nflog = 1;
13782 +MODULE_PARM(nflog, "i");
13783 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
13784 +
13785  #if 0
13786  #define DEBUGP printk
13787  #else
13788 @@ -315,28 +321,25 @@
13789         /* maxlen = 230+   91  + 230 + 252 = 803 */
13790  }
13791  
13792 -static unsigned int
13793 -ipt_log_target(struct sk_buff **pskb,
13794 +static void
13795 +ipt_log_packet(unsigned int hooknum,
13796 +              const struct sk_buff *skb,
13797                const struct net_device *in,
13798                const struct net_device *out,
13799 -              unsigned int hooknum,
13800 -              const void *targinfo,
13801 -              void *userinfo)
13802 +              const struct ipt_log_info *loginfo,
13803 +              const char *level_string,
13804 +              const char *prefix)
13805  {
13806 -       const struct ipt_log_info *loginfo = targinfo;
13807 -       char level_string[4] = "< >";
13808 -
13809 -       level_string[1] = '0' + (loginfo->level % 8);
13810         spin_lock_bh(&log_lock);
13811         printk(level_string);
13812         printk("%sIN=%s OUT=%s ",
13813 -              loginfo->prefix,
13814 +              prefix == NULL ? loginfo->prefix : prefix,
13815                in ? in->name : "",
13816                out ? out->name : "");
13817  #ifdef CONFIG_BRIDGE_NETFILTER
13818 -       if ((*pskb)->nf_bridge) {
13819 -               struct net_device *physindev = (*pskb)->nf_bridge->physindev;
13820 -               struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev;
13821 +       if (skb->nf_bridge) {
13822 +               struct net_device *physindev = skb->nf_bridge->physindev;
13823 +               struct net_device *physoutdev = skb->nf_bridge->physoutdev;
13824  
13825                 if (physindev && in != physindev)
13826                         printk("PHYSIN=%s ", physindev->name);
13827 @@ -348,25 +351,56 @@
13828         if (in && !out) {
13829                 /* MAC logging for input chain only. */
13830                 printk("MAC=");
13831 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len
13832 -                   && (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) {
13833 +               if (skb->dev && skb->dev->hard_header_len
13834 +                   && skb->mac.raw != (void*)skb->nh.iph) {
13835                         int i;
13836 -                       unsigned char *p = (*pskb)->mac.raw;
13837 -                       for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
13838 +                       unsigned char *p = skb->mac.raw;
13839 +                       for (i = 0; i < skb->dev->hard_header_len; i++,p++)
13840                                 printk("%02x%c", *p,
13841 -                                      i==(*pskb)->dev->hard_header_len - 1
13842 +                                      i==skb->dev->hard_header_len - 1
13843                                        ? ' ':':');
13844                 } else
13845                         printk(" ");
13846         }
13847  
13848 -       dump_packet(loginfo, *pskb, 0);
13849 +       dump_packet(loginfo, skb, 0);
13850         printk("\n");
13851         spin_unlock_bh(&log_lock);
13852 +}
13853 +
13854 +static unsigned int
13855 +ipt_log_target(struct sk_buff **pskb,
13856 +              const struct net_device *in,
13857 +              const struct net_device *out,
13858 +              unsigned int hooknum,
13859 +              const void *targinfo,
13860 +              void *userinfo)
13861 +{
13862 +       const struct ipt_log_info *loginfo = targinfo;
13863 +       char level_string[4] = "< >";
13864 +
13865 +       level_string[1] = '0' + (loginfo->level % 8);
13866 +       ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
13867  
13868         return IPT_CONTINUE;
13869  }
13870  
13871 +static void
13872 +ipt_logfn(unsigned int hooknum,
13873 +         const struct sk_buff *skb,
13874 +         const struct net_device *in,
13875 +         const struct net_device *out,
13876 +         const char *prefix)
13877 +{
13878 +       struct ipt_log_info loginfo = { 
13879 +               .level = 0, 
13880 +               .logflags = IPT_LOG_MASK, 
13881 +               .prefix = "" 
13882 +       };
13883 +
13884 +       ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
13885 +}
13886 +
13887  static int ipt_log_checkentry(const char *tablename,
13888                               const struct ipt_entry *e,
13889                               void *targinfo,
13890 @@ -406,12 +440,17 @@
13891  {
13892         if (ipt_register_target(&ipt_log_reg))
13893                 return -EINVAL;
13894 +       if (nflog)
13895 +               nf_log_register(PF_INET, &ipt_logfn);
13896  
13897         return 0;
13898  }
13899  
13900  static void __exit fini(void)
13901  {
13902 +       if (nflog)
13903 +               nf_log_unregister(PF_INET, &ipt_logfn);
13904 +
13905         ipt_unregister_target(&ipt_log_reg);
13906  }
13907  
13908 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
13909 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mark.c        2003-11-26 21:46:13.000000000 +0100
13910 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mark.c    2003-12-11 10:24:14.940545280 +0100
13911 @@ -17,9 +17,15 @@
13912        int offset,
13913        int *hotdrop)
13914  {
13915 -       const struct ipt_mark_info *info = matchinfo;
13916 +       const struct ipt_mark_info *info = (struct ipt_mark_info *)matchinfo;
13917  
13918 -       return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13919 +       if (info->bit_op == IPT_MARK_BIT_OP_NONE)
13920 +               return (skb->nfmark == info->mark) ^ info->invert;
13921 +       else
13922 +               if (info->bit_op == IPT_MARK_BIT_OP_AND)
13923 +                       return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
13924 +               else
13925 +                       return ((skb->nfmark | info->mask) == info->mark) ^ info->invert;
13926  }
13927  
13928  static int
13929 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
13930 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_mport.c       1970-01-01 01:00:00.000000000 +0100
13931 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_mport.c   2003-12-11 10:23:27.304787016 +0100
13932 @@ -0,0 +1,112 @@
13933 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
13934 +   the same place so we can treat them as equal. */
13935 +#include <linux/module.h>
13936 +#include <linux/types.h>
13937 +#include <linux/udp.h>
13938 +#include <linux/skbuff.h>
13939 +
13940 +#include <linux/netfilter_ipv4/ipt_mport.h>
13941 +#include <linux/netfilter_ipv4/ip_tables.h>
13942 +
13943 +MODULE_LICENSE("GPL");
13944 +
13945 +#if 0
13946 +#define duprintf(format, args...) printk(format , ## args)
13947 +#else
13948 +#define duprintf(format, args...)
13949 +#endif
13950 +
13951 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
13952 +static inline int
13953 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
13954 +{
13955 +       unsigned int i;
13956 +        unsigned int m;
13957 +        u_int16_t pflags = minfo->pflags;
13958 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
13959 +                u_int16_t s, e;
13960 +
13961 +                if (pflags & m
13962 +                    && minfo->ports[i] == 65535)
13963 +                        return 0;
13964 +
13965 +                s = minfo->ports[i];
13966 +
13967 +                if (pflags & m) {
13968 +                        e = minfo->ports[++i];
13969 +                        m <<= 1;
13970 +                } else
13971 +                        e = s;
13972 +
13973 +                if (minfo->flags & IPT_MPORT_SOURCE
13974 +                    && src >= s && src <= e)
13975 +                        return 1;
13976 +
13977 +               if (minfo->flags & IPT_MPORT_DESTINATION
13978 +                   && dst >= s && dst <= e)
13979 +                       return 1;
13980 +       }
13981 +
13982 +       return 0;
13983 +}
13984 +
13985 +static int
13986 +match(const struct sk_buff *skb,
13987 +      const struct net_device *in,
13988 +      const struct net_device *out,
13989 +      const void *matchinfo,
13990 +      int offset,
13991 +      const void *hdr,
13992 +      u_int16_t datalen,
13993 +      int *hotdrop)
13994 +{
13995 +       const struct udphdr *udp = hdr;
13996 +       const struct ipt_mport *minfo = matchinfo;
13997 +
13998 +       /* Must be big enough to read ports. */
13999 +       if (offset == 0 && datalen < sizeof(struct udphdr)) {
14000 +               /* We've been asked to examine this packet, and we
14001 +                  can't.  Hence, no choice but to drop. */
14002 +                       duprintf("ipt_mport:"
14003 +                                " Dropping evil offset=0 tinygram.\n");
14004 +                       *hotdrop = 1;
14005 +                       return 0;
14006 +       }
14007 +
14008 +       /* Must not be a fragment. */
14009 +       return !offset
14010 +               && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
14011 +}
14012 +
14013 +/* Called when user tries to insert an entry of this type. */
14014 +static int
14015 +checkentry(const char *tablename,
14016 +          const struct ipt_ip *ip,
14017 +          void *matchinfo,
14018 +          unsigned int matchsize,
14019 +          unsigned int hook_mask)
14020 +{
14021 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
14022 +               return 0;
14023 +
14024 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
14025 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
14026 +               && !(ip->invflags & IPT_INV_PROTO)
14027 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
14028 +}
14029 +
14030 +static struct ipt_match mport_match
14031 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
14032 +
14033 +static int __init init(void)
14034 +{
14035 +       return ipt_register_match(&mport_match);
14036 +}
14037 +
14038 +static void __exit fini(void)
14039 +{
14040 +       ipt_unregister_match(&mport_match);
14041 +}
14042 +
14043 +module_init(init);
14044 +module_exit(fini);
14045 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
14046 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_NOTRACK.c     1970-01-01 01:00:00.000000000 +0100
14047 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_NOTRACK.c 2003-12-11 10:23:17.229318720 +0100
14048 @@ -0,0 +1,79 @@
14049 +/* This is a module which is used for setting up fake conntracks
14050 + * on packets so that they are not seen by the conntrack/NAT code.
14051 + */
14052 +#include <linux/module.h>
14053 +#include <linux/skbuff.h>
14054 +
14055 +#include <linux/netfilter_ipv4/ip_tables.h>
14056 +#include <linux/netfilter_ipv4/ip_conntrack.h>
14057 +
14058 +static unsigned int
14059 +target(struct sk_buff **pskb,
14060 +       const struct net_device *in,
14061 +       const struct net_device *out,
14062 +       unsigned int hooknum,
14063 +       const void *targinfo,
14064 +       void *userinfo)
14065 +{
14066 +       /* Previously seen (loopback)? Ignore. */
14067 +       if ((*pskb)->nfct != NULL)
14068 +               return IPT_CONTINUE;
14069 +
14070 +       /* Attach fake conntrack entry. 
14071 +          If there is a real ct entry correspondig to this packet, 
14072 +          it'll hang aroun till timing out. We don't deal with it
14073 +          for performance reasons. JK */
14074 +       (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
14075 +       nf_conntrack_get((*pskb)->nfct);
14076 +
14077 +       return IPT_CONTINUE;
14078 +}
14079 +
14080 +static int
14081 +checkentry(const char *tablename,
14082 +          const struct ipt_entry *e,
14083 +           void *targinfo,
14084 +           unsigned int targinfosize,
14085 +           unsigned int hook_mask)
14086 +{
14087 +       if (targinfosize != 0) {
14088 +               printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
14089 +                      targinfosize);
14090 +               return 0;
14091 +       }
14092 +
14093 +       if (strcmp(tablename, "raw") != 0) {
14094 +               printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
14095 +               return 0;
14096 +       }
14097 +
14098 +       return 1;
14099 +}
14100 +
14101 +static struct ipt_target ipt_notrack_reg = { 
14102 +       .name           = "NOTRACK", 
14103 +       .target         = target, 
14104 +       .checkentry     = checkentry, 
14105 +       .destroy        = NULL, 
14106 +       .me             = THIS_MODULE,
14107 +};
14108 +
14109 +static int __init init(void)
14110 +{
14111 +       if (ipt_register_target(&ipt_notrack_reg))
14112 +               return -EINVAL;
14113 +
14114 +       return 0;
14115 +}
14116 +
14117 +static void __exit fini(void)
14118 +{
14119 +       ipt_unregister_target(&ipt_notrack_reg);
14120 +}
14121 +
14122 +module_init(init);
14123 +module_exit(fini);
14124 +
14125 +MODULE_LICENSE("GPL");
14126 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
14127 +MODULE_DESCRIPTION("IPv4 NOTRACK target");
14128 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
14129 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
14130 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_nth.c     2003-12-11 10:23:30.640279944 +0100
14131 @@ -0,0 +1,172 @@
14132 +/*
14133 +  This is a module which is used for match support for every Nth packet
14134 +  This file is distributed under the terms of the GNU General Public
14135 +  License (GPL). Copies of the GPL can be obtained from:
14136 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
14137 +
14138 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14139 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
14140 +        * added support for multiple counters
14141 +        * added support for matching on individual packets
14142 +          in the counter cycle
14143 +
14144 +*/
14145 +
14146 +#include <linux/module.h>
14147 +#include <linux/skbuff.h>
14148 +#include <linux/ip.h>
14149 +#include <net/tcp.h>
14150 +#include <linux/spinlock.h>
14151 +#include <linux/netfilter_ipv4/ip_tables.h>
14152 +#include <linux/netfilter_ipv4/ipt_nth.h>
14153 +
14154 +MODULE_LICENSE("GPL");
14155 +
14156 +/*
14157 + * State information.
14158 + */
14159 +struct state {
14160 +       spinlock_t lock;
14161 +       u_int16_t number;
14162 +};
14163 +
14164 +static struct state states[IPT_NTH_NUM_COUNTERS];
14165 +
14166 +static int
14167 +ipt_nth_match(const struct sk_buff *pskb,
14168 +             const struct net_device *in,
14169 +             const struct net_device *out,
14170 +             const void *matchinfo,
14171 +             int offset,
14172 +             const void *hdr,
14173 +             u_int16_t datalen,
14174 +             int *hotdrop)
14175 +{
14176 +       /* Parameters from userspace */
14177 +       const struct ipt_nth_info *info = matchinfo;
14178 +        unsigned counter = info->counter;
14179 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
14180 +       {
14181 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14182 +               return 0;
14183 +        };
14184 +
14185 +        spin_lock(&states[counter].lock);
14186 +
14187 +        /* Are we matching every nth packet?*/
14188 +        if (info->packet == 0xFF)
14189 +        {
14190 +               /* We're matching every nth packet and only every nth packet*/
14191 +               /* Do we match or invert match? */
14192 +               if (info->not == 0)
14193 +               {
14194 +                       if (states[counter].number == 0)
14195 +                       {
14196 +                               ++states[counter].number;
14197 +                               goto match;
14198 +                       }
14199 +                       if (states[counter].number >= info->every)
14200 +                               states[counter].number = 0; /* reset the counter */
14201 +                       else
14202 +                               ++states[counter].number;
14203 +                       goto dontmatch;
14204 +               }
14205 +               else
14206 +               {
14207 +                       if (states[counter].number == 0)
14208 +                       {
14209 +                               ++states[counter].number;
14210 +                               goto dontmatch;
14211 +                       }
14212 +                       if (states[counter].number >= info->every)
14213 +                               states[counter].number = 0;
14214 +                       else
14215 +                               ++states[counter].number;
14216 +                       goto match;
14217 +               }
14218 +        }
14219 +        else
14220 +        {
14221 +               /* We're using the --packet, so there must be a rule for every value */
14222 +               if (states[counter].number == info->packet)
14223 +               {
14224 +                       /* only increment the counter when a match happens */
14225 +                       if (states[counter].number >= info->every)
14226 +                               states[counter].number = 0; /* reset the counter */
14227 +                       else
14228 +                               ++states[counter].number;
14229 +                       goto match;
14230 +               }
14231 +               else
14232 +                       goto dontmatch;
14233 +       }
14234 +
14235 + dontmatch:
14236 +       /* don't match */
14237 +       spin_unlock(&states[counter].lock);
14238 +       return 0;
14239 +
14240 + match:
14241 +       spin_unlock(&states[counter].lock);
14242 +       return 1;
14243 +}
14244 +
14245 +static int
14246 +ipt_nth_checkentry(const char *tablename,
14247 +                  const struct ipt_ip *e,
14248 +                  void *matchinfo,
14249 +                  unsigned int matchsize,
14250 +                  unsigned int hook_mask)
14251 +{
14252 +       /* Parameters from userspace */
14253 +       const struct ipt_nth_info *info = matchinfo;
14254 +        unsigned counter = info->counter;
14255 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
14256 +       {
14257 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
14258 +                       return 0;
14259 +               };
14260 +
14261 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
14262 +               printk("nth: matchsize %u != %u\n", matchsize,
14263 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
14264 +               return 0;
14265 +       }
14266 +
14267 +       states[counter].number = info->startat;
14268 +
14269 +       return 1;
14270 +}
14271 +
14272 +static struct ipt_match ipt_nth_reg = { 
14273 +       {NULL, NULL},
14274 +       "nth",
14275 +       ipt_nth_match,
14276 +       ipt_nth_checkentry,
14277 +       NULL,
14278 +       THIS_MODULE };
14279 +
14280 +static int __init init(void)
14281 +{
14282 +       unsigned counter;
14283 +        memset(&states, 0, sizeof(states));
14284 +       if (ipt_register_match(&ipt_nth_reg))
14285 +               return -EINVAL;
14286 +
14287 +        for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
14288 +       {
14289 +               spin_lock_init(&(states[counter].lock));
14290 +        };
14291 +
14292 +       printk("ipt_nth match loaded\n");
14293 +       return 0;
14294 +}
14295 +
14296 +static void __exit fini(void)
14297 +{
14298 +       ipt_unregister_match(&ipt_nth_reg);
14299 +       printk("ipt_nth match unloaded\n");
14300 +}
14301 +
14302 +module_init(init);
14303 +module_exit(fini);
14304 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
14305 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
14306 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_osf.c     2003-12-11 10:23:31.784106056 +0100
14307 @@ -0,0 +1,699 @@
14308 +/*
14309 + * ipt_osf.c
14310 + *
14311 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
14312 + *
14313 + *
14314 + * This program is free software; you can redistribute it and/or modify
14315 + * it under the terms of the GNU General Public License as published by
14316 + * the Free Software Foundation; either version 2 of the License, or
14317 + * (at your option) any later version.
14318 + *
14319 + * This program is distributed in the hope that it will be useful,
14320 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14321 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14322 + * GNU General Public License for more details.
14323 + *
14324 + * You should have received a copy of the GNU General Public License
14325 + * along with this program; if not, write to the Free Software
14326 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14327 + */
14328 +
14329 +/*
14330 + * OS fingerprint matching module.
14331 + * It simply compares various parameters from SYN packet with
14332 + * some hardcoded ones.
14333 + *
14334 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
14335 + * for his p0f.
14336 + */
14337 +
14338 +#include <linux/smp.h>
14339 +#include <linux/module.h>
14340 +#include <linux/skbuff.h>
14341 +#include <linux/file.h>
14342 +#include <linux/ip.h>
14343 +#include <linux/proc_fs.h>
14344 +#include <linux/fs.h>
14345 +#include <linux/slab.h>
14346 +#include <linux/spinlock.h>
14347 +#include <linux/ctype.h>
14348 +#include <linux/list.h>
14349 +
14350 +#include <net/sock.h>
14351 +#include <net/ip.h>
14352 +
14353 +#include <linux/netfilter_ipv4/ip_tables.h>
14354 +
14355 +#include <linux/netfilter_ipv4/ipt_osf.h>
14356 +
14357 +//#define OSF_DEBUG
14358 +
14359 +#ifdef OSF_DEBUG
14360 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
14361 +#define loga(x...)             printk(x)
14362 +#else
14363 +#define log(x...)              do {} while(0)
14364 +#define loga(x...)             do {} while(0)
14365 +#endif
14366 +
14367 +#define FMATCH_WRONG           0
14368 +#define FMATCH_OK              1
14369 +#define FMATCH_OPT_WRONG       2
14370 +
14371 +#define OPTDEL                 ','
14372 +#define OSFPDEL                ':'
14373 +#define MAXOPTSTRLEN           128
14374 +#define OSFFLUSH               "FLUSH"
14375 +
14376 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
14377 +static struct list_head        finger_list;    
14378 +
14379 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
14380 +                     const void *, int, const void *, u_int16_t, int *);
14381 +static int checkentry(const char *, const struct ipt_ip *, void *,
14382 +                          unsigned int, unsigned int);
14383 +
14384 +static struct ipt_match osf_match = 
14385 +{ 
14386 +       { NULL, NULL }, 
14387 +       "osf", 
14388 +       &match, 
14389 +       &checkentry, 
14390 +       NULL, 
14391 +       THIS_MODULE 
14392 +};
14393 +
14394 +static int
14395 +match(const struct sk_buff *skb,
14396 +      const struct net_device *in,
14397 +      const struct net_device *out,
14398 +      const void *matchinfo,
14399 +      int offset,
14400 +      const void *hdr,
14401 +      u_int16_t datalen,
14402 +      int *hotdrop)
14403 +{
14404 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
14405 +       struct iphdr *ip = skb->nh.iph;
14406 +       struct tcphdr *tcp;
14407 +       int fmatch = FMATCH_WRONG;
14408 +       unsigned long totlen, optsize = 0, window;
14409 +       unsigned char df, *optp = NULL, *_optp = NULL;
14410 +       char check_WSS = 0;
14411 +       struct list_head *ent;
14412 +       struct osf_finger *f;
14413 +
14414 +       if (!ip || !info)
14415 +               return 0;
14416 +                               
14417 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
14418 +
14419 +       if (!tcp->syn)
14420 +               return 0;
14421 +       
14422 +       totlen = ntohs(ip->tot_len);
14423 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
14424 +       window = ntohs(tcp->window);
14425 +       
14426 +       if (tcp->doff*4 > sizeof(struct tcphdr))
14427 +       {
14428 +               _optp = optp = (char *)(tcp+1);
14429 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
14430 +       }
14431 +
14432 +       
14433 +       /* Actually we can create hash/table of all genres and search
14434 +        * only in appropriate part, but here is initial variant,
14435 +        * so will use slow path.
14436 +        */
14437 +       read_lock(&osf_lock);
14438 +       list_for_each(ent, &finger_list)
14439 +       {
14440 +               f = list_entry(ent, struct osf_finger, flist);
14441 +               
14442 +               if (strcmp(info->genre, f->genre)) 
14443 +                       continue;
14444 +
14445 +               optp = _optp;
14446 +
14447 +               if (    ip->ttl == f->ttl &&
14448 +                       totlen  == f->ss &&
14449 +                       df      == f->df)
14450 +               {
14451 +                       unsigned long foptsize;
14452 +                       int optnum;
14453 +                       unsigned short mss = 0;
14454 +
14455 +                       check_WSS = 0;
14456 +
14457 +                       switch (f->wss.wc)
14458 +                       {
14459 +                               case 0:   check_WSS = 0; break;
14460 +                               case 'S': check_WSS = 1; break;
14461 +                               case 'T': check_WSS = 2; break;
14462 +                               case '%': check_WSS = 3; break;
14463 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
14464 +                                                        f->wss.wc, f->genre, f->details);
14465 +                                        check_WSS = 4;
14466 +                                        break;
14467 +                       }
14468 +                       if (check_WSS == 4)
14469 +                               continue;
14470 +
14471 +                       /* Check options */
14472 +
14473 +                       foptsize = 0;
14474 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
14475 +                               foptsize += f->opt[optnum].length;
14476 +
14477 +                               
14478 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
14479 +                               continue;
14480 +
14481 +                       if (!optp)
14482 +                       {
14483 +                               fmatch = FMATCH_OK;
14484 +                               loga("\tYEP : matching without options.\n");
14485 +                               break;
14486 +                       }
14487 +                       
14488 +
14489 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
14490 +                       {
14491 +                               if (f->opt[optnum].kind == (*optp))
14492 +                               {
14493 +                                       unsigned char len = f->opt[optnum].length;
14494 +                                       unsigned char *optend = optp + len;
14495 +
14496 +                                       fmatch = FMATCH_OK;
14497 +
14498 +                                       if (*optp == OSFOPT_MSS) /* MSS */
14499 +                                               mss = ntohs(*(unsigned short *)(optp+2));
14500 +                                       
14501 +                                       if (len != 1)
14502 +                                       {
14503 +                                               /* Skip kind and length fields*/
14504 +                                               optp += 2; 
14505 +
14506 +                                               if (f->opt[optnum].wc.wc != 0)
14507 +                                               {
14508 +                                                       unsigned long tmp = 0;
14509 +                                                       
14510 +                                                       /* Hmmm... It looks a bit ugly. :) */
14511 +                                                       memcpy(&tmp, &f->opt[optnum].wc.val, 
14512 +                                                               (len > sizeof(unsigned long)?
14513 +                                                                       sizeof(unsigned long):len));
14514 +
14515 +                                                       tmp = ntohl(tmp);
14516 +                                                       if (tmp != f->opt[optnum].wc.val)
14517 +                                                               fmatch = FMATCH_OPT_WRONG;
14518 +                                               }
14519 +                                       }
14520 +
14521 +                                       optp = optend;
14522 +                               }
14523 +                               else
14524 +                                       fmatch = FMATCH_OPT_WRONG;
14525 +
14526 +                               if (fmatch != FMATCH_OK)
14527 +                                       break;
14528 +                       }
14529 +
14530 +                       if (fmatch != FMATCH_OPT_WRONG)
14531 +                       {
14532 +                               fmatch = FMATCH_WRONG;
14533 +
14534 +                               switch (check_WSS)
14535 +                               {
14536 +                                       case 0:
14537 +                                               if (window == f->wss.val)
14538 +                                                       fmatch = FMATCH_OK;
14539 +                                               break;
14540 +                                       case 1: /* MSS */
14541 +                                               if (window == f->wss.val*mss)
14542 +                                                       fmatch = FMATCH_OK;
14543 +                                               break;
14544 +                                       case 2: /* MTU */
14545 +                                               if (window == f->wss.val*(mss+40))
14546 +                                                       fmatch = FMATCH_OK;
14547 +                                               break;
14548 +                                       case 3: /* MOD */
14549 +                                               if (window % f->wss.val == 0)
14550 +                                                       fmatch = FMATCH_OK;
14551 +                                               break;
14552 +                               }
14553 +                       }
14554 +                                       
14555 +
14556 +                       if (fmatch == FMATCH_OK)
14557 +                       {
14558 +
14559 +                               log("genre %s[%25s]: ttl=%d, size=%lu, df=%d, "
14560 +                                       "check_WSS=%d, win=%lu, optsize=%lu:\n", 
14561 +                                       f->genre, f->details, 
14562 +                                       ip->ttl, totlen, df, 
14563 +                                       check_WSS, window, optsize);
14564 +                               break;
14565 +                       }
14566 +               }
14567 +       }
14568 +       read_unlock(&osf_lock);
14569 +
14570 +       return (fmatch == FMATCH_OK)?1:0;
14571 +}
14572 +
14573 +static int
14574 +checkentry(const char *tablename,
14575 +           const struct ipt_ip *ip,
14576 +           void *matchinfo,
14577 +           unsigned int matchsize,
14578 +           unsigned int hook_mask)
14579 +{
14580 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
14581 +               return 0;
14582 +       if (ip->proto != IPPROTO_TCP)
14583 +              return 0;
14584 +
14585 +       return 1;
14586 +}
14587 +
14588 +static char * osf_strchr(char *ptr, char c)
14589 +{
14590 +       char *tmp;
14591 +
14592 +       tmp = strchr(ptr, c);
14593 +
14594 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
14595 +               tmp++;
14596 +
14597 +       return tmp;
14598 +}
14599 +
14600 +static struct osf_finger * finger_alloc()
14601 +{
14602 +       struct osf_finger *f;
14603 +
14604 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
14605 +       if (f)
14606 +               memset(f, 0, sizeof(struct osf_finger));
14607 +       
14608 +       return f;
14609 +}
14610 +
14611 +static void finger_free(struct osf_finger *f)
14612 +{
14613 +       memset(f, 0, sizeof(struct osf_finger));
14614 +       kfree(f);
14615 +}
14616 +
14617 +
14618 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
14619 +{
14620 +       int i, op;
14621 +       char *ptr, wc;
14622 +       unsigned long val;
14623 +
14624 +       ptr = &obuf[0];
14625 +       i = 0;
14626 +       while (ptr != NULL && i < olen)
14627 +       {
14628 +               val = 0;
14629 +               op = 0;
14630 +               wc = 0;
14631 +               switch (obuf[i])
14632 +               {
14633 +                       case 'N': 
14634 +                               op = OSFOPT_NOP;
14635 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14636 +                               if (ptr)
14637 +                               {
14638 +                                       *ptr = '\0';
14639 +                                       ptr++;
14640 +                                       i += (int)(ptr-&obuf[i]);
14641 +
14642 +                               }
14643 +                               else
14644 +                                       i++;
14645 +                               break;
14646 +                       case 'S': 
14647 +                               op = OSFOPT_SACKP;
14648 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14649 +                               if (ptr)
14650 +                               {
14651 +                                       *ptr = '\0';
14652 +                                       ptr++;
14653 +                                       i += (int)(ptr-&obuf[i]);
14654 +
14655 +                               }
14656 +                               else
14657 +                                       i++;
14658 +                               break;
14659 +                       case 'T': 
14660 +                               op = OSFOPT_TS;
14661 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14662 +                               if (ptr)
14663 +                               {
14664 +                                       *ptr = '\0';
14665 +                                       ptr++;
14666 +                                       i += (int)(ptr-&obuf[i]);
14667 +
14668 +                               }
14669 +                               else
14670 +                                       i++;
14671 +                               break;
14672 +                       case 'W': 
14673 +                               op = OSFOPT_WSO;
14674 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14675 +                               if (ptr)
14676 +                               {
14677 +                                       switch (obuf[i+1])
14678 +                                       {
14679 +                                               case '%':       wc = '%'; break;
14680 +                                               case 'S':       wc = 'S'; break;
14681 +                                               case 'T':       wc = 'T'; break;
14682 +                                               default:        wc = 0; break;
14683 +                                       }
14684 +                                       
14685 +                                       *ptr = '\0';
14686 +                                       ptr++;
14687 +                                       if (wc)
14688 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
14689 +                                       else
14690 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
14691 +                                       i += (int)(ptr-&obuf[i]);
14692 +
14693 +                               }
14694 +                               else
14695 +                                       i++;
14696 +                               break;
14697 +                       case 'M': 
14698 +                               op = OSFOPT_MSS;
14699 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14700 +                               if (ptr)
14701 +                               {
14702 +                                       if (obuf[i+1] == '%')
14703 +                                               wc = '%';
14704 +                                       *ptr = '\0';
14705 +                                       ptr++;
14706 +                                       if (wc)
14707 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
14708 +                                       else
14709 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
14710 +                                       i += (int)(ptr-&obuf[i]);
14711 +
14712 +                               }
14713 +                               else
14714 +                                       i++;
14715 +                               break;
14716 +                       case 'E': 
14717 +                               op = OSFOPT_EOL;
14718 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14719 +                               if (ptr)
14720 +                               {
14721 +                                       *ptr = '\0';
14722 +                                       ptr++;
14723 +                                       i += (int)(ptr-&obuf[i]);
14724 +
14725 +                               }
14726 +                               else
14727 +                                       i++;
14728 +                               break;
14729 +                       default:
14730 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
14731 +                               if (ptr)
14732 +                               {
14733 +                                       ptr++;
14734 +                                       i += (int)(ptr-&obuf[i]);
14735 +
14736 +                               }
14737 +                               else
14738 +                                       i++;
14739 +                               break;
14740 +               }
14741 +
14742 +               opt[*optnum].kind       = IANA_opts[op].kind;
14743 +               opt[*optnum].length     = IANA_opts[op].length;
14744 +               opt[*optnum].wc.wc      = wc;
14745 +               opt[*optnum].wc.val     = val;
14746 +
14747 +               log("opt %2d: kind=%2d, length=%2d, wc.wc=%d, wc.val=%5lu\n",
14748 +                       *optnum, opt[*optnum].kind, opt[*optnum].length, 
14749 +                       opt[*optnum].wc.wc, opt[*optnum].wc.val);
14750 +               
14751 +               (*optnum)++;
14752 +       }
14753 +}
14754 +
14755 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
14756 +{
14757 +       struct list_head *ent;
14758 +       struct osf_finger *f = NULL;
14759 +       int i;
14760 +       
14761 +       *eof = 1;
14762 +       count = 0;
14763 +
14764 +       read_lock_bh(&osf_lock);
14765 +       list_for_each(ent, &finger_list)
14766 +       {
14767 +               f = list_entry(ent, struct osf_finger, flist);
14768 +
14769 +               log("%s - %s: ttl=%d, wss=%c%lu, df=%d, size=%lu",
14770 +                       f->genre, f->details, f->ttl, (f->wss.wc)?f->wss.wc:' ', f->wss.val, f->df, f->ss);
14771 +               
14772 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
14773 +                                       f->genre, f->version,
14774 +                                       f->subtype, f->details);
14775 +               
14776 +               if (f->opt_num)
14777 +               {
14778 +                       loga(" OPT: ");
14779 +                       //count += sprintf(buf+count, " OPT: ");
14780 +                       for (i=0; i<f->opt_num; ++i)
14781 +                       {
14782 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
14783 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14784 +                               loga("%d.%c%lu; ", 
14785 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
14786 +                       }
14787 +               }
14788 +               loga("\n");
14789 +               count += sprintf(buf+count, "\n");
14790 +       }
14791 +       read_unlock_bh(&osf_lock);
14792 +
14793 +       return count;
14794 +}
14795 +
14796 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
14797 +{
14798 +       int cnt;
14799 +       unsigned long i;
14800 +       char obuf[MAXOPTSTRLEN];
14801 +       struct osf_finger *finger;
14802 +       struct list_head *ent, *n;
14803 +
14804 +       char *pbeg, *pend;
14805 +
14806 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
14807 +       {
14808 +               int i = 0;
14809 +               write_lock_bh(&osf_lock);
14810 +               list_for_each_safe(ent, n, &finger_list)
14811 +               {
14812 +                       i++;
14813 +                       finger = list_entry(ent, struct osf_finger, flist);
14814 +                       list_del(&finger->flist);
14815 +                       finger_free(finger);
14816 +               }
14817 +               write_unlock_bh(&osf_lock);
14818 +       
14819 +               log("Flushed %d entries.\n", i);
14820 +               
14821 +               return count;
14822 +       }
14823 +
14824 +       
14825 +       cnt = 0;
14826 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
14827 +               if (buffer[i] == ':')
14828 +                       cnt++;
14829 +
14830 +       if (cnt != 8 || i != count)
14831 +       {
14832 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
14833 +                       cnt, i, count);
14834 +               return count;
14835 +       }
14836 +
14837 +       memset(obuf, 0, sizeof(obuf));
14838 +       
14839 +       finger = finger_alloc();
14840 +       if (!finger)
14841 +       {
14842 +               log("Failed to allocate new fingerprint entry.\n");
14843 +               return -ENOMEM;
14844 +       }
14845 +
14846 +       pbeg = (char *)buffer;
14847 +       pend = osf_strchr(pbeg, OSFPDEL);
14848 +       if (pend)
14849 +       {
14850 +               *pend = '\0';
14851 +               if (pbeg[0] == 'S')
14852 +               {
14853 +                       finger->wss.wc = 'S';
14854 +                       if (pbeg[1] == '%')
14855 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14856 +                       else if (pbeg[1] == '*')
14857 +                               finger->wss.val = 0;
14858 +                       else 
14859 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14860 +               }
14861 +               else if (pbeg[0] == 'T')
14862 +               {
14863 +                       finger->wss.wc = 'T';
14864 +                       if (pbeg[1] == '%')
14865 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
14866 +                       else if (pbeg[1] == '*')
14867 +                               finger->wss.val = 0;
14868 +                       else 
14869 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
14870 +               }
14871 +               if (isdigit(pbeg[0]))
14872 +               {
14873 +                       finger->wss.wc = 0;
14874 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
14875 +               }
14876 +
14877 +               pbeg = pend+1;
14878 +       }
14879 +       pend = osf_strchr(pbeg, OSFPDEL);
14880 +       if (pend)
14881 +       {
14882 +               *pend = '\0';
14883 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
14884 +               pbeg = pend+1;
14885 +       }
14886 +       pend = osf_strchr(pbeg, OSFPDEL);
14887 +       if (pend)
14888 +       {
14889 +               *pend = '\0';
14890 +               finger->df = simple_strtoul(pbeg, NULL, 10);
14891 +               pbeg = pend+1;
14892 +       }
14893 +       pend = osf_strchr(pbeg, OSFPDEL);
14894 +       if (pend)
14895 +       {
14896 +               *pend = '\0';
14897 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
14898 +               pbeg = pend+1;
14899 +       }
14900 +
14901 +       pend = osf_strchr(pbeg, OSFPDEL);
14902 +       if (pend)
14903 +       {
14904 +               *pend = '\0';
14905 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
14906 +               pbeg = pend+1;
14907 +       }
14908 +
14909 +       pend = osf_strchr(pbeg, OSFPDEL);
14910 +       if (pend)
14911 +       {
14912 +               *pend = '\0';
14913 +               if (pbeg[0] == '@' || pbeg[0] == '*')
14914 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
14915 +               else
14916 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
14917 +               pbeg = pend+1;
14918 +       }
14919 +       
14920 +       pend = osf_strchr(pbeg, OSFPDEL);
14921 +       if (pend)
14922 +       {
14923 +               *pend = '\0';
14924 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
14925 +               pbeg = pend+1;
14926 +       }
14927 +       
14928 +       pend = osf_strchr(pbeg, OSFPDEL);
14929 +       if (pend)
14930 +       {
14931 +               *pend = '\0';
14932 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
14933 +               pbeg = pend+1;
14934 +       }
14935 +
14936 +       cnt = snprintf(finger->details, 
14937 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
14938 +                       "%s", pbeg);
14939 +       
14940 +       log("%s - %s[%s] : %s\n", 
14941 +               finger->genre, finger->version,
14942 +               finger->subtype, finger->details);
14943 +       
14944 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
14945 +       
14946 +
14947 +       write_lock_bh(&osf_lock);
14948 +       list_add(&finger->flist, &finger_list);
14949 +       write_unlock_bh(&osf_lock);
14950 +
14951 +       return count;
14952 +}
14953 +
14954 +static int __init osf_init(void)
14955 +{
14956 +       int err;
14957 +       struct proc_dir_entry *p;
14958 +
14959 +       log("Startng OS fingerprint matching module.\n");
14960 +
14961 +       INIT_LIST_HEAD(&finger_list);
14962 +       
14963 +       err = ipt_register_match(&osf_match);
14964 +       if (err)
14965 +       {
14966 +               log("Failed to register OS fingerprint matching module.\n");
14967 +               return -ENXIO;
14968 +       }
14969 +
14970 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
14971 +       if (!p)
14972 +       {
14973 +               ipt_unregister_match(&osf_match);
14974 +               return -ENXIO;
14975 +       }
14976 +
14977 +       p->write_proc = osf_proc_write;
14978 +       p->read_proc  = osf_proc_read;
14979 +
14980 +       return 0;
14981 +}
14982 +
14983 +static void __exit osf_fini(void)
14984 +{
14985 +       struct list_head *ent, *n;
14986 +       struct osf_finger *f;
14987 +       
14988 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
14989 +       ipt_unregister_match(&osf_match);
14990 +
14991 +       list_for_each_safe(ent, n, &finger_list)
14992 +       {
14993 +               f = list_entry(ent, struct osf_finger, flist);
14994 +               list_del(&f->flist);
14995 +               finger_free(f);
14996 +       }
14997 +       
14998 +       log("OS fingerprint matching module finished.\n");
14999 +}
15000 +
15001 +module_init(osf_init);
15002 +module_exit(osf_fini);
15003 +
15004 +MODULE_LICENSE("GPL");
15005 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
15006 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
15007 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
15008 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_pool.c        1970-01-01 01:00:00.000000000 +0100
15009 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_pool.c    2003-12-11 10:23:32.944929584 +0100
15010 @@ -0,0 +1,71 @@
15011 +/* Kernel module to match an IP address pool. */
15012 +
15013 +#include <linux/module.h>
15014 +#include <linux/ip.h>
15015 +#include <linux/skbuff.h>
15016 +
15017 +#include <linux/netfilter_ipv4/ip_tables.h>
15018 +#include <linux/netfilter_ipv4/ip_pool.h>
15019 +#include <linux/netfilter_ipv4/ipt_pool.h>
15020 +
15021 +static inline int match_pool(
15022 +       ip_pool_t index,
15023 +       __u32 addr,
15024 +       int inv
15025 +) {
15026 +       if (ip_pool_match(index, ntohl(addr)))
15027 +               inv = !inv;
15028 +       return inv;
15029 +}
15030 +
15031 +static int match(
15032 +       const struct sk_buff *skb,
15033 +       const struct net_device *in,
15034 +       const struct net_device *out,
15035 +       const void *matchinfo,
15036 +       int offset,
15037 +       const void *hdr,
15038 +       u_int16_t datalen,
15039 +       int *hotdrop
15040 +) {
15041 +       const struct ipt_pool_info *info = matchinfo;
15042 +       const struct iphdr *iph = skb->nh.iph;
15043 +
15044 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
15045 +                                               info->flags&IPT_POOL_INV_SRC))
15046 +               return 0;
15047 +
15048 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
15049 +                                               info->flags&IPT_POOL_INV_DST))
15050 +               return 0;
15051 +
15052 +       return 1;
15053 +}
15054 +
15055 +static int checkentry(
15056 +       const char *tablename,
15057 +       const struct ipt_ip *ip,
15058 +       void *matchinfo,
15059 +       unsigned int matchsize,
15060 +       unsigned int hook_mask
15061 +) {
15062 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
15063 +               return 0;
15064 +       return 1;
15065 +}
15066 +
15067 +static struct ipt_match pool_match
15068 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
15069 +
15070 +static int __init init(void)
15071 +{
15072 +       return ipt_register_match(&pool_match);
15073 +}
15074 +
15075 +static void __exit fini(void)
15076 +{
15077 +       ipt_unregister_match(&pool_match);
15078 +}
15079 +
15080 +module_init(init);
15081 +module_exit(fini);
15082 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
15083 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_POOL.c        1970-01-01 01:00:00.000000000 +0100
15084 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_POOL.c    2003-12-11 10:23:32.945929432 +0100
15085 @@ -0,0 +1,116 @@
15086 +/* ipt_POOL.c - netfilter target to manipulate IP pools
15087 + *
15088 + * This target can be used almost everywhere. It acts on some specified
15089 + * IP pool, adding or deleting some IP address in the pool. The address
15090 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
15091 + * of the packet under inspection.
15092 + *
15093 + * The target normally returns IPT_CONTINUE.
15094 + */
15095 +
15096 +#include <linux/types.h>
15097 +#include <linux/ip.h>
15098 +#include <linux/timer.h>
15099 +#include <linux/module.h>
15100 +#include <linux/netfilter.h>
15101 +#include <linux/netdevice.h>
15102 +#include <linux/if.h>
15103 +#include <linux/inetdevice.h>
15104 +#include <net/protocol.h>
15105 +#include <net/checksum.h>
15106 +#include <linux/netfilter_ipv4.h>
15107 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
15108 +#include <linux/netfilter_ipv4/ipt_pool.h>
15109 +
15110 +#if 0
15111 +#define DEBUGP printk
15112 +#else
15113 +#define DEBUGP(format, args...)
15114 +#endif
15115 +
15116 +/*** NOTE NOTE NOTE NOTE ***
15117 +**
15118 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
15119 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
15120 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
15121 +** is modified for the source IP address of the packet under inspection.
15122 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
15123 +**
15124 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
15125 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
15126 +**
15127 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
15128 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
15129 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
15130 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
15131 +*/
15132 +
15133 +static int
15134 +do_check(const char *tablename,
15135 +              const struct ipt_entry *e,
15136 +              void *targinfo,
15137 +              unsigned int targinfosize,
15138 +              unsigned int hook_mask)
15139 +{
15140 +       const struct ipt_pool_info *ipi = targinfo;
15141 +
15142 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
15143 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
15144 +               return 0;
15145 +       }
15146 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
15147 +       return 1;
15148 +}
15149 +
15150 +static unsigned int
15151 +do_target(struct sk_buff **pskb,
15152 +               unsigned int hooknum,
15153 +               const struct net_device *in,
15154 +               const struct net_device *out,
15155 +               const void *targinfo,
15156 +               void *userinfo)
15157 +{
15158 +       const struct ipt_pool_info *ipi = targinfo;
15159 +       int modified;
15160 +       unsigned int verdict = IPT_CONTINUE;
15161 +
15162 +       if (ipi->src != IP_POOL_NONE) {
15163 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
15164 +                                       ipi->flags & IPT_POOL_DEL_SRC);
15165 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
15166 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
15167 +                               verdict = NF_ACCEPT;
15168 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
15169 +                               verdict = NF_DROP;
15170 +               }
15171 +       }
15172 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
15173 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
15174 +                                       ipi->flags & IPT_POOL_DEL_DST);
15175 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
15176 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
15177 +                               verdict = NF_ACCEPT;
15178 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
15179 +                               verdict = NF_DROP;
15180 +               }
15181 +       }
15182 +       return verdict;
15183 +}
15184 +
15185 +static struct ipt_target pool_reg
15186 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
15187 +
15188 +static int __init init(void)
15189 +{
15190 +       DEBUGP("init ipt_POOL\n");
15191 +       return ipt_register_target(&pool_reg);
15192 +}
15193 +
15194 +static void __exit fini(void)
15195 +{
15196 +       DEBUGP("fini ipt_POOL\n");
15197 +       ipt_unregister_target(&pool_reg);
15198 +}
15199 +
15200 +module_init(init);
15201 +module_exit(fini);
15202 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
15203 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
15204 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_psd.c     2003-12-11 10:23:34.086756000 +0100
15205 @@ -0,0 +1,361 @@
15206 +/*
15207 +  This is a module which is used for PSD (portscan detection)
15208 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
15209 +  and LOG target module.
15210 +
15211 +  Copyright (C) 2000,2001 astaro AG
15212 +
15213 +  This file is distributed under the terms of the GNU General Public
15214 +  License (GPL). Copies of the GPL can be obtained from:
15215 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
15216 +
15217 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
15218 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
15219 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
15220 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
15221 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
15222 +*/
15223 +
15224 +#include <linux/module.h>
15225 +#include <linux/skbuff.h>
15226 +#include <linux/ip.h>
15227 +#include <net/tcp.h>
15228 +#include <linux/spinlock.h>
15229 +#include <linux/netfilter_ipv4/ip_tables.h>
15230 +#include <linux/netfilter_ipv4/ipt_psd.h>
15231 +
15232 +#if 0
15233 +#define DEBUGP printk
15234 +#else
15235 +#define DEBUGP(format, args...)
15236 +#endif
15237 +
15238 +MODULE_LICENSE("GPL");
15239 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
15240 +
15241 +#define HF_DADDR_CHANGING   0x01
15242 +#define HF_SPORT_CHANGING   0x02
15243 +#define HF_TOS_CHANGING            0x04
15244 +#define HF_TTL_CHANGING            0x08
15245 +            
15246 +/*
15247 + * Information we keep per each target port
15248 + */
15249 +struct port {
15250 +       u_int16_t number;      /* port number */ 
15251 +       u_int8_t proto;        /* protocol number */
15252 +       u_int8_t and_flags;    /* tcp ANDed flags */
15253 +       u_int8_t or_flags;     /* tcp ORed flags */
15254 +};
15255 +
15256 +/*
15257 + * Information we keep per each source address.
15258 + */
15259 +struct host {
15260 +       struct host *next;              /* Next entry with the same hash */
15261 +       clock_t timestamp;              /* Last update time */
15262 +       struct in_addr src_addr;        /* Source address */
15263 +       struct in_addr dest_addr;       /* Destination address */
15264 +       unsigned short src_port;        /* Source port */
15265 +       int count;                      /* Number of ports in the list */
15266 +       int weight;                     /* Total weight of ports in the list */
15267 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
15268 +       unsigned char tos;              /* TOS */
15269 +       unsigned char ttl;              /* TTL */
15270 +       unsigned char flags;            /* HF_ flags bitmask */
15271 +};
15272 +
15273 +/*
15274 + * State information.
15275 + */
15276 +static struct {
15277 +       spinlock_t lock;
15278 +       struct host list[LIST_SIZE];    /* List of source addresses */
15279 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
15280 +       int index;                      /* Oldest entry to be replaced */
15281 +} state;
15282 +
15283 +/*
15284 + * Convert an IP address into a hash table index.
15285 + */
15286 +static inline int hashfunc(struct in_addr addr)
15287 +{
15288 +       unsigned int value;
15289 +       int hash;
15290 +
15291 +       value = addr.s_addr;
15292 +       hash = 0;
15293 +       do {
15294 +               hash ^= value;
15295 +       } while ((value >>= HASH_LOG));
15296 +
15297 +       return hash & (HASH_SIZE - 1);
15298 +}
15299 +
15300 +static int
15301 +ipt_psd_match(const struct sk_buff *pskb,
15302 +             const struct net_device *in,
15303 +             const struct net_device *out,
15304 +             const void *matchinfo,
15305 +             int offset,
15306 +             const void *hdr,
15307 +             u_int16_t datalen,
15308 +             int *hotdrop)
15309 +{
15310 +       struct iphdr *ip_hdr;
15311 +       struct tcphdr *tcp_hdr;
15312 +       struct in_addr addr;
15313 +       u_int16_t src_port,dest_port;
15314 +       u_int8_t tcp_flags, proto;
15315 +       clock_t now;
15316 +       struct host *curr, *last, **head;
15317 +       int hash, index, count;
15318 +
15319 +       /* Parameters from userspace */
15320 +       const struct ipt_psd_info *psdinfo = matchinfo;
15321 +
15322 +       /* IP header */
15323 +       ip_hdr = pskb->nh.iph;
15324 +
15325 +       /* Sanity check */
15326 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
15327 +               DEBUGP("PSD: sanity check failed\n");
15328 +               return 0;
15329 +       }
15330 +
15331 +       /* TCP or UDP ? */
15332 +       proto = ip_hdr->protocol;
15333 +
15334 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
15335 +               DEBUGP("PSD: protocol not supported\n");
15336 +               return 0;
15337 +       }
15338 +
15339 +       /* Get the source address, source & destination ports, and TCP flags */
15340 +
15341 +       addr.s_addr = ip_hdr->saddr;
15342 +
15343 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
15344 +
15345 +       /* Yep, it´s dirty */
15346 +       src_port = tcp_hdr->source;
15347 +       dest_port = tcp_hdr->dest;
15348 +
15349 +       if (proto == IPPROTO_TCP) {
15350 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
15351 +       }
15352 +       else {
15353 +               tcp_flags = 0x00;
15354 +       }
15355 +
15356 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
15357 +        * them spoof us. [DHCP needs this feature - HW] */
15358 +       if (!addr.s_addr) {
15359 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
15360 +               return 0;
15361 +       }
15362 +
15363 +       /* Use jiffies here not to depend on someone setting the time while we're
15364 +        * running; we need to be careful with possible return value overflows. */
15365 +       now = jiffies;
15366 +
15367 +       spin_lock(&state.lock);
15368 +
15369 +       /* Do we know this source address already? */
15370 +       count = 0;
15371 +       last = NULL;
15372 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
15373 +               do {
15374 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
15375 +                       count++;
15376 +                       if (curr->next) last = curr;
15377 +               } while ((curr = curr->next));
15378 +
15379 +       if (curr) {
15380 +
15381 +               /* We know this address, and the entry isn't too old. Update it. */
15382 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
15383 +                   time_after_eq(now, curr->timestamp)) {
15384 +
15385 +                       /* Just update the appropriate list entry if we've seen this port already */
15386 +                       for (index = 0; index < curr->count; index++) {
15387 +                               if (curr->ports[index].number == dest_port) {
15388 +                                       curr->ports[index].proto = proto;
15389 +                                       curr->ports[index].and_flags &= tcp_flags;
15390 +                                       curr->ports[index].or_flags |= tcp_flags;
15391 +                                       goto out_no_match;
15392 +                               }
15393 +                       }
15394 +
15395 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
15396 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
15397 +                               goto out_no_match;
15398 +
15399 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
15400 +                       curr->timestamp = now;
15401 +
15402 +                       /* Logged this scan already? Then drop the packet. */
15403 +                       if (curr->weight >= psdinfo->weight_threshold)
15404 +                               goto out_match;
15405 +
15406 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
15407 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
15408 +                               curr->flags |= HF_DADDR_CHANGING;
15409 +                       if (curr->src_port != src_port)
15410 +                               curr->flags |= HF_SPORT_CHANGING;
15411 +                       if (curr->tos != ip_hdr->tos)
15412 +                               curr->flags |= HF_TOS_CHANGING;
15413 +                       if (curr->ttl != ip_hdr->ttl)
15414 +                               curr->flags |= HF_TTL_CHANGING;
15415 +
15416 +                       /* Update the total weight */
15417 +                       curr->weight += (ntohs(dest_port) < 1024) ?
15418 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15419 +
15420 +                       /* Got enough destination ports to decide that this is a scan? */
15421 +                       /* Then log it and drop the packet. */
15422 +                       if (curr->weight >= psdinfo->weight_threshold)
15423 +                               goto out_match;
15424 +
15425 +                       /* Remember the new port */
15426 +                       if (curr->count < SCAN_MAX_COUNT) {
15427 +                               curr->ports[curr->count].number = dest_port;
15428 +                               curr->ports[curr->count].proto = proto;
15429 +                               curr->ports[curr->count].and_flags = tcp_flags;
15430 +                               curr->ports[curr->count].or_flags = tcp_flags;
15431 +                               curr->count++;
15432 +                       }
15433 +
15434 +                       goto out_no_match;
15435 +               }
15436 +
15437 +               /* We know this address, but the entry is outdated. Mark it unused, and
15438 +                * remove from the hash table. We'll allocate a new entry instead since
15439 +                * this one might get re-used too soon. */
15440 +               curr->src_addr.s_addr = 0;
15441 +               if (last)
15442 +                       last->next = last->next->next;
15443 +               else if (*head)
15444 +                       *head = (*head)->next;
15445 +               last = NULL;
15446 +       }
15447 +
15448 +       /* We don't need an ACK from a new source address */
15449 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
15450 +               goto out_no_match;
15451 +
15452 +       /* Got too many source addresses with the same hash value? Then remove the
15453 +        * oldest one from the hash table, so that they can't take too much of our
15454 +        * CPU time even with carefully chosen spoofed IP addresses. */
15455 +       if (count >= HASH_MAX && last) last->next = NULL;
15456 +
15457 +       /* We're going to re-use the oldest list entry, so remove it from the hash
15458 +        * table first (if it is really already in use, and isn't removed from the
15459 +        * hash table already because of the HASH_MAX check above). */
15460 +
15461 +       /* First, find it */
15462 +       if (state.list[state.index].src_addr.s_addr)
15463 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
15464 +       else
15465 +               head = &last;
15466 +       last = NULL;
15467 +       if ((curr = *head))
15468 +       do {
15469 +               if (curr == &state.list[state.index]) break;
15470 +               last = curr;
15471 +       } while ((curr = curr->next));
15472 +
15473 +       /* Then, remove it */
15474 +       if (curr) {
15475 +               if (last)
15476 +                       last->next = last->next->next;
15477 +               else if (*head)
15478 +                       *head = (*head)->next;
15479 +       }
15480 +
15481 +       /* Get our list entry */
15482 +       curr = &state.list[state.index++];
15483 +       if (state.index >= LIST_SIZE) state.index = 0;
15484 +
15485 +       /* Link it into the hash table */
15486 +       head = &state.hash[hash];
15487 +       curr->next = *head;
15488 +       *head = curr;
15489 +
15490 +       /* And fill in the fields */
15491 +       curr->timestamp = now;
15492 +       curr->src_addr = addr;
15493 +       curr->dest_addr.s_addr = ip_hdr->daddr;
15494 +       curr->src_port = src_port;
15495 +       curr->count = 1;
15496 +       curr->weight = (ntohs(dest_port) < 1024) ?
15497 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
15498 +       curr->ports[0].number = dest_port;
15499 +       curr->ports[0].proto = proto;
15500 +       curr->ports[0].and_flags = tcp_flags;
15501 +       curr->ports[0].or_flags = tcp_flags;
15502 +       curr->tos = ip_hdr->tos;
15503 +       curr->ttl = ip_hdr->ttl;
15504 +
15505 +out_no_match:
15506 +       spin_unlock(&state.lock);
15507 +       return 0;
15508 +
15509 +out_match:
15510 +       spin_unlock(&state.lock);
15511 +       return 1;
15512 +}
15513 +
15514 +static int ipt_psd_checkentry(const char *tablename,
15515 +                             const struct ipt_ip *e,
15516 +                             void *matchinfo,
15517 +                             unsigned int matchsize,
15518 +                             unsigned int hook_mask)
15519 +{
15520 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
15521 +
15522 +       /* we accept TCP only */
15523 +/*     if (e->ip.proto != IPPROTO_TCP) { */
15524 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
15525 +/*             return 0; */
15526 +/*     } */
15527 +
15528 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
15529 +               DEBUGP("PSD: matchsize %u != %u\n",
15530 +                      matchsize,
15531 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
15532 +               return 0;
15533 +       }
15534 +
15535 +       return 1;
15536 +}
15537 +
15538 +static struct ipt_match ipt_psd_reg = { 
15539 +       {NULL, NULL},
15540 +       "psd",
15541 +       ipt_psd_match,
15542 +       ipt_psd_checkentry,
15543 +       NULL,
15544 +       THIS_MODULE };
15545 +
15546 +static int __init init(void)
15547 +{
15548 +       if (ipt_register_match(&ipt_psd_reg))
15549 +               return -EINVAL;
15550 +
15551 +       memset(&state, 0, sizeof(state));
15552 +
15553 +       spin_lock_init(&(state.lock));
15554 +
15555 +       printk("netfilter PSD loaded - (c) astaro AG\n");
15556 +       return 0;
15557 +}
15558 +
15559 +static void __exit fini(void)
15560 +{
15561 +       ipt_unregister_match(&ipt_psd_reg);
15562 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
15563 +}
15564 +
15565 +module_init(init);
15566 +module_exit(fini);
15567 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
15568 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_quota.c       1970-01-01 01:00:00.000000000 +0100
15569 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_quota.c   2003-12-11 10:23:35.183589256 +0100
15570 @@ -0,0 +1,81 @@
15571 +/* 
15572 + * netfilter module to enforce network quotas
15573 + *
15574 + * Sam Johnston <samj@samj.net>
15575 + */
15576 +#include <linux/module.h>
15577 +#include <linux/skbuff.h>
15578 +#include <linux/spinlock.h>
15579 +#include <linux/interrupt.h>
15580 +
15581 +#include <linux/netfilter_ipv4/ip_tables.h>
15582 +#include <linux/netfilter_ipv4/ipt_quota.h>
15583 +
15584 +MODULE_LICENSE("GPL");
15585 +
15586 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
15587 +
15588 +static int
15589 +match(const struct sk_buff *skb,
15590 +      const struct net_device *in,
15591 +      const struct net_device *out,
15592 +      const void *matchinfo,
15593 +      int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
15594 +{
15595 +
15596 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
15597 +
15598 +        spin_lock_bh(&quota_lock);
15599 +
15600 +        if (q->quota >= datalen) {
15601 +                /* we can afford this one */
15602 +                q->quota -= datalen;
15603 +                spin_unlock_bh(&quota_lock);
15604 +
15605 +#ifdef DEBUG_IPT_QUOTA
15606 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
15607 +#endif
15608 +                return 1;
15609 +        }
15610 +
15611 +        /* so we do not allow even small packets from now on */
15612 +        q->quota = 0;
15613 +
15614 +#ifdef DEBUG_IPT_QUOTA
15615 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
15616 +#endif
15617 +
15618 +        spin_unlock_bh(&quota_lock);
15619 +        return 0;
15620 +}
15621 +
15622 +static int
15623 +checkentry(const char *tablename,
15624 +           const struct ipt_ip *ip,
15625 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
15626 +{
15627 +        /* TODO: spinlocks? sanity checks? */
15628 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
15629 +                return 0;
15630 +
15631 +        return 1;
15632 +}
15633 +
15634 +static struct ipt_match quota_match
15635 +    = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
15636 +
15637 +static int __init
15638 +init(void)
15639 +{
15640 +        return ipt_register_match(&quota_match);
15641 +}
15642 +
15643 +static void __exit
15644 +fini(void)
15645 +{
15646 +        ipt_unregister_match(&quota_match);
15647 +}
15648 +
15649 +module_init(init);
15650 +module_exit(fini);
15651 +
15652 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
15653 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_random.c      1970-01-01 01:00:00.000000000 +0100
15654 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_random.c  2003-12-11 10:23:37.415249992 +0100
15655 @@ -0,0 +1,96 @@
15656 +/*
15657 +  This is a module which is used for a "random" match support.
15658 +  This file is distributed under the terms of the GNU General Public
15659 +  License (GPL). Copies of the GPL can be obtained from:
15660 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
15661 +
15662 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
15663 +*/
15664 +
15665 +#include <linux/module.h>
15666 +#include <linux/skbuff.h>
15667 +#include <linux/ip.h>
15668 +#include <linux/random.h>
15669 +#include <net/tcp.h>
15670 +#include <linux/spinlock.h>
15671 +#include <linux/netfilter_ipv4/ip_tables.h>
15672 +#include <linux/netfilter_ipv4/ipt_random.h>
15673 +
15674 +MODULE_LICENSE("GPL");
15675 +
15676 +static int
15677 +ipt_rand_match(const struct sk_buff *pskb,
15678 +              const struct net_device *in,
15679 +              const struct net_device *out,
15680 +              const void *matchinfo,
15681 +              int offset,
15682 +              const void *hdr,
15683 +              u_int16_t datalen,
15684 +              int *hotdrop)
15685 +{
15686 +       /* Parameters from userspace */
15687 +       const struct ipt_rand_info *info = matchinfo;
15688 +       u_int8_t random_number;
15689 +
15690 +       /* get 1 random number from the kernel random number generation routine */
15691 +       get_random_bytes((void *)(&random_number), 1);
15692 +
15693 +       /* Do we match ? */
15694 +       if (random_number <= info->average)
15695 +               return 1;
15696 +       else
15697 +               return 0;
15698 +}
15699 +
15700 +static int
15701 +ipt_rand_checkentry(const char *tablename,
15702 +                  const struct ipt_ip *e,
15703 +                  void *matchinfo,
15704 +                  unsigned int matchsize,
15705 +                  unsigned int hook_mask)
15706 +{
15707 +       /* Parameters from userspace */
15708 +       const struct ipt_rand_info *info = matchinfo;
15709 +
15710 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
15711 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
15712 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
15713 +               return 0;
15714 +       }
15715 +
15716 +       /* must be  1 <= average % <= 99 */
15717 +       /* 1  x 2.55 = 2   */
15718 +       /* 99 x 2.55 = 252 */
15719 +       if ((info->average < 2) || (info->average > 252)) {
15720 +               printk("ipt_random:  invalid average %u\n", info->average);
15721 +               return 0;
15722 +       }
15723 +
15724 +       return 1;
15725 +}
15726 +
15727 +static struct ipt_match ipt_rand_reg = { 
15728 +       {NULL, NULL},
15729 +       "random",
15730 +       ipt_rand_match,
15731 +       ipt_rand_checkentry,
15732 +       NULL,
15733 +       THIS_MODULE };
15734 +
15735 +static int __init init(void)
15736 +{
15737 +       if (ipt_register_match(&ipt_rand_reg))
15738 +               return -EINVAL;
15739 +
15740 +       printk("ipt_random match loaded\n");
15741 +       return 0;
15742 +}
15743 +
15744 +static void __exit fini(void)
15745 +{
15746 +       ipt_unregister_match(&ipt_rand_reg);
15747 +       printk("ipt_random match unloaded\n");
15748 +}
15749 +
15750 +module_init(init);
15751 +module_exit(fini);
15752 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
15753 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_realm.c       1970-01-01 01:00:00.000000000 +0100
15754 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_realm.c   2003-12-11 10:23:38.553077016 +0100
15755 @@ -0,0 +1,68 @@
15756 +/* Kernel module to match realm from routing. */
15757 +#include <linux/module.h>
15758 +#include <linux/skbuff.h>
15759 +#include <linux/netdevice.h>
15760 +#include <net/route.h>
15761 +
15762 +#include <linux/netfilter_ipv4/ipt_realm.h>
15763 +#include <linux/netfilter_ipv4/ip_tables.h>
15764 +
15765 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
15766 +MODULE_LICENSE("GPL");
15767 +
15768 +static int
15769 +match(const struct sk_buff *skb,
15770 +      const struct net_device *in,
15771 +      const struct net_device *out,
15772 +      const void *matchinfo,
15773 +      int offset,
15774 +      const void *hdr,
15775 +      u_int16_t datalen,
15776 +      int *hotdrop)
15777 +{
15778 +       const struct ipt_realm_info *info = matchinfo;
15779 +       struct dst_entry *dst = skb->dst;
15780 +       u32 id;
15781 +    
15782 +       if(dst == NULL)
15783 +               return 0;
15784 +       id = dst->tclassid;
15785 +
15786 +       return (info->id == (id & info->mask)) ^ info->invert;
15787 +}
15788 +
15789 +static int check(const char *tablename,
15790 +                 const struct ipt_ip *ip,
15791 +                 void *matchinfo,
15792 +                 unsigned int matchsize,
15793 +                 unsigned int hook_mask)
15794 +{
15795 +       if (hook_mask
15796 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
15797 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
15798 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
15799 +                      "LOCAL_IN or FORWARD.\n");
15800 +               return 0;
15801 +       }
15802 +
15803 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
15804 +               return 0;
15805 +
15806 +       return 1;
15807 +}
15808 +
15809 +static struct ipt_match realm_match
15810 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
15811 +
15812 +static int __init init(void)
15813 +{
15814 +       return ipt_register_match(&realm_match);
15815 +}
15816 +
15817 +static void __exit fini(void)
15818 +{
15819 +       ipt_unregister_match(&realm_match);
15820 +}
15821 +
15822 +module_init(init);
15823 +module_exit(fini);
15824 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
15825 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_REJECT.c      2003-11-26 21:45:22.000000000 +0100
15826 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_REJECT.c  2003-12-11 10:24:13.908702144 +0100
15827 @@ -2,6 +2,7 @@
15828   * This is a module which is used for rejecting packets.
15829   * Added support for customized reject packets (Jozsef Kadlecsik).
15830   * Added support for ICMP type-3-code-13 (Maciej Soltysiak). [RFC 1812]
15831 + * Added support for fake source IP in icmp-unreach (Fabrice MARIE & Guillaume MORIN).
15832   */
15833  #include <linux/config.h>
15834  #include <linux/module.h>
15835 @@ -204,13 +205,13 @@
15836         kfree_skb(nskb);
15837  }
15838  
15839 -static void send_unreach(struct sk_buff *skb_in, int code)
15840 +static void send_unreach(struct sk_buff *skb_in, int code, u_int8_t fake_source_address)
15841  {
15842         struct iphdr *iph;
15843         struct udphdr *udph;
15844         struct icmphdr *icmph;
15845         struct sk_buff *nskb;
15846 -       u32 saddr;
15847 +       u32 saddr,packet_daddr;
15848         u8 tos;
15849         int hh_len, length;
15850         struct rtable *rt = (struct rtable*)skb_in->dst;
15851 @@ -274,7 +275,7 @@
15852                         return;
15853         }
15854  
15855 -       saddr = iph->daddr;
15856 +       packet_daddr = saddr = iph->daddr;
15857         if (!(rt->rt_flags & RTCF_LOCAL))
15858                 saddr = 0;
15859  
15860 @@ -322,7 +323,16 @@
15861         iph->ttl = MAXTTL;
15862         ip_select_ident(iph, &rt->u.dst, NULL);
15863         iph->protocol=IPPROTO_ICMP;
15864 -       iph->saddr=rt->rt_src;
15865 +
15866 +        /* fake source IP if we have to
15867 +           if fake_source_address == 1, we fake the source IP
15868 +           from the packet destination address dynamically.
15869 +        */
15870 +        if (fake_source_address == 1)
15871 +                iph->saddr = packet_daddr;
15872 +        else
15873 +               iph->saddr=rt->rt_src;
15874 +
15875         iph->daddr=rt->rt_dst;
15876         iph->check=0;
15877         iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
15878 @@ -370,25 +380,25 @@
15879            must return an absolute verdict. --RR */
15880         switch (reject->with) {
15881         case IPT_ICMP_NET_UNREACHABLE:
15882 -               send_unreach(*pskb, ICMP_NET_UNREACH);
15883 +               send_unreach(*pskb, ICMP_NET_UNREACH, reject->fake_source_address);
15884                 break;
15885         case IPT_ICMP_HOST_UNREACHABLE:
15886 -               send_unreach(*pskb, ICMP_HOST_UNREACH);
15887 +               send_unreach(*pskb, ICMP_HOST_UNREACH, reject->fake_source_address);
15888                 break;
15889         case IPT_ICMP_PROT_UNREACHABLE:
15890 -               send_unreach(*pskb, ICMP_PROT_UNREACH);
15891 +               send_unreach(*pskb, ICMP_PROT_UNREACH, reject->fake_source_address);
15892                 break;
15893         case IPT_ICMP_PORT_UNREACHABLE:
15894 -               send_unreach(*pskb, ICMP_PORT_UNREACH);
15895 +               send_unreach(*pskb, ICMP_PORT_UNREACH, reject->fake_source_address);
15896                 break;
15897         case IPT_ICMP_NET_PROHIBITED:
15898 -               send_unreach(*pskb, ICMP_NET_ANO);
15899 +               send_unreach(*pskb, ICMP_NET_ANO, reject->fake_source_address);
15900                 break;
15901         case IPT_ICMP_HOST_PROHIBITED:
15902 -               send_unreach(*pskb, ICMP_HOST_ANO);
15903 +               send_unreach(*pskb, ICMP_HOST_ANO, reject->fake_source_address);
15904                 break;
15905         case IPT_ICMP_ADMIN_PROHIBITED:
15906 -               send_unreach(*pskb, ICMP_PKT_FILTERED);
15907 +               send_unreach(*pskb, ICMP_PKT_FILTERED, reject->fake_source_address);
15908                 break;
15909         case IPT_TCP_RESET:
15910                 send_reset(*pskb, hooknum);
15911 @@ -435,6 +445,11 @@
15912                         DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
15913                         return 0;
15914                 }
15915 +               /* cannot fake source address */
15916 +               if (rejinfo->fake_source_address != 0) {
15917 +                       DEBUGP("REJECT: fake-source-address illegal for TCP-RESET\n");
15918 +                       return 0;
15919 +               }
15920         }
15921  
15922         return 1;
15923 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
15924 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
15925 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_rpc.c     2003-12-11 10:24:04.354154656 +0100
15926 @@ -0,0 +1,428 @@
15927 +/* RPC extension for IP connection matching, Version 2.2
15928 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
15929 + *     - original rpc tracking module
15930 + *     - "recent" connection handling for kernel 2.3+ netfilter
15931 + *
15932 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
15933 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
15934 + *
15935 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
15936 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
15937 + *     - extended matching to support filtering on procedures
15938 + *
15939 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
15940 + *
15941 + *     This program is free software; you can redistribute it and/or
15942 + *     modify it under the terms of the GNU General Public License
15943 + *     as published by the Free Software Foundation; either version
15944 + *     2 of the License, or (at your option) any later version.
15945 + **
15946 + *     Module load syntax:
15947 + *     insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
15948 + *
15949 + *     Please give the ports of all RPC servers you wish to connect to.
15950 + *     If you don't specify ports, the default will be port 111.
15951 + **
15952 + *     Note to all:
15953 + *
15954 + *     RPCs should not be exposed to the internet - ask the Pentagon;
15955 + *
15956 + *       "The unidentified crackers pleaded guilty in July to charges
15957 + *        of juvenile delinquency stemming from a string of Pentagon
15958 + *        network intrusions in February.
15959 + *
15960 + *        The youths, going by the names TooShort and Makaveli, used
15961 + *        a common server security hole to break in, according to
15962 + *        Dane Jasper, owner of the California Internet service
15963 + *        provider, Sonic. They used the hole, known as the 'statd'
15964 + *        exploit, to attempt more than 800 break-ins, Jasper said."
15965 + *
15966 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
15967 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
15968 + **
15969 + */
15970 +
15971 +#include <linux/module.h>
15972 +#include <linux/skbuff.h>
15973 +#include <linux/list.h>
15974 +#include <linux/udp.h>
15975 +#include <linux/tcp.h>
15976 +#include <linux/netfilter_ipv4/ip_conntrack.h>
15977 +#include <linux/netfilter_ipv4/ip_tables.h>
15978 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
15979 +#include <linux/netfilter_ipv4/lockhelp.h>
15980 +#include <linux/netfilter_ipv4/ipt_rpc.h>
15981 +
15982 +#define MAX_PORTS 8
15983 +static int ports[MAX_PORTS];
15984 +static int ports_n_c = 0;
15985 +
15986 +#ifdef MODULE_PARM
15987 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
15988 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
15989 +#endif
15990 +
15991 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
15992 +MODULE_DESCRIPTION("RPC connection matching module");
15993 +MODULE_LICENSE("GPL");
15994 +
15995 +#if 0
15996 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
15997 +                                       format, ## args)
15998 +#else
15999 +#define DEBUGP(format, args...)
16000 +#endif
16001 +
16002 +EXPORT_NO_SYMBOLS;
16003 +
16004 +/* vars from ip_conntrack_rpc_tcp */
16005 +extern struct list_head request_p_list_tcp;
16006 +extern struct module *ip_conntrack_rpc_tcp;
16007 +
16008 +/* vars from ip_conntrack_rpc_udp */
16009 +extern struct list_head request_p_list_udp;
16010 +extern struct module *ip_conntrack_rpc_udp;
16011 +
16012 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
16013 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
16014 +
16015 +#define ASSERT_READ_LOCK(x)                                    \
16016 +do {                                                           \
16017 +       if (x == &request_p_list_udp)                           \
16018 +               MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);        \
16019 +       else if (x == &request_p_list_tcp)                      \
16020 +               MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);        \
16021 +} while (0)
16022 +
16023 +#define ASSERT_WRITE_LOCK(x)                                   \
16024 +do {                                                           \
16025 +       if (x == &request_p_list_udp)                           \
16026 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);       \
16027 +       else if (x == &request_p_list_tcp)                      \
16028 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);       \
16029 +} while (0)
16030 +
16031 +#include <linux/netfilter_ipv4/listhelp.h>
16032 +
16033 +const int IPT_RPC_CHAR_LEN = 11;
16034 +
16035 +
16036 +static int k_atoi(char *string)
16037 +{
16038 +       unsigned int result = 0;
16039 +       int maxoctet = IPT_RPC_CHAR_LEN;
16040 +
16041 +       for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
16042 +               if (*string < 0)
16043 +                       return(0);
16044 +               if (*string == 0)
16045 +                       break;
16046 +               if (*string < 48 || *string > 57) {
16047 +                       return(0);
16048 +               }
16049 +               result = result * 10 + ( *string - 48 );
16050 +       }
16051 +       return(result);
16052 +}
16053 +
16054 +
16055 +static int match_rpcs(char *c_procs, int i_procs, int proc)
16056 +{
16057 +       int   proc_ctr;
16058 +       char *proc_ptr;
16059 +       unsigned int proc_num;
16060 +
16061 +       DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
16062 +
16063 +       if (i_procs == -1)
16064 +               return 1;
16065 +
16066 +       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
16067 +
16068 +               proc_ptr = c_procs;
16069 +               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
16070 +               proc_num = k_atoi(proc_ptr);
16071 +
16072 +               if (proc_num == proc)
16073 +                       return 1;
16074 +       }
16075 +
16076 +       return 0;
16077 +}
16078 +
16079 +
16080 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
16081 +                       int *hotdrop, int dir, struct ip_conntrack *ct,
16082 +                       int offset, struct list_head request_p_list)
16083 +{
16084 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
16085 +       struct request_p *req_p;
16086 +       u_int32_t xid;
16087 +
16088 +
16089 +       /* Get XID */
16090 +       xid = *data;
16091 +
16092 +       /* This does sanity checking on RPC payloads,
16093 +        * and permits only the RPC "get port" (3)
16094 +        * in authorised procedures in client
16095 +        * communications with the portmapper.
16096 +        */
16097 +
16098 +       data += 5;
16099 +
16100 +       /* Get RPC requestor */
16101 +       if (IXDR_GET_INT32(data) != 3) {
16102 +               DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
16103 +               if(rpcinfo->strict == 1)
16104 +                       *hotdrop = 1;
16105 +               return 0;
16106 +       }
16107 +       DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
16108 +
16109 +       data++;
16110 +
16111 +       /* Jump Credentials and Verfifier */
16112 +       data = data + IXDR_GET_INT32(data) + 2;
16113 +       data = data + IXDR_GET_INT32(data) + 2;
16114 +
16115 +       /* Get RPC procedure */
16116 +       if (match_rpcs((char *)&rpcinfo->c_procs,
16117 +           rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
16118 +               DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
16119 +                       (unsigned int)IXDR_GET_INT32(data));
16120 +
16121 +               /* If the RPC conntrack half entry already exists .. */
16122 +
16123 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
16124 +                       case IPPROTO_UDP:
16125 +                               WRITE_LOCK(&ipct_rpc_udp_lock);
16126 +                       case IPPROTO_TCP:
16127 +                               WRITE_LOCK(&ipct_rpc_tcp_lock);
16128 +               }
16129 +               req_p = LIST_FIND(&request_p_list, request_p_cmp,
16130 +                                 struct request_p *, xid,
16131 +                                 ct->tuplehash[dir].tuple.src.ip,
16132 +                                 ct->tuplehash[dir].tuple.src.u.all);
16133 +
16134 +               if (req_p) {
16135 +                       DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16136 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
16137 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16138 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
16139 +
16140 +                       /* .. remove it */
16141 +                       if (del_timer(&req_p->timeout))
16142 +                               req_p->timeout.expires = 0;
16143 +
16144 +                               LIST_DELETE(&request_p_list, req_p);
16145 +                       DEBUGP("RPC req_p removed. [done]\n");
16146 +
16147 +               } else {
16148 +                       DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
16149 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
16150 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
16151 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
16152 +
16153 +               }
16154 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
16155 +                       case IPPROTO_UDP:
16156 +                               WRITE_UNLOCK(&ipct_rpc_udp_lock);
16157 +                       case IPPROTO_TCP:
16158 +                               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
16159 +               }
16160 +
16161 +               if(rpcinfo->strict == 1)
16162 +                       *hotdrop = 1;
16163 +               return 0;
16164 +       }
16165 +
16166 +       DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
16167 +               (unsigned int)IXDR_GET_INT32(data));
16168 +       return (1 && (!offset));
16169 +}
16170 +
16171 +
16172 +static int match(const struct sk_buff *skb, const struct net_device *in,
16173 +                const struct net_device *out, const void *matchinfo,
16174 +                int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
16175 +{
16176 +       struct ip_conntrack *ct;
16177 +       enum ip_conntrack_info ctinfo;
16178 +       const u_int32_t *data;
16179 +       enum ip_conntrack_dir dir;
16180 +       const struct tcphdr *tcp;
16181 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
16182 +       int port, portsok;
16183 +       int tval;
16184 +
16185 +
16186 +       DEBUGP("new packet to evaluate ..\n");
16187 +
16188 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
16189 +       if (!ct) {
16190 +               DEBUGP("no ct available [skip]\n");
16191 +               return 0;
16192 +       }
16193 +
16194 +       DEBUGP("ct detected. [cont]\n");
16195 +       dir = CTINFO2DIR(ctinfo);
16196 +
16197 +       /* we only want the client to server packets for matching */
16198 +       if (dir != IP_CT_DIR_ORIGINAL)
16199 +               return 0;
16200 +
16201 +       /* This does sanity checking on UDP or TCP packets,
16202 +        * like their respective modules.
16203 +        */
16204 +
16205 +       switch (ct->tuplehash[0].tuple.dst.protonum) {
16206 +
16207 +               case IPPROTO_UDP:
16208 +                       DEBUGP("PROTO_UDP [cont]\n");
16209 +                       if (offset == 0 && datalen < sizeof(struct udphdr)) {
16210 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
16211 +                               return 0;
16212 +                       }
16213 +
16214 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
16215 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16216 +                                       portsok++;
16217 +                                       break;
16218 +                               }
16219 +                       }
16220 +                       if (portsok == 0) {
16221 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16222 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16223 +                               return 0;
16224 +                       }
16225 +
16226 +                       if ((datalen - sizeof(struct udphdr)) != 56) {
16227 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
16228 +                               if (rpcinfo->strict == 1)
16229 +                                       *hotdrop = 1;
16230 +                               return 0;
16231 +                       }
16232 +                       DEBUGP("packet length is correct. [cont]\n");
16233 +
16234 +                       /* Get to the data */
16235 +                       data = (const u_int32_t *)hdr + 2;
16236 +
16237 +                       /* Check the RPC data */
16238 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
16239 +                                               dir, ct, offset,
16240 +                                               request_p_list_udp);
16241 +
16242 +                       return tval;
16243 +                       
16244 +               
16245 +               case IPPROTO_TCP:
16246 +                       DEBUGP("PROTO_TCP [cont]\n");
16247 +                       if (offset == 0 && datalen < sizeof(struct tcphdr)) {
16248 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
16249 +                               return 0;
16250 +                       }
16251 +       
16252 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
16253 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
16254 +                                       portsok++;
16255 +                                       break;
16256 +                               }
16257 +                       }
16258 +                       if (portsok == 0) {
16259 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
16260 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
16261 +                               return 0;
16262 +                       }
16263 +
16264 +                       tcp = hdr;
16265 +                       if (datalen == (tcp->doff * 4)) {
16266 +                               DEBUGP("packet does not contain any data. [match]\n");
16267 +                               return (1 && (!offset));
16268 +                       }
16269 +
16270 +                       /* Tests if packet len is ok */
16271 +                       if ((datalen - (tcp->doff * 4)) != 60) {
16272 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
16273 +                               if(rpcinfo->strict == 1)
16274 +                                       *hotdrop = 1;
16275 +                               return 0;
16276 +                       }
16277 +                       DEBUGP("packet length is correct. [cont]\n");
16278 +
16279 +                       /* Get to the data */
16280 +                       data = (const u_int32_t *)tcp + tcp->doff + 1;  
16281 +
16282 +                       /* Check the RPC data */
16283 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
16284 +                                               dir, ct, offset,
16285 +                                               request_p_list_tcp);
16286 +
16287 +                       return tval;
16288 +
16289 +       }
16290 +
16291 +       DEBUGP("transport protocol=%u, is not supported [skip]\n",
16292 +               ct->tuplehash[0].tuple.dst.protonum);
16293 +       return 0;
16294 +}
16295 +
16296 +
16297 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
16298 +                  unsigned int matchsize, unsigned int hook_mask)
16299 +{
16300 +       if (hook_mask
16301 +           & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
16302 +               | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
16303 +               printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
16304 +               return 0;
16305 +       }
16306 +
16307 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
16308 +               return 0;
16309 +
16310 +       return 1;
16311 +}
16312 +
16313 +
16314 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
16315 +                                       &match, &checkentry, NULL,
16316 +                                       THIS_MODULE };
16317 +
16318 +
16319 +static int __init init(void)
16320 +{
16321 +       int port;
16322 +
16323 +       DEBUGP("incrementing usage counts\n");
16324 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
16325 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
16326 +
16327 +       /* If no port given, default to standard RPC port */
16328 +       if (ports[0] == 0)
16329 +               ports[0] = RPC_PORT;
16330 +
16331 +       DEBUGP("registering match [%s] for;\n", rpc_match.name);
16332 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
16333 +               DEBUGP("  port %i (UDP|TCP);\n", ports[port]);
16334 +               ports_n_c++;
16335 +       }
16336 +       
16337 +       return ipt_register_match(&rpc_match);
16338 +}
16339 +
16340 +
16341 +static void fini(void)
16342 +{
16343 +       DEBUGP("unregistering match\n");
16344 +       ipt_unregister_match(&rpc_match);
16345 +
16346 +       DEBUGP("decrementing usage counts\n");
16347 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
16348 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
16349 +}
16350 +
16351 +
16352 +module_init(init);
16353 +module_exit(fini);
16354 +
16355 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
16356 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_sctp.c        1970-01-01 01:00:00.000000000 +0100
16357 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_sctp.c    2003-12-11 10:23:18.303155472 +0100
16358 @@ -0,0 +1,125 @@
16359 +/* IP tables module for matching the SCTP header
16360 + *
16361 + * $ipt_sctp.c,v 1.3 2002/05/29 15:09:00 laforge Exp$
16362 + *
16363 + * (C) 2003 by Harald Welte <laforge@gnumonks.org>
16364 + *
16365 + * This software is distributed under the terms GNU GPL v2
16366 + */
16367 +
16368 +#include <linux/module.h>
16369 +#include <linux/skbuff.h>
16370 +#include <linux/sctp.h>
16371 +
16372 +#include <linux/netfilter_ipv4/ip_tables.h>
16373 +#include <linux/netfilter_ipv4/ipt_sctp.h>
16374 +
16375 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
16376 +MODULE_DESCRIPTION("IP tables SCTP matching module");
16377 +MODULE_LICENSE("GPL");
16378 +
16379 +/* Returns 1 if the port is matched by the range, 0 otherwise */
16380 +static inline int
16381 +port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
16382 +{
16383 +       int ret;
16384 +
16385 +       ret = (port >= min && port <= max) ^ invert;
16386 +       return ret;
16387 +}
16388 +
16389 +static int chunk_match(const struct sk_buff *skb, u_int32_t chunks, u_int32_t chunk_mask)
16390 +{
16391 +       sctp_chunkhdr_t *ch = (sctp_chunkhdr_t *) skb->data;
16392 +
16393 +       u_int32_t chunks_present = 0;
16394 +
16395 +       do {
16396 +               u_int8_t *ch_end;
16397 +               ch_end = ((u_int8_t *) ch) + WORD_ROUND(ntohs(ch->length));
16398 +
16399 +               if (ch->type < 32)
16400 +                       chunks_present |= (1 << ch_type);
16401 +               else if (ch->type == SCTP_CID_ASCONF)
16402 +                       chunks_present |= (1 << 31);
16403 +               else if (ch->type == SCTP_CID_ASCONF_ACK)
16404 +                       chunks_present |= (1 << 30);
16405 +
16406 +               ch = (sctp_chunkhdr_t *) ch_end;
16407 +       } while (ch_end < skb->tail);
16408 +
16409 +       return ((chunks_present& chunk_mask) == chunks);
16410 +}
16411 +
16412 +static int match(const struct sk_buff *skb, const struct net_device *in,
16413 +                const struct net_device *out, const void *matchinfo,
16414 +                int offset, const void *hdr, u_int16_t datalen,
16415 +                int *hotdrop)
16416 +{
16417 +       const struct ipt_sctp_info *info = matchinfo;
16418 +       const struct iphdr *iph = skb->nh.iph;
16419 +       const struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
16420 +
16421 +       if (iph->protocol != IPPROTO_SCTP)
16422 +               return 0;
16423 +
16424 +       if (offset == 1) {
16425 +               duprintf("Dropping evil SCTP offset=1 frag.\n");
16426 +               *hotdrop = 1;
16427 +               return 0;
16428 +       } else if (offset == 0 && datalen < sizeof(struct sctphdr)) {
16429 +               /* We've been askd o examine this packet, and we can't.
16430 +                * Hence, no choice but to drop. */
16431 +               duprintf("Dropping evil SCTP offset=0 tinygram.\n");
16432 +               *hotdrop = 1;
16433 +               return 0;
16434 +       }
16435 +
16436 +       return (!offset
16437 +               && port_match(info->spts[0], info->spts[1],
16438 +                             ntohs(sh->source),
16439 +                             !!(info->invflags & IPT_SCTP_INV_SRCPT))
16440 +               && port_match(info->dpts[0], info->dpts[1],
16441 +                             ntohs(sh->dest),
16442 +                             !!(info->invflags & IPT_SCTP_INV_DSTPT))
16443 +               && chunk_match(skb, info->chunks, info->chunk_mask)
16444 +              );
16445 +}
16446 +
16447 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
16448 +                     void *matchinfo, unsigned int matchsize,
16449 +                     unsigned int hook_mask)
16450 +{
16451 +       const struct ipt_sctp_info *info = matchinfo;
16452 +
16453 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_sctp_info)))
16454 +               return 0;
16455 +
16456 +       if (ip->proto != IPPROTO_SCTP && !(ip->invflags & IPT_INV_PROTO))
16457 +               return 0;
16458 +
16459 +       if !(info->invflags & ~IPT_SCTP_INV_MASK)
16460 +               return 0;
16461 +
16462 +       return 1;
16463 +}
16464 +
16465 +static struct ipt_match sctp_match = {
16466 +       .name           = "sctp",
16467 +       .match          = &match,
16468 +       .checkentry     = &checkentry,
16469 +       .me             = THIS_MODULE,
16470 +};
16471 +
16472 +static int __init init(void)
16473 +{
16474 +       return ipt_register_match(&sctp_match);
16475 +}
16476 +
16477 +static void __exit fini(void)
16478 +{
16479 +       ipt_unregister_match(&sctp_match);
16480 +}
16481 +
16482 +module_init(init);
16483 +module_exit(fini);
16484 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
16485 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_state.c       2003-11-26 21:46:07.000000000 +0100
16486 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_state.c   2003-12-11 10:23:17.230318568 +0100
16487 @@ -23,10 +23,12 @@
16488         enum ip_conntrack_info ctinfo;
16489         unsigned int statebit;
16490  
16491 -       if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16492 -               statebit = IPT_STATE_INVALID;
16493 -       else
16494 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
16495 +               statebit = IPT_STATE_UNTRACKED;
16496 +       else if (ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
16497                 statebit = IPT_STATE_BIT(ctinfo);
16498 +       else
16499 +               statebit = IPT_STATE_INVALID;
16500  
16501         return (sinfo->statemask & statebit);
16502  }
16503 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
16504 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TCPLAG.c      1970-01-01 01:00:00.000000000 +0100
16505 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TCPLAG.c  2003-12-11 10:24:10.438229736 +0100
16506 @@ -0,0 +1,697 @@
16507 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
16508 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
16509 + *
16510 + * This program is free software; you can redistribute it and/or modify
16511 + * it under the terms of the GNU General Public License as published by
16512 + * the Free Software Foundation; either version 2 of the License, or
16513 + * (at your option) any later version.
16514 + *
16515 + * This program is distributed in the hope that it will be useful,
16516 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16517 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16518 + * GNU General Public License for more details.
16519 + *
16520 + * You should have received a copy of the GNU General Public License
16521 + * along with this program; if not, write to the Free Software
16522 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16523 + */
16524 +
16525 +/*
16526 + * This collects packets and attempts to make them into pairs
16527 + * based on its own knowledge of how typical network conversations
16528 + * operate. Once it has a pair, it logs the time between them.
16529 + */
16530 +#include <linux/module.h>
16531 +#include <linux/skbuff.h>
16532 +#include <linux/ip.h>
16533 +#include <linux/spinlock.h>
16534 +#include <net/icmp.h>
16535 +#include <net/udp.h>
16536 +#include <net/tcp.h>
16537 +#include <linux/netfilter_ipv4/ip_tables.h>
16538 +
16539 +#include <net/route.h>
16540 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
16541 +
16542 +#if 0
16543 +#define DEBUGP printk
16544 +#else
16545 +#define DEBUGP(format, args...)
16546 +#endif
16547 +
16548 +/*
16549 + * We need one spinlock for the hash table.
16550 + */
16551 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
16552 +
16553 +typedef struct timeval timeval_T;
16554 +
16555 +/*
16556 + * Linked lists of events in the connection,
16557 + * these store the SEQ numbers and the newest is always
16558 + * at the start of the linked list, then they get older
16559 + * down to the end of the linked list (this is not perfect
16560 + * if packets get out of order but we don't worry about fine
16561 + * details like that).
16562 + *
16563 + * Matching any event wipes out that event and also all other
16564 + * events down the chain (i.e. all older events).
16565 + * This keeps the linked list as short as possible.
16566 + */
16567 +typedef struct tcplag_event_S
16568 +{
16569 +       struct tcplag_event_S *next;
16570 +       u16 source_port;
16571 +       u16 dest_port;
16572 +       u32 expected_ACK;
16573 +       struct timeval stamp;
16574 +} tcplag_event_T;
16575 +
16576 +/*
16577 + * This stores the connection statistics
16578 + * We define connections more loosely than TCP/IP does,
16579 + * because we only consider the two hosts, not the ports
16580 + * Also, we list the host-pairs in low,high order which
16581 + * means that we don't care who originated the connection.
16582 + */
16583 +typedef struct tcplag_hash_S
16584 +{
16585 +       u32 low_ip;
16586 +       u32 high_ip;
16587 +       struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
16588 +       struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
16589 +       tcplag_event_T *h_ACK_list;     /* Try to match ACK packets coming from h in this list */
16590 +       tcplag_event_T *l_ACK_list;     /* Try to match ACK packets coming from l in this list */
16591 +       time_t stamp;                   /* When this bucket got added to the table */
16592 +       u16 count_l_SEQ_h_ACK;          /* Increment for each event */
16593 +       u16 count_h_SEQ_l_ACK;          /* Increment for each event */
16594 +} tcplag_hash_T;
16595 +
16596 +static tcplag_hash_T **hashtab = 0;
16597 +static u32 hashsize = 0;
16598 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
16599 +static u32 reaper_ix = 0;
16600 +
16601 +static void divide_down( timeval_T *T, int c )
16602 +{
16603 +       int remainder;
16604 +
16605 +       T->tv_usec /= c;
16606 +       remainder = T->tv_sec % c; /* Only works properly with positive numbers */
16607 +       remainder *= 1000000;
16608 +       T->tv_usec == remainder;
16609 +       T->tv_sec /= c;
16610 +}
16611 +
16612 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
16613 +{
16614 +       register long x;
16615 +
16616 +       x = tv1->tv_sec - tv2->tv_sec;
16617 +       if( x ) return( x );
16618 +       x = tv1->tv_usec - tv2->tv_usec;
16619 +       return( x );
16620 +}
16621 +
16622 +void sprint_timeval( char *buf, timeval_T *tv )
16623 +{
16624 +       if( tv->tv_sec )
16625 +               sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
16626 +       else
16627 +               sprintf( buf, "%lu", tv->tv_usec );
16628 +}
16629 +
16630 +/*
16631 + * This generates the log messages through printk()
16632 + *
16633 + * There is really no particular interest in the port numbers at this stage,
16634 + * they are only useful for matching up the request with the reply.
16635 + * The IP numbers are useful because some sites may be slower than others
16636 + * or may travel different routes, etc (OK, in theory changing the port number
16637 + * could also change the route but I don't like that sort of theory).
16638 + *
16639 + * The tags are:
16640 + *
16641 + * LIP=          The IP number of the side with the lowest lag
16642 + * RIP=          The IP number of the side with the highest lag
16643 + * LLAG=         The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
16644 + * RLAG=         The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
16645 + */
16646 +static void output( tcplag_hash_T *H, int level, const char *prefix )
16647 +{
16648 +       struct timeval ltm, rtm;
16649 +       u32 local_ip, remote_ip;
16650 +       char r_buf[ 20 ], l_buf[ 20 ];
16651 +/*
16652 + * We can't make sense of a connection that only passes data one way,
16653 + * In principle, at least the SYN and FIN should go both ways so we
16654 + * should get a few hits for every connection.
16655 + */
16656 +       if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
16657 +/*
16658 + * Calculate average times by dividing down
16659 + */
16660 +       divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
16661 +       divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
16662 +/*
16663 + * Sort these two by the lag so the the local is always the short lag
16664 + */
16665 +       if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
16666 +       {
16667 +               local_ip    = H->low_ip;
16668 +               remote_ip   = H->high_ip;
16669 +               rtm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
16670 +               rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
16671 +               ltm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
16672 +               ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
16673 +       }
16674 +       else
16675 +       {
16676 +               local_ip    = H->high_ip;
16677 +               remote_ip   = H->low_ip;
16678 +               ltm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
16679 +               ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
16680 +               rtm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
16681 +               rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
16682 +       }
16683 +/*
16684 + * Don't use a spinlock on the output,
16685 + * it is not guaranteed safe because some OTHER printk could
16686 + * split our log message so we want only one single printk.
16687 + *
16688 + * We use sprintf() to partially pre-digest the output
16689 + *
16690 + * Actually, neither this not the main netfilter LOG target is
16691 + * really safe from printk() overlap, basically syslog cannot
16692 + * be regarded as a guaranteed data output channel. It is good
16693 + * enough for most purposes.
16694 + */
16695 +       sprint_timeval( l_buf, &ltm );
16696 +       sprint_timeval( r_buf, &rtm );
16697 +       printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
16698 +                       level & 7, prefix,
16699 +                       NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
16700 +                       l_buf, r_buf );
16701 +}
16702 +
16703 +/*
16704 + * The reaper rolls through the hash table looking for old.
16705 + * Log entries are only generated at the reaping time
16706 + * (which means all log entries are out-of-date)
16707 + */
16708 +static void reaper( time_t now, int level, const char *prefix )
16709 +{
16710 +       int i;
16711 +
16712 +       now -= max_seconds;
16713 +       if( !hashsize ) return;
16714 +       if( !hashtab ) return;
16715 +       for( i = 0; i < 10; i++ )
16716 +       {
16717 +               if( ++reaper_ix >= hashsize ) reaper_ix = 0; 
16718 +
16719 +//             DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
16720 +
16721 +               if( hashtab[ reaper_ix ])
16722 +               {
16723 +                       tcplag_hash_T *found = 0;
16724 +
16725 +                       spin_lock_bh( &hash_lock );
16726 +                       if( hashtab[ reaper_ix ])
16727 +                       {
16728 +                               if( now > hashtab[ reaper_ix ]->stamp )
16729 +                               {
16730 +                                       DEBUGP( KERN_WARNING "reaper found expired entry\n" );
16731 +                                       found = hashtab[ reaper_ix ];
16732 +                                       hashtab[ reaper_ix ] = 0;
16733 +                               }
16734 +                       }
16735 +                       spin_unlock_bh( &hash_lock );
16736 +
16737 +                       if( found )
16738 +                       {
16739 +                               output( found, level, prefix );
16740 +                               kfree( found );
16741 +                       }
16742 +               }
16743 +       }
16744 +}
16745 +
16746 +/*
16747 + * Convert the connection characteristics into a number
16748 + * (not including the timestamp) FIXME: this is a sucky hash function
16749 + */
16750 +static u32 make_hash( tcplag_hash_T *connection )
16751 +{
16752 +       register u32 r;
16753 +
16754 +       r = connection->low_ip;
16755 +       r += connection->high_ip;
16756 +       return( r );
16757 +}
16758 +
16759 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
16760 +{
16761 +       int x;
16762 +
16763 +       x = con1->low_ip - con2->low_ip; if( x ) return( x );
16764 +       x = con1->high_ip - con2->high_ip;
16765 +       return( x );
16766 +}
16767 +
16768 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
16769 +{
16770 +       int x;
16771 +
16772 +       DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
16773 +       x = ev1->expected_ACK - ev2->expected_ACK;
16774 +       if( x ) return( x );
16775 +       DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
16776 +       x = ev1->source_port - ev2->source_port;
16777 +       if( x ) return( x );
16778 +       DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
16779 +       x = ev1->dest_port - ev2->dest_port;
16780 +       return( x );
16781 +}
16782 +
16783 +/*
16784 + * Go to the hash table and either find an existing connection that
16785 + * matches correctly or inject a new connection into the table.
16786 + * Once the connection is OK, chain the event onto the linked list.
16787 + */
16788 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
16789 +{
16790 +       u32 h, i;
16791 +
16792 +       if( !event ) return; /* Just to be safe */
16793 +       if( !hashsize ) return;
16794 +       if( !hashtab ) return;
16795 +
16796 +       h = make_hash( connection );
16797 +       h %= hashsize;
16798 +
16799 +       DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
16800 +
16801 +       spin_lock_bh( &hash_lock );
16802 +       for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
16803 +       {
16804 +               tcplag_hash_T *co_new = 0;
16805 +/*
16806 + * Consider existing entry
16807 + */
16808 +               if( hashtab[ h ])
16809 +               {
16810 +                       if( compare_connections( hashtab[ h ], connection )) continue;
16811 +                       co_new = hashtab[ h ];
16812 +                       DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
16813 +                       goto add_link;
16814 +               }
16815 +/*
16816 + * Use empty slot for new entry
16817 + */
16818 +               if( !hashtab[ h ])
16819 +               {
16820 +                       co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
16821 +                       memset( co_new, 0, sizeof( tcplag_hash_T ));
16822 +                       co_new->low_ip = connection->low_ip;
16823 +                       co_new->high_ip = connection->high_ip;
16824 +                       co_new->stamp = event->stamp.tv_sec;
16825 +                       hashtab[ h ] = co_new;
16826 +                       DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
16827 + add_link:
16828 +                       {
16829 +                               tcplag_event_T *ev_new;
16830 +
16831 +                               ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
16832 +                               memcpy( ev_new, event, sizeof( tcplag_event_T ));
16833 +                               if( direction )
16834 +                               {
16835 +                                       ev_new->next = co_new->h_ACK_list;
16836 +                                       co_new->h_ACK_list = ev_new;
16837 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
16838 +                               }
16839 +                               else
16840 +                               {
16841 +                                       ev_new->next = co_new->l_ACK_list;
16842 +                                       co_new->l_ACK_list = ev_new;
16843 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
16844 +                               }
16845 +                       }
16846 +                       goto done;
16847 +               }
16848 +       }
16849 + done:
16850 +       spin_unlock_bh( &hash_lock );
16851 +}
16852 +
16853 +/*
16854 + * Search the hash table for a matching connection,
16855 + * if we can't find one of those then we are stuffed.
16856 + *
16857 + * Once a connection has been found, scan along the list for
16858 + * a matching SEQ number and if that is found then calculate
16859 + * the lag, update the counters and cut the chain at the
16860 + * point where the matching SEQ is found.
16861 + */
16862 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
16863 +{
16864 +       u32 h, i;
16865 +
16866 +       if( !event ) return( 0 );
16867 +       if( !hashsize ) return( 0 );
16868 +       if( !hashtab ) return( 0 );
16869 +       h = make_hash( connection );
16870 +       h %= hashsize;
16871 +
16872 +       DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
16873 +
16874 +       for( i = 0; i < hashsize; i++ )
16875 +       {
16876 +               tcplag_hash_T *found = 0;
16877 +
16878 +               if( !hashtab[ h ]) return( 0 );
16879 +
16880 +               spin_lock_bh( &hash_lock );
16881 +               if( hashtab[ h ])
16882 +               {
16883 +                       if( !compare_connections( hashtab[ h ], connection ))
16884 +                       {
16885 +                               tcplag_event_T *ev, **evroot;
16886 +                               timeval_T *tv;
16887 +                               u16 *cn;
16888 +
16889 +                               found = hashtab[ h ];
16890 +                               if( direction )
16891 +                               {
16892 +                                       evroot = &found->h_ACK_list;
16893 +                                       tv = &found->lag_l_SEQ_h_ACK;
16894 +                                       cn = &found->count_l_SEQ_h_ACK;
16895 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
16896 +                               }
16897 +                               else
16898 +                               {
16899 +                                       evroot = &found->l_ACK_list;
16900 +                                       tv = &found->lag_h_SEQ_l_ACK;
16901 +                                       cn = &found->count_h_SEQ_l_ACK;
16902 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
16903 +                               }
16904 +                               for( ev = *evroot; ev; ev = ev->next )
16905 +                               {
16906 +                                       if( !compare_events( ev, event ))
16907 +                                       {
16908 +/*
16909 + * Calculate the lag (in two parts) and add that to the collection
16910 + */
16911 +                                               event->stamp.tv_sec -= ev->stamp.tv_sec;
16912 +                                               event->stamp.tv_usec -= ev->stamp.tv_usec;
16913 +                                               if( event->stamp.tv_usec < 0 )
16914 +                                               {
16915 +                                                       event->stamp.tv_usec += 1000000;
16916 +                                                       event->stamp.tv_sec++;
16917 +                                               }
16918 +                                               if( event->stamp.tv_sec < 0 )
16919 +                                               {
16920 +                                                       DEBUGP( KERN_WARNING "Negative lag detected\n" );
16921 +                                               }
16922 +                                               else
16923 +                                               {
16924 +                                                       tv->tv_sec += event->stamp.tv_sec;
16925 +                                                       tv->tv_usec += event->stamp.tv_usec;
16926 +                                                       ++*cn;
16927 +                                                       DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
16928 +                                                                       " (accumulator is up to %lu.%06lu, %u events)\n",
16929 +                                                                       event->stamp.tv_sec,
16930 +                                                                       event->stamp.tv_usec,
16931 +                                                                       tv->tv_sec, tv->tv_usec, *cn );
16932 +                                               }
16933 +/*
16934 + * Truncate the linked list.
16935 + *
16936 + * Visit each event in the list and return the memory to the pool.
16937 + *
16938 + * If a host is making multiple connections to the same remote host
16939 + * then this truncation will result in some requests not being
16940 + * monitored. Statistically we will still get some reasonable number
16941 + * of measurements and multiple simultaneous connections between host
16942 + * pairs don't happen all that often.
16943 + */
16944 +                                               *evroot = 0;
16945 +                                               while( ev )
16946 +                                               {
16947 +                                                       tcplag_event_T *ev_next = ev->next;
16948 +                                                       DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
16949 +                                                       kfree( ev );
16950 +                                                       ev = ev_next;
16951 +                                               }
16952 +/*
16953 + * TODO: overflow limit for *cn, force premature output() if necessary
16954 + * (and drop this connection from the hash table)
16955 + */
16956 +                                               break;
16957 +                                       }
16958 +                               }
16959 +                               goto done;
16960 +                       }
16961 +               }
16962 + done:
16963 +               spin_unlock_bh( &hash_lock );
16964 +
16965 +               if( found ) return( 1 );
16966 +               if( ++h >= hashsize ) h = 0;
16967 +       }       
16968 +       return( 0 );
16969 +}
16970 +
16971 +/*
16972 + * Here is our target data:
16973 + *
16974 + * pskb      --  The packet itself (see linux/skbuff.h for breakdown)
16975 + *
16976 + * hooknum   --
16977 + *
16978 + * in        --  The device that this packet came in on
16979 + *               (depending on the chain this may or may not exist)
16980 + *
16981 + * out       --  The device that this packet is just about to go
16982 + *               out onto (again existance depends on the chain)
16983 + *
16984 + * targinfo  --  Our private data (handed through from iptables command util)
16985 + *
16986 + * userinfo  --  Some more data
16987 + *
16988 + */
16989 +
16990 +static unsigned int target( struct sk_buff **pskb,
16991 +                                                       unsigned int hooknum,
16992 +                                                       const struct net_device *in,
16993 +                                                       const struct net_device *out,
16994 +                                                       const void *targinfo,
16995 +                                                       void *userinfo )
16996 +{
16997 +       struct iphdr *iph = ( *pskb )->nh.iph;
16998 +       const struct ipt_tcplag *el = targinfo;
16999 +       tcplag_hash_T connection;
17000 +       tcplag_event_T event;
17001 +       int direction;
17002 +/*
17003 + * We know we are dealing with IP here
17004 + * Fill in all the obvious fields
17005 + */
17006 +       if( iph->saddr > iph->daddr )
17007 +       {
17008 +               direction = 0;
17009 +               connection.high_ip = iph->saddr;
17010 +               connection.low_ip = iph->daddr;
17011 +       }
17012 +       else
17013 +       {
17014 +               direction = 1;
17015 +               connection.low_ip = iph->saddr;
17016 +               connection.high_ip = iph->daddr;
17017 +       }
17018 +       do_gettimeofday( &event.stamp );
17019 +/*
17020 + * Do a bit of cleaning
17021 + */
17022 +       reaper( event.stamp.tv_sec, el->level, el->prefix );
17023 +
17024 +       DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
17025 +                       event.stamp.tv_sec,
17026 +                       event.stamp.tv_usec,
17027 +                       in ? in->name : "none", out ? out->name : "none" );
17028 +/*
17029 + * Now start looking at the details
17030 + *
17031 + * First step is to identify this packet to see if it is 
17032 + * the sort of packet that we are interested in.
17033 + * Don't hold any locks while we are doing this because often
17034 + * we will just let the packet go without any further consideration.
17035 + */
17036 +       switch( iph->protocol )
17037 +       {
17038 +               case IPPROTO_TCP:
17039 +               {
17040 +                       struct tcphdr *tcp;
17041 +
17042 +                       if( ntohs( iph->frag_off ) & IP_OFFSET )
17043 +                       {
17044 +                               DEBUGP( KERN_WARNING "ignoring fragment\n" );
17045 +                               break;
17046 +                       }
17047 +                       tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
17048 +                       event.source_port = ntohs( tcp->source );
17049 +                       event.dest_port = ntohs( tcp->dest );
17050 +/*
17051 + * Every packet should have a valid SEQ number so use this to
17052 + * generate an ACK number. This works along the formula:
17053 + * -- Start with the SEQ number
17054 + * -- For SYN or FIN add 1 to that number
17055 + * -- For data packet, add the data length to that number
17056 + */
17057 +
17058 +/*
17059 + * Data length requires a bit of fiddling around
17060 + */
17061 +                       {
17062 +                               unsigned int data_len;
17063 +                               if( tcp->syn || tcp->fin )
17064 +                               {
17065 +                                       data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
17066 +                               }
17067 +                               else
17068 +                               {
17069 +                                       data_len = ntohs( iph->tot_len );
17070 +                                       data_len -= 4 * iph->ihl;  /* Subtract away IP header & options */
17071 +                                       data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
17072 +                               }
17073 +                               
17074 +                               DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
17075 +
17076 +                               if( data_len ) /* Only track events that demand an ACK */
17077 +                               {
17078 +                                       event.expected_ACK = ntohl( tcp->seq ) + data_len;
17079 +                                       hash_insert( &connection, &event, direction );
17080 +                               }
17081 +                               else
17082 +                               {
17083 +                                       DEBUGP( "Don't bother to insert this, ACK not required\n" );
17084 +                               }
17085 +                       }
17086 +
17087 +                       if( tcp->ack )
17088 +                       {
17089 +/*
17090 + * Now we consider the matching of an existing event.
17091 + * Reverse the port numbers and change the ACK number to the actual ACK number
17092 + * Note that the direction is reversed because the reply will be going
17093 + * the opposite way to the request.
17094 + */
17095 +                               event.expected_ACK = ntohl( tcp->ack_seq );
17096 +                               event.dest_port = ntohs( tcp->source );
17097 +                               event.source_port = ntohs( tcp->dest );
17098 +                               request_complete( &connection, &event, !direction );
17099 +                       }
17100 +                       else
17101 +                       {
17102 +                               DEBUGP( "Don't bother to check this, ACK not valid\n" );
17103 +                       }
17104 +               }
17105 +       }
17106 +       return( IPT_CONTINUE );
17107 +}
17108 +
17109 +/*
17110 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
17111 + * return( 1 ) if the entry is suitable
17112 + *
17113 + * tablename     --  
17114 + *
17115 + * e             --  
17116 + *
17117 + * targinfo      --  Our private data block (handed to us from iptables plug-in)
17118 + *
17119 + * targinfosize  --  The size of our private data block
17120 + *
17121 + * hook_mask     --  
17122 + *
17123 + *
17124 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
17125 + * all possible flag combos make sense. All we check for is correct data size.
17126 + */
17127 +static int checkentry( const char *tablename,
17128 +                                          const struct ipt_entry *e,
17129 +                                          void *targinfo,
17130 +                                          unsigned int targinfosize,
17131 +                                          unsigned int hook_mask )
17132 +{
17133 +       const struct ipt_tcplag *el = targinfo;
17134 +
17135 +       if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
17136 +       {
17137 +               DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
17138 +                               IPT_ALIGN( sizeof( struct ipt_tcplag )));
17139 +               return( 0 );
17140 +       }
17141 +       if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
17142 +       return( 1 );
17143 +}
17144 +
17145 +static struct ipt_target reg =
17146 +{
17147 +       { 0, 0 },
17148 +       "TCPLAG",
17149 +       &target,
17150 +       &checkentry,
17151 +       0,
17152 +    THIS_MODULE
17153 +};
17154 +
17155 +static int __init init( void )
17156 +{
17157 +       if( ipt_register_target( &reg )) return( -EINVAL );
17158 +       hashsize = 123; /* should be configurable */
17159 +       hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
17160 +       memset( hashtab, 0, sizeof( void * ) * hashsize );
17161 +       return( 0 );
17162 +}
17163 +
17164 +/*
17165 + * This should not need locks (in theory)
17166 + * because it can only get punted after it is no longer
17167 + * chained into any of the netfilter lists.
17168 + */
17169 +static void __exit fini( void )
17170 +{
17171 +       int i;
17172 +
17173 +       ipt_unregister_target( &reg );
17174 +/*
17175 + * Put back kernel memory
17176 + */
17177 +       for( i = 0; i < hashsize; i++ )
17178 +       {
17179 +               tcplag_hash_T *p;
17180 +
17181 +               if(( p = hashtab[ i ]))
17182 +               {
17183 +                       tcplag_event_T *ev, *evn;
17184 +
17185 +                       hashtab[ i ] = 0;
17186 +                       for( ev = p->h_ACK_list; ev; ev = evn )
17187 +                       {
17188 +                               evn = ev->next;
17189 +                               kfree( ev );
17190 +                       }
17191 +                       for( ev = p->l_ACK_list; ev; ev = evn )
17192 +                       {
17193 +                               evn = ev->next;
17194 +                               kfree( ev );
17195 +                       }
17196 +                       kfree( p );
17197 +               }
17198 +       }
17199 +       kfree( hashtab );
17200 +}
17201 +
17202 +module_init(init);
17203 +module_exit(fini);
17204 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
17205 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_time.c        1970-01-01 01:00:00.000000000 +0100
17206 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_time.c    2003-12-11 10:23:40.871724528 +0100
17207 @@ -0,0 +1,185 @@
17208 +/*
17209 +  This is a module which is used for time matching
17210 +  It is using some modified code from dietlibc (localtime() function)
17211 +  that you can find at http://www.fefe.de/dietlibc/
17212 +  This file is distributed under the terms of the GNU General Public
17213 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
17214 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
17215 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
17216 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
17217 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
17218 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
17219 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
17220 +*/
17221 +
17222 +#include <linux/module.h>
17223 +#include <linux/skbuff.h>
17224 +#include <linux/netfilter_ipv4/ip_tables.h>
17225 +#include <linux/netfilter_ipv4/ipt_time.h>
17226 +#include <linux/time.h>
17227 +
17228 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
17229 +MODULE_DESCRIPTION("Match arrival timestamp");
17230 +MODULE_LICENSE("GPL");
17231 +
17232 +struct tm
17233 +{
17234 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
17235 +       int tm_min;                   /* Minutes.     [0-59] */
17236 +       int tm_hour;                  /* Hours.       [0-23] */
17237 +       int tm_mday;                  /* Day.         [1-31] */
17238 +       int tm_mon;                   /* Month.       [0-11] */
17239 +       int tm_year;                  /* Year - 1900.  */
17240 +       int tm_wday;                  /* Day of week. [0-6] */
17241 +       int tm_yday;                  /* Days in year.[0-365] */
17242 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
17243 +
17244 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
17245 +       const char *tm_zone;          /* we don't care, we count from GMT */
17246 +};
17247 +
17248 +void
17249 +localtime(const time_t *timepr, struct tm *r);
17250 +
17251 +static int
17252 +match(const struct sk_buff *skb,
17253 +      const struct net_device *in,
17254 +      const struct net_device *out,
17255 +      const void *matchinfo,
17256 +      int offset,
17257 +      const void *hdr,
17258 +      u_int16_t datalen,
17259 +      int *hotdrop)
17260 +{
17261 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
17262 +       struct tm currenttime;                          /* time human readable */
17263 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
17264 +       u_int16_t packet_time;
17265 +       struct timeval kerneltimeval;
17266 +       time_t packet_local_time;
17267 +
17268 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
17269 +       if (info->kerneltime)
17270 +       {
17271 +               do_gettimeofday(&kerneltimeval);
17272 +               packet_local_time = kerneltimeval.tv_sec;
17273 +       }
17274 +       else
17275 +               packet_local_time = skb->stamp.tv_sec;
17276 +
17277 +       /* Transform the timestamp of the packet, in a human readable form */
17278 +       localtime(&packet_local_time, &currenttime);
17279 +
17280 +       /* check if we match this timestamp, we start by the days... */
17281 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
17282 +               return 0; /* the day doesn't match */
17283 +
17284 +       /* ... check the time now */
17285 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
17286 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
17287 +               return 0;
17288 +
17289 +       /* here we match ! */
17290 +       return 1;
17291 +}
17292 +
17293 +static int
17294 +checkentry(const char *tablename,
17295 +           const struct ipt_ip *ip,
17296 +           void *matchinfo,
17297 +           unsigned int matchsize,
17298 +           unsigned int hook_mask)
17299 +{
17300 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
17301 +
17302 +       /* First, check that we are in the correct hook */
17303 +       /* PRE_ROUTING, LOCAL_IN or FROWARD */
17304 +       if (hook_mask
17305 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
17306 +       {
17307 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
17308 +               return 0;
17309 +       }
17310 +       /* we use the kerneltime if we are in forward or output */
17311 +       info->kerneltime = 1;
17312 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
17313 +               /* if not, we use the skb time */
17314 +               info->kerneltime = 0;
17315 +
17316 +       /* Check the size */
17317 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
17318 +               return 0;
17319 +       /* Now check the coherence of the data ... */
17320 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
17321 +           (info->time_stop  > 1439))
17322 +       {
17323 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
17324 +               return 0;
17325 +       }
17326 +
17327 +       return 1;
17328 +}
17329 +
17330 +static struct ipt_match time_match
17331 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
17332 +
17333 +static int __init init(void)
17334 +{
17335 +       printk("ipt_time loading\n");
17336 +       return ipt_register_match(&time_match);
17337 +}
17338 +
17339 +static void __exit fini(void)
17340 +{
17341 +       ipt_unregister_match(&time_match);
17342 +       printk("ipt_time unloaded\n");
17343 +}
17344 +
17345 +module_init(init);
17346 +module_exit(fini);
17347 +
17348 +
17349 +/* The part below is borowed and modified from dietlibc */
17350 +
17351 +/* seconds per day */
17352 +#define SPD 24*60*60
17353 +
17354 +void
17355 +localtime(const time_t *timepr, struct tm *r) {
17356 +       time_t i;
17357 +       time_t timep;
17358 +       extern struct timezone sys_tz;
17359 +       const unsigned int __spm[12] =
17360 +               { 0,
17361 +                 (31),
17362 +                 (31+28),
17363 +                 (31+28+31),
17364 +                 (31+28+31+30),
17365 +                 (31+28+31+30+31),
17366 +                 (31+28+31+30+31+30),
17367 +                 (31+28+31+30+31+30+31),
17368 +                 (31+28+31+30+31+30+31+31),
17369 +                 (31+28+31+30+31+30+31+31+30),
17370 +                 (31+28+31+30+31+30+31+31+30+31),
17371 +                 (31+28+31+30+31+30+31+31+30+31+30),
17372 +               };
17373 +       register time_t work;
17374 +
17375 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
17376 +       work=timep%(SPD);
17377 +       r->tm_sec=work%60; work/=60;
17378 +       r->tm_min=work%60; r->tm_hour=work/60;
17379 +       work=timep/(SPD);
17380 +       r->tm_wday=(4+work)%7;
17381 +       for (i=1970; ; ++i) {
17382 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
17383 +               if (work>k)
17384 +                       work-=k;
17385 +               else
17386 +                       break;
17387 +       }
17388 +       r->tm_year=i-1900;
17389 +       for (i=11; i && __spm[i]>work; --i) ;
17390 +       r->tm_mon=i;
17391 +       r->tm_mday=work-__spm[i]+1;
17392 +}
17393 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
17394 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TRACE.c       1970-01-01 01:00:00.000000000 +0100
17395 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TRACE.c   2003-12-11 10:23:17.229318720 +0100
17396 @@ -0,0 +1,67 @@
17397 +/* This is a module which is used for setting 
17398 + * the NFC_TRACE flag in the nfcache field of an skb. 
17399 + */
17400 +#include <linux/module.h>
17401 +#include <linux/skbuff.h>
17402 +
17403 +#include <linux/netfilter_ipv4/ip_tables.h>
17404 +
17405 +static unsigned int
17406 +target(struct sk_buff **pskb,
17407 +       const struct net_device *in,
17408 +       const struct net_device *out,
17409 +       unsigned int hooknum,
17410 +       const void *targinfo,
17411 +       void *userinfo)
17412 +{
17413 +       (*pskb)->nfcache |= NFC_TRACE;
17414 +       return IPT_CONTINUE;
17415 +}
17416 +
17417 +static int
17418 +checkentry(const char *tablename,
17419 +          const struct ipt_entry *e,
17420 +           void *targinfo,
17421 +           unsigned int targinfosize,
17422 +           unsigned int hook_mask)
17423 +{
17424 +       if (targinfosize != 0) {
17425 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17426 +                      targinfosize);
17427 +               return 0;
17428 +       }
17429 +
17430 +       if (strcmp(tablename, "raw") != 0) {
17431 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17432 +               return 0;
17433 +       }
17434 +
17435 +       return 1;
17436 +}
17437 +
17438 +static struct ipt_target ipt_trace_reg = { 
17439 +       .name           = "TRACE", 
17440 +       .target         = target, 
17441 +       .checkentry     = checkentry, 
17442 +       .destroy        = NULL, 
17443 +       .me             = THIS_MODULE,
17444 +};
17445 +
17446 +static int __init init(void)
17447 +{
17448 +       if (ipt_register_target(&ipt_trace_reg))
17449 +               return -EINVAL;
17450 +
17451 +       return 0;
17452 +}
17453 +
17454 +static void __exit fini(void)
17455 +{
17456 +       ipt_unregister_target(&ipt_trace_reg);
17457 +}
17458 +
17459 +module_init(init);
17460 +module_exit(fini);
17461 +MODULE_LICENSE("GPL");
17462 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
17463 +MODULE_DESCRIPTION("IPv4 TRACE target");
17464 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
17465 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
17466 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_TTL.c     2003-12-11 10:23:41.987554896 +0100
17467 @@ -0,0 +1,110 @@
17468 +/* TTL modification target for IP tables
17469 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
17470 + *
17471 + * Version: 1.8
17472 + *
17473 + * This software is distributed under the terms of GNU GPL
17474 + */
17475 +
17476 +#include <linux/module.h>
17477 +#include <linux/skbuff.h>
17478 +#include <linux/ip.h>
17479 +#include <net/checksum.h>
17480 +
17481 +#include <linux/netfilter_ipv4/ip_tables.h>
17482 +#include <linux/netfilter_ipv4/ipt_TTL.h>
17483 +
17484 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
17485 +MODULE_DESCRIPTION("IP tables TTL modification module");
17486 +MODULE_LICENSE("GPL");
17487 +
17488 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
17489 +               const struct net_device *in, const struct net_device *out,
17490 +               const void *targinfo, void *userinfo)
17491 +{
17492 +       struct iphdr *iph = (*pskb)->nh.iph;
17493 +       const struct ipt_TTL_info *info = targinfo;
17494 +       u_int16_t diffs[2];
17495 +       int new_ttl;
17496 +                        
17497 +       switch (info->mode) {
17498 +               case IPT_TTL_SET:
17499 +                       new_ttl = info->ttl;
17500 +                       break;
17501 +               case IPT_TTL_INC:
17502 +                       new_ttl = iph->ttl + info->ttl;
17503 +                       if (new_ttl > 255)
17504 +                               new_ttl = 255;
17505 +                       break;
17506 +               case IPT_TTL_DEC:
17507 +                       new_ttl = iph->ttl + info->ttl;
17508 +                       if (new_ttl < 0)
17509 +                               new_ttl = 0;
17510 +                       break;
17511 +               default:
17512 +                       new_ttl = iph->ttl;
17513 +                       break;
17514 +       }
17515 +
17516 +       if (new_ttl != iph->ttl) {
17517 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
17518 +               iph->ttl = new_ttl;
17519 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
17520 +               iph->check = csum_fold(csum_partial((char *)diffs,
17521 +                                                   sizeof(diffs),
17522 +                                                   iph->check^0xFFFF));
17523 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
17524 +       }
17525 +
17526 +       return IPT_CONTINUE;
17527 +}
17528 +
17529 +static int ipt_ttl_checkentry(const char *tablename,
17530 +               const struct ipt_entry *e,
17531 +               void *targinfo,
17532 +               unsigned int targinfosize,
17533 +               unsigned int hook_mask)
17534 +{
17535 +       struct ipt_TTL_info *info = targinfo;
17536 +
17537 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
17538 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
17539 +                               targinfosize,
17540 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
17541 +               return 0;       
17542 +       }       
17543 +
17544 +       if (strcmp(tablename, "mangle")) {
17545 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
17546 +               return 0;
17547 +       }
17548 +
17549 +       if (info->mode > IPT_TTL_MAXMODE) {
17550 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
17551 +                       info->mode);
17552 +               return 0;
17553 +       }
17554 +
17555 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
17556 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
17557 +               return 0;
17558 +       }
17559 +       
17560 +       return 1;
17561 +}
17562 +
17563 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL", 
17564 +       ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
17565 +
17566 +static int __init init(void)
17567 +{
17568 +       return ipt_register_target(&ipt_TTL);
17569 +}
17570 +
17571 +static void __exit fini(void)
17572 +{
17573 +       ipt_unregister_target(&ipt_TTL);
17574 +}
17575 +
17576 +module_init(init);
17577 +module_exit(fini);
17578 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
17579 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
17580 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_u32.c     2003-12-11 10:23:43.131381008 +0100
17581 @@ -0,0 +1,211 @@
17582 +/* Kernel module to match u32 packet content. */
17583 +
17584 +/* 
17585 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
17586 +have specified values.  The specification of what to extract is general 
17587 +enough to find data at given offsets from tcp headers or payloads.
17588 +
17589 + --u32 tests
17590 + The argument amounts to a program in a small language described below.
17591 + tests := location = value |  tests && location = value
17592 + value := range | value , range
17593 + range := number | number : number
17594 +  a single number, n, is interpreted the same as n:n
17595 +  n:m is interpreted as the range of numbers >=n and <=m
17596 + location := number | location operator number
17597 + operator := & | << | >> | @
17598 +
17599 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
17600 + membership operator and the value syntax describes a set.  The @ operator
17601 + is what allows moving to the next header and is described further below.
17602 +
17603 + *** Until I can find out how to avoid it, there are some artificial limits
17604 + on the size of the tests:
17605 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
17606 + - no more than 10 ranges (and 9 commas) per value
17607 + - no more than 10 numbers (and 9 operators) per location
17608 +
17609 + To describe the meaning of location, imagine the following machine that
17610 + interprets it.  There are three registers:
17611 +  A is of type char*, initially the address of the IP header
17612 +  B and C are unsigned 32 bit integers, initially zero
17613 +
17614 +  The instructions are:
17615 +   number      B = number;
17616 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
17617 +   &number     C = C&number
17618 +   <<number    C = C<<number
17619 +   >>number    C = C>>number
17620 +   @number     A = A+C; then do the instruction number
17621 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
17622 +  Otherwise the result of the computation is the final value of C.
17623 +
17624 + Whitespace is allowed but not required in the tests.
17625 + However the characters that do occur there are likely to require
17626 + shell quoting, so it's a good idea to enclose the arguments in quotes.
17627 +
17628 +Example:
17629 + match IP packets with total length >= 256
17630 + The IP header contains a total length field in bytes 2-3.
17631 + --u32 "0&0xFFFF=0x100:0xFFFF" 
17632 + read bytes 0-3
17633 + AND that with FFFF (giving bytes 2-3),
17634 + and test whether that's in the range [0x100:0xFFFF]
17635 +
17636 +Example: (more realistic, hence more complicated)
17637 + match icmp packets with icmp type 0
17638 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
17639 + --u32 "6&0xFF=1 && ...
17640 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
17641 + Next test that it's not a fragment.
17642 +  (If so it might be part of such a packet but we can't always tell.)
17643 +  n.b. This test is generally needed if you want to match anything
17644 +  beyond the IP header.
17645 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
17646 + packet (not a fragment).  Alternatively, you can allow first fragments
17647 + by only testing the last 5 bits of byte 6.
17648 + ... 4&0x3FFF=0 && ...
17649 + Last test: the first byte past the IP header (the type) is 0
17650 + This is where we have to use the @syntax.  The length of the IP header
17651 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
17652 + IP header itself.
17653 + ... 0>>22&0x3C@0>>24=0"
17654 + The first 0 means read bytes 0-3,
17655 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
17656 +   the first byte, so only 22 bits is four times that plus a few more bits.
17657 + &3C then eliminates the two extra bits on the right and the first four 
17658 + bits of the first byte.
17659 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
17660 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
17661 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
17662 + @ means to use this number as a new offset into the packet, and read
17663 + four bytes starting from there.  This is the first 4 bytes of the icmp
17664 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
17665 + the value 24 to the right to throw out all but the first byte and compare
17666 + the result with 0.
17667 +
17668 +Example: 
17669 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
17670 + First we test that the packet is a tcp packet (similar to icmp).
17671 + --u32 "6&0xFF=6 && ...
17672 + Next, test that it's not a fragment (same as above).
17673 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
17674 + 0>>22&3C as above computes the number of bytes in the IP header.
17675 + @ makes this the new offset into the packet, which is the start of the
17676 + tcp header.  The length of the tcp header (again in 32 bit words) is
17677 + the left half of byte 12 of the tcp header.  The 12>>26&3C
17678 + computes this length in bytes (similar to the IP header before).
17679 + @ makes this the new offset, which is the start of the tcp payload.
17680 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
17681 + result is any of 1, 2, 5 or 8
17682 +*/
17683 +
17684 +#include <linux/module.h>
17685 +#include <linux/skbuff.h>
17686 +
17687 +#include <linux/netfilter_ipv4/ipt_u32.h>
17688 +#include <linux/netfilter_ipv4/ip_tables.h>
17689 +
17690 +/* #include <asm-i386/timex.h> for timing */
17691 +
17692 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
17693 +MODULE_DESCRIPTION("IP tables u32 matching module");
17694 +MODULE_LICENSE("GPL");
17695 +
17696 +static int
17697 +match(const struct sk_buff *skb,
17698 +      const struct net_device *in,
17699 +      const struct net_device *out,
17700 +      const void *matchinfo,
17701 +      int offset,
17702 +      const void *hdr,
17703 +      u_int16_t datalen,
17704 +      int *hotdrop)
17705 +{
17706 +       const struct ipt_u32 *data = matchinfo;
17707 +       int testind, i;
17708 +       unsigned char* origbase = (char*)skb->nh.iph;
17709 +       unsigned char* base = origbase;
17710 +       unsigned char* head = skb->head;
17711 +       unsigned char* end = skb->end;
17712 +       int nnums, nvals;
17713 +       u_int32_t pos, val;
17714 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
17715 +          cycles1 = get_cycles(); */
17716 +
17717 +       for (testind=0; testind < data->ntests; testind++) {
17718 +               base = origbase; /* reset for each test */
17719 +               pos = data->tests[testind].location[0].number;
17720 +               if (base+pos+3 > end || base+pos < head) 
17721 +                       return 0;
17722 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
17723 +                       (base[pos+2]<<8) + base[pos+3];
17724 +               nnums = data->tests[testind].nnums;
17725 +               for (i=1; i < nnums; i++) {
17726 +                       u_int32_t number = data->tests[testind].location[i].number;
17727 +                       switch (data->tests[testind].location[i].nextop) {
17728 +                       case IPT_U32_AND: 
17729 +                               val = val & number; 
17730 +                               break;
17731 +                       case IPT_U32_LEFTSH: 
17732 +                               val = val << number;
17733 +                               break;
17734 +                       case IPT_U32_RIGHTSH: 
17735 +                               val = val >> number; 
17736 +                               break;
17737 +                       case IPT_U32_AT:
17738 +                               base = base + val;
17739 +                               pos = number;
17740 +                               if (base+pos+3 > end || base+pos < head) 
17741 +                                       return 0;
17742 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
17743 +                                       (base[pos+2]<<8) + base[pos+3];
17744 +                               break;
17745 +                       }
17746 +               }
17747 +               nvals = data->tests[testind].nvalues;
17748 +               for (i=0; i < nvals; i++) {
17749 +                       if ((data->tests[testind].value[i].min <= val) &&
17750 +                           (val <= data->tests[testind].value[i].max)) {
17751 +                               break;
17752 +                       }
17753 +               }
17754 +               if (i >= data->tests[testind].nvalues) {
17755 +                       /* cycles2 = get_cycles(); 
17756 +                          printk("failed %d in %d cycles\n", testind, 
17757 +                                 cycles2-cycles1); */
17758 +                       return 0;
17759 +               }
17760 +       }
17761 +       /* cycles2 = get_cycles();
17762 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
17763 +       return 1;
17764 +}
17765 +
17766 +static int
17767 +checkentry(const char *tablename,
17768 +           const struct ipt_ip *ip,
17769 +           void *matchinfo,
17770 +           unsigned int matchsize,
17771 +           unsigned int hook_mask)
17772 +{
17773 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
17774 +               return 0;
17775 +       return 1;
17776 +}
17777 +
17778 +static struct ipt_match u32_match
17779 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
17780 +
17781 +static int __init init(void)
17782 +{
17783 +       return ipt_register_match(&u32_match);
17784 +}
17785 +
17786 +static void __exit fini(void)
17787 +{
17788 +       ipt_unregister_match(&u32_match);
17789 +}
17790 +
17791 +module_init(init);
17792 +module_exit(fini);
17793 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
17794 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_ULOG.c        2003-11-26 21:43:34.000000000 +0100
17795 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_ULOG.c    2003-12-11 10:23:14.923669232 +0100
17796 @@ -45,6 +45,7 @@
17797  #include <linux/netlink.h>
17798  #include <linux/netdevice.h>
17799  #include <linux/mm.h>
17800 +#include <linux/netfilter.h>
17801  #include <linux/netfilter_ipv4/ip_tables.h>
17802  #include <linux/netfilter_ipv4/ipt_ULOG.h>
17803  #include <linux/netfilter_ipv4/lockhelp.h>
17804 @@ -75,6 +76,10 @@
17805  MODULE_PARM(flushtimeout, "i");
17806  MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
17807  
17808 +static unsigned int nflog = 1;
17809 +MODULE_PARM(nflog, "i");
17810 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
17811 +
17812  /* global data structures */
17813  
17814  typedef struct {
17815 @@ -152,17 +157,17 @@
17816         return skb;
17817  }
17818  
17819 -static unsigned int ipt_ulog_target(struct sk_buff **pskb,
17820 -                                   const struct net_device *in,
17821 -                                   const struct net_device *out,
17822 -                                   unsigned int hooknum,
17823 -                                   const void *targinfo, void *userinfo)
17824 +static void ipt_ulog_packet(unsigned int hooknum,
17825 +                           const struct sk_buff *skb,
17826 +                           const struct net_device *in,
17827 +                           const struct net_device *out,
17828 +                           const struct ipt_ulog_info *loginfo,
17829 +                           const char *prefix)
17830  {
17831         ulog_buff_t *ub;
17832         ulog_packet_msg_t *pm;
17833         size_t size, copy_len;
17834         struct nlmsghdr *nlh;
17835 -       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
17836  
17837         /* ffs == find first bit set, necessary because userspace
17838          * is already shifting groupnumber, but we need unshifted.
17839 @@ -171,8 +176,8 @@
17840  
17841         /* calculate the size of the skb needed */
17842         if ((loginfo->copy_range == 0) ||
17843 -           (loginfo->copy_range > (*pskb)->len)) {
17844 -               copy_len = (*pskb)->len;
17845 +           (loginfo->copy_range > skb->len)) {
17846 +               copy_len = skb->len;
17847         } else {
17848                 copy_len = loginfo->copy_range;
17849         }
17850 @@ -209,19 +214,21 @@
17851  
17852         /* copy hook, prefix, timestamp, payload, etc. */
17853         pm->data_len = copy_len;
17854 -       pm->timestamp_sec = (*pskb)->stamp.tv_sec;
17855 -       pm->timestamp_usec = (*pskb)->stamp.tv_usec;
17856 -       pm->mark = (*pskb)->nfmark;
17857 +       pm->timestamp_sec = skb->stamp.tv_sec;
17858 +       pm->timestamp_usec = skb->stamp.tv_usec;
17859 +       pm->mark = skb->nfmark;
17860         pm->hook = hooknum;
17861 -       if (loginfo->prefix[0] != '\0')
17862 +       if (prefix != NULL)
17863 +               strncpy(pm->prefix, prefix, sizeof(pm->prefix));
17864 +       else if (loginfo->prefix[0] != '\0')
17865                 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
17866         else
17867                 *(pm->prefix) = '\0';
17868  
17869         if (in && in->hard_header_len > 0
17870 -           && (*pskb)->mac.raw != (void *) (*pskb)->nh.iph
17871 +           && skb->mac.raw != (void *) skb->nh.iph
17872             && in->hard_header_len <= ULOG_MAC_LEN) {
17873 -               memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
17874 +               memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
17875                 pm->mac_len = in->hard_header_len;
17876         } else
17877                 pm->mac_len = 0;
17878 @@ -236,8 +243,8 @@
17879         else
17880                 pm->outdev_name[0] = '\0';
17881  
17882 -       /* copy_len <= (*pskb)->len, so can't fail. */
17883 -       if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0)
17884 +       /* copy_len <= skb->len, so can't fail. */
17885 +       if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
17886                 BUG();
17887         
17888         /* check if we are building multi-part messages */
17889 @@ -261,8 +268,7 @@
17890  
17891         UNLOCK_BH(&ulog_lock);
17892  
17893 -       return IPT_CONTINUE;
17894 -
17895 +       return;
17896  
17897  nlmsg_failure:
17898         PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
17899 @@ -271,8 +277,35 @@
17900         PRINTR("ipt_ULOG: Error building netlink message\n");
17901  
17902         UNLOCK_BH(&ulog_lock);
17903 +}
17904 +
17905 +static unsigned int ipt_ulog_target(struct sk_buff **pskb,
17906 +                                   const struct net_device *in,
17907 +                                   const struct net_device *out,
17908 +                                   unsigned int hooknum,
17909 +                                   const void *targinfo, void *userinfo)
17910 +{
17911 +       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
17912  
17913 -       return IPT_CONTINUE;
17914 +       ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
17915
17916 +       return IPT_CONTINUE;
17917 +}
17918
17919 +static void ipt_logfn(unsigned int hooknum,
17920 +                     const struct sk_buff *skb,
17921 +                     const struct net_device *in,
17922 +                     const struct net_device *out,
17923 +                     const char *prefix)
17924 +{
17925 +       struct ipt_ulog_info loginfo = { 
17926 +               .nl_group = NFLOG_DEFAULT_NLGROUP,
17927 +               .copy_range = 0,
17928 +               .qthreshold = NFLOG_DEFAULT_QTHRESHOLD,
17929 +               .prefix = ""
17930 +       };
17931 +
17932 +       ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
17933  }
17934  
17935  static int ipt_ulog_checkentry(const char *tablename,
17936 @@ -337,6 +370,9 @@
17937                 return -EINVAL;
17938         }
17939  
17940 +       if (nflog)
17941 +               nf_log_register(PF_INET, &ipt_logfn);
17942 +       
17943         return 0;
17944  }
17945  
17946 @@ -347,6 +383,9 @@
17947  
17948         DEBUGP("ipt_ULOG: cleanup_module\n");
17949  
17950 +       if (nflog)
17951 +               nf_log_unregister(PF_INET, &ipt_logfn);
17952 +       
17953         ipt_unregister_target(&ipt_ulog_reg);
17954         sock_release(nflognl->sk_socket);
17955  
17956 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
17957 --- linux-2.6.0-test11.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
17958 +++ linux-2.6.0-test11/net/ipv4/netfilter/ipt_XOR.c     2003-12-11 10:24:11.736032440 +0100
17959 @@ -0,0 +1,107 @@
17960 +/* XOR target for IP tables
17961 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
17962 + * Based on ipt_TTL.c
17963 + *
17964 + * Version 1.0
17965 + *
17966 + * This software is distributed under the terms of GNU GPL
17967 + */
17968 +
17969 +#include <linux/module.h>
17970 +#include <linux/skbuff.h>
17971 +#include <linux/ip.h>
17972 +#include <linux/tcp.h>
17973 +#include <linux/udp.h>
17974 +
17975 +#include <linux/netfilter_ipv4/ip_tables.h>
17976 +#include <linux/netfilter_ipv4/ipt_XOR.h>
17977 +
17978 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
17979 +MODULE_DESCRIPTION("IP tables XOR module");
17980 +MODULE_LICENSE("GPL");
17981 +
17982 +static unsigned int ipt_xor_target(struct sk_buff **pskb, unsigned int hooknum, 
17983 +               const struct net_device *in, const struct net_device *out, 
17984 +               const void *targinfo, void *userinfo)
17985 +{
17986 +       struct ipt_XOR_info *info = (void *) targinfo;
17987 +       struct iphdr *iph = (*pskb)->nh.iph;
17988 +       struct tcphdr *tcph;
17989 +       struct udphdr *udph;
17990 +       int i, j, k;
17991 +  
17992 +       if (iph->protocol == IPPROTO_TCP) {
17993 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
17994 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
17995 +                       for (k=0; k<=info->block_size; k++) {
17996 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
17997 +                                               info->key[j];
17998 +                               i++;
17999 +                       }
18000 +                       j++;
18001 +                       if (info->key[j] == 0x00)
18002 +                               j = 0;
18003 +               }
18004 +       } else if (iph->protocol == IPPROTO_UDP) {
18005 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
18006 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
18007 +                       for (k=0; k<=info->block_size; k++) {
18008 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
18009 +                                               info->key[j];
18010 +                               i++;
18011 +                       }
18012 +                       j++;
18013 +                       if (info->key[j] == 0x00)
18014 +                               j = 0;
18015 +               }
18016 +       }
18017 +  
18018 +       return IPT_CONTINUE;
18019 +}
18020 +
18021 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
18022 +               void *targinfo, unsigned int targinfosize, 
18023 +               unsigned int hook_mask)
18024 +{
18025 +       struct ipt_XOR_info *info = targinfo;
18026 +
18027 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
18028 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
18029 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
18030 +       return 0;
18031 +       }       
18032 +
18033 +       if (strcmp(tablename, "mangle")) {
18034 +               printk(KERN_WARNING "XOR: can only be called from"
18035 +                               "\"mangle\" table, not \"%s\"\n", tablename);
18036 +               return 0; 
18037 +       }
18038 +
18039 +       if (!strcmp(info->key, "")) {
18040 +               printk(KERN_WARNING "XOR: You must specify a key");
18041 +               return 0;
18042 +       }
18043 +
18044 +       if (info->block_size == 0) {
18045 +               printk(KERN_WARNING "XOR: You must specify a block-size");
18046 +               return 0;
18047 +       }
18048 +
18049 +       return 1;
18050 +}
18051 +
18052 +static struct ipt_target ipt_XOR = { { NULL, NULL }, "XOR",
18053 +       ipt_xor_target, ipt_xor_checkentry, NULL, THIS_MODULE };
18054 +
18055 +static int __init init(void)
18056 +{
18057 +       return ipt_register_target(&ipt_XOR);
18058 +}
18059 +
18060 +static void __exit fini(void)
18061 +{
18062 +       ipt_unregister_target(&ipt_XOR);
18063 +}
18064 +
18065 +module_init(init);
18066 +module_exit(fini);
18067 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig linux-2.6.0-test11/net/ipv4/netfilter/Kconfig
18068 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Kconfig   2003-11-26 21:45:21.000000000 +0100
18069 +++ linux-2.6.0-test11/net/ipv4/netfilter/Kconfig       2003-12-11 12:57:13.875135120 +0100
18070 @@ -5,6 +5,620 @@
18071  menu "IP: Netfilter Configuration"
18072         depends on INET && NETFILTER
18073  
18074 +config IP_NF_TARGET_XOR
18075 +       tristate  ' XOR target support'
18076 +       depends on IP_NF_IPTABLES
18077 +       help
18078 +         XOR target support
18079 +         CONFIG_IP_NF_TARGET_XOR
18080 +         This option adds a `XOR' target, which can encrypt TCP and
18081 +         UDP traffic using a simple XOR encryption.
18082 +         
18083 +         If you want to compile it as a module, say M here and read
18084 +         Documentation/modules.txt.  If unsure, say `N'.
18085 +
18086 +
18087 +
18088 +config IP_NF_TARGET_TCPLAG
18089 +       tristate  ' TCPLAG target support'
18090 +       depends on IP_NF_IPTABLES
18091 +       help
18092 +         TCPLAG target support
18093 +         CONFIG_IP_NF_TARGET_TCPLAG
18094 +         This option adds a `TCPLAG' target, intended for INPUT, OUTPUT and
18095 +         FORWARD chains.
18096 +         
18097 +         This target has no effect on packets but will passively monitor TCP/IP
18098 +         connections and send lag estimates to syslog. Lag estimates are
18099 +         generated by considering the time delay between SEQ and matching ACK,
18100 +         which does not map precisely to any particular network property.
18101 +         We can say that a fast network will typically give smaller lag values
18102 +         than a slow network.
18103 +         
18104 +         Safest option is to choose `M' here and compile as a module,
18105 +         the module will do nothing until activated using the `iptables' utility.
18106 +         
18107 +
18108 +
18109 +
18110 +config IP_NF_TALK
18111 +       tristate  ' talk protocol support'
18112 +       depends on IP_NF_CONNTRACK
18113 +       help
18114 +         Talk protocol support
18115 +         CONFIG_IP_NF_TALK
18116 +         The talk protocols (both otalk/talk - or talk/ntalk, to confuse
18117 +         you by the different namings about which is old or which is new :-)
18118 +         use an additional channel to setup the talk session and a separated
18119 +         data channel for the actual conversation (like in FTP). Both the
18120 +         initiating and the setup channels are over UDP, while the data channel
18121 +         is over TCP, on a random port. The conntrack part of this extension
18122 +         will enable you to let in/out talk sessions easily by matching these
18123 +         connections as RELATED by the state match, while the NAT part helps
18124 +         you to let talk sessions trough a NAT machine.
18125 +         
18126 +         If you want to compile it as a module, say 'M' here and read
18127 +         Documentation/modules.txt.  If unsure, say 'N'.
18128 +
18129 +
18130 +
18131 +config IP_NF_RTSP
18132 +       tristate  ' RTSP protocol support'
18133 +       depends on IP_NF_CONNTRACK
18134 +       help
18135 +         RTSP protocol support
18136 +         CONFIG_IP_NF_RTSP
18137 +         Support the RTSP protocol.  This allows UDP transports to be setup
18138 +         properly, including RTP and RDT.
18139 +         
18140 +         If you want to compile it as a module, say 'M' here and read
18141 +         Documentation/modules.txt.  If unsure, say 'Y'.
18142 +         
18143 +
18144 +
18145 +
18146 +config IP_NF_RSH
18147 +       tristate  ' RSH protocol support'
18148 +       depends on IP_NF_CONNTRACK
18149 +       help
18150 +         RSH protocol support
18151 +         CONFIG_IP_NF_RSH
18152 +         The RSH connection tracker is required if the dynamic
18153 +         stderr "Server to Client" connection is to occur during a
18154 +         normal RSH session.  This typically operates as follows;
18155 +         
18156 +         Client 0:1023 --> Server 514    (stream 1 - stdin/stdout)
18157 +         Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
18158 +         
18159 +         This connection tracker will identify new RSH sessions,
18160 +         extract the outbound session details, and notify netfilter
18161 +         of pending "related" sessions.
18162 +         
18163 +         Warning: This module could be dangerous. It is not "best
18164 +         practice" to use RSH, use SSH in all instances.
18165 +         (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
18166 +         
18167 +         
18168 +         If you want to compile it as a module, say M here and read
18169 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
18170 +
18171 +
18172 +
18173 +config IP_NF_MATCH_RPC
18174 +       tristate  ' RPC match support'
18175 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
18176 +       help
18177 +         RPC match support
18178 +         CONFIG_IP_NF_MATCH_RPC
18179 +         This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
18180 +         matcher and tracker.
18181 +         
18182 +         This option supplies two connection tracking modules;
18183 +         ip_conntrack_rpc_udp and ip_conntrack_rpc_tcp, which track
18184 +         portmapper requests using UDP and TCP respectively.
18185 +         
18186 +         This option also adds an RPC match module for iptables, which
18187 +         matches both via the old "record match" method and a new
18188 +         "procedure match" method. The older method matches all RPC
18189 +         procedure packets that relate to previously recorded packets
18190 +         seen querying a portmapper. The newer method matches only
18191 +         those RPC procedure packets explicitly specified by the user,
18192 +         and that can then be related to previously recorded packets
18193 +         seen querying a portmapper.
18194 +         
18195 +         These three modules are required if RPCs are to be filtered
18196 +         accurately; as RPCs are allocated pseudo-randomly to UDP and
18197 +         TCP ports as they register with the portmapper.
18198 +         
18199 +         Up to 8 portmapper ports per module, and up to 128 RPC
18200 +         procedures per iptables rule, may be specified by the user,
18201 +         to enable effective RPC management.
18202 +         
18203 +         
18204 +         If you want to compile it as a module, say M here and read
18205 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
18206 +
18207 +
18208 +
18209 +config IP_NF_QUAKE3
18210 +       tristate  ' Quake III protocol support'
18211 +       depends on IP_NF_CONNTRACK
18212 +       help
18213 +         Quake III Arena protocol support
18214 +         CONFIG_IP_NF_QUAKE3
18215 +         Quake III Arena  connection tracking helper. This module allows for a
18216 +         stricter firewall rulebase if one only allows traffic to a master
18217 +         server. Connections to Quake III server IP addresses and ports returned
18218 +         by the master server will be tracked automatically.
18219 +         
18220 +         If you want to compile it as a module, say M here and read
18221 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
18222 +
18223 +
18224 +
18225 +config IP_NF_CT_PROTO_GRE
18226 +       tristate  ' GRE protocol support'
18227 +       depends on IP_NF_CONNTRACK
18228 +config IP_NF_PPTP
18229 +       tristate  ' PPTP protocol support'
18230 +       depends on IP_NF_CT_PROTO_GRE
18231 +       help
18232 +         PPTP conntrack and NAT support
18233 +         CONFIG_IP_NF_PPTP
18234 +         This module adds support for PPTP (Point to Point Tunnelling Protocol,
18235 +         RFC2637) conncection tracking and NAT.
18236 +         
18237 +         If you are running PPTP sessions over a stateful firewall or NAT box,
18238 +         you may want to enable this feature.
18239 +         
18240 +         Please note that not all PPTP modes of operation are supported yet.
18241 +         For more info, read top of the file net/ipv4/netfilter/ip_conntrack_pptp.c
18242 +         
18243 +         If you want to compile it as a module, say M here and read
18244 +         Documentation/modules.txt.  If unsure, say `N'.
18245 +         
18246 +         GRE protocol conntrack and NAT support
18247 +         CONFIG_IP_NF_CT_PROTO_GRE
18248 +         This module adds generic support for connection tracking and NAT of the
18249 +         GRE protocol (RFC1701, RFC2784).  Please note that this will only work
18250 +         with GRE connections using the key field of the GRE header.
18251 +         
18252 +         You will need GRE support to enable PPTP support.
18253 +         
18254 +         If you want to compile it as a module, say `M' here and read
18255 +         Documentation/modules.txt.  If unsire, say `N'.
18256 +
18257 +
18258 +
18259 +config IP_NF_MMS
18260 +       tristate  ' MMS protocol support'
18261 +       depends on IP_NF_CONNTRACK
18262 +       help
18263 +         MMS protocol support
18264 +         CONFIG_IP_NF_MMS
18265 +         Tracking MMS (Microsoft Windows Media Services) connections
18266 +         could be problematic if random ports are used to send the
18267 +         streaming content. This option allows users to track streaming
18268 +         connections over random UDP or TCP ports.
18269 +         
18270 +         If you want to compile it as a module, say M here and read
18271 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
18272 +
18273 +
18274 +
18275 +config IP_NF_TARGET_IPMARK
18276 +       tristate  ' IPMARK target support'
18277 +       depends on IP_NF_MANGLE
18278 +       help
18279 +         IPMARK target support
18280 +         CONFIG_IP_NF_TARGET_IPMARK
18281 +         This option adds a `IPMARK' target, which allows you to create rules
18282 +         in the `mangle' table which alter the netfilter mark (nfmark) field
18283 +         basing on the source or destination ip address of the packet.
18284 +         This is very useful for very fast massive mangling and marking.
18285 +         
18286 +         If you want to compile it as a module, say M here and read
18287 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
18288 +         
18289 +         
18290 +
18291 +
18292 +
18293 +config IP_NF_H323
18294 +       tristate  ' H.323 (netmeeting) support'
18295 +       depends on IP_NF_CONNTRACK
18296 +       help
18297 +         H.323 (netmeeting) support
18298 +         CONFIG_IP_NF_H323
18299 +         H.323 is a standard signalling protocol used by teleconferencing
18300 +         softwares like netmeeting. With the ip_conntrack_h323 and
18301 +         the ip_nat_h323 modules you can support the protocol on a connection
18302 +         tracking/NATing firewall.
18303 +         
18304 +         If you want to compile it as a module, say 'M' here and read
18305 +         Documentation/modules.txt.  If unsure, say 'N'.
18306 +
18307 +
18308 +
18309 +config IP_NF_EGG
18310 +       tristate  ' Eggdrop bot support'
18311 +       depends on IP_NF_CONNTRACK
18312 +       help
18313 +         Eggdrop bot support
18314 +         CONFIG_IP_NF_EGG
18315 +         If you are running an eggdrop hub bot on this machine, then you
18316 +         may want to enable this feature. This enables eggdrop bots to share
18317 +         their user file to other eggdrop bots.
18318 +         
18319 +         If you want to compile it as a module, say M here and read
18320 +         Documentation/modules.txt.  If unsure, say `N'.
18321 +
18322 +
18323 +
18324 +config IP_NF_CUSEEME
18325 +       tristate  ' CuSeeMe protocol support'
18326 +       depends on IP_NF_CONNTRACK
18327 +       help
18328 +         CuSeeMe protocol support
18329 +         CONFIG_IP_NF_CUSEEME
18330 +         The CuSeeMe conferencing protocol is problematic when used in
18331 +         conjunction with NAT; even though there are no random ports used for
18332 +         extra connections, the messages contain IP addresses inside them.
18333 +         This NAT helper mangles the IP address inside packets so both
18334 +         parties don't get confused.
18335 +         
18336 +         If you want to compile it as a module, say M here and read
18337 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
18338 +
18339 +
18340 +
18341 +
18342 +
18343 +config IP_NF_CONNTRACK_MARK
18344 +       bool  ' Connection mark tracking support'
18345 +config IP_NF_TARGET_CONNMARK
18346 +       tristate  ' CONNMARK target support'
18347 +       depends on IP_NF_IPTABLES
18348 +config IP_NF_MATCH_CONNMARK
18349 +       tristate  ' Connection mark match support'
18350 +       depends on IP_NF_IPTABLES
18351 +       help
18352 +         Per connection mark support
18353 +         CONFIG_IP_NF_CONNTRACK_MARK
18354 +         This option enables support for connection marks, used by the
18355 +         `CONNMARK' target and `connmark' match. Similar to the mark value
18356 +         of packets, but this mark value is kept in the conntrack session
18357 +         instead of the individual packets.
18358 +         
18359 +         CONNMARK target support
18360 +         CONFIG_IP_NF_TARGET_CONNMARK
18361 +         This option adds a `CONNMARK' target, which allows one to manipulate
18362 +         the connection mark value.  Similar to the MARK target, but
18363 +         affects the connection mark value rather than the packet mark value.
18364 +         
18365 +         If you want to compile it as a module, say M here and read
18366 +         Documentation/modules.txt.  The module will be called
18367 +         ipt_CONNMARK.o.  If unsure, say `N'.
18368 +         
18369 +         connmark match support
18370 +         CONFIP_IP_NF_MATCH_CONNMARK
18371 +         This option adds a `connmark' match, which allows you to match the
18372 +         connection mark value previously set for the session by `CONNMARK'.
18373 +
18374 +
18375 +
18376 +config IP_NF_MATCH_CONDITION
18377 +       tristate  ' condition match support'
18378 +       depends on IP_NF_IPTABLES
18379 +       help
18380 +         Condition variable match support
18381 +         CONFIG_IP_NF_MATCH_CONDITION
18382 +         This option allows you to match firewall rules against condition
18383 +         variables stored in the /proc/net/ipt_condition directory.
18384 +         
18385 +         If you want to compile it as a module, say M here and read
18386 +         Documentation/modules.txt.  If unsure, say `N'.
18387 +
18388 +
18389 +
18390 +config IP_NF_MATCH_ADDRTYPE
18391 +       tristate  ' address type match support'
18392 +       depends on IP_NF_IPTABLES
18393 +       help
18394 +         addrtype match support
18395 +         CONFIG_IP_NF_MATCH_ADDRTYPE
18396 +         This option allows you to match what routing thinks of an address,
18397 +         eg. UNICAST, LOCAL, BROADCAST, ...
18398 +         
18399 +         If you want to compile it as a module, say M here and read
18400 +         Documentation/modules.txt.  If unsure, say `N'.
18401 +
18402 +
18403 +
18404 +config IP_NF_MATCH_U32
18405 +       tristate  ' U32 match support'
18406 +       depends on IP_NF_U32
18407 +       help
18408 +         U32 patch support
18409 +         CONFIG_IP_NF_MATCH_U32
18410 +         U32 allows you to extract quantities of up to 4 bytes from a packet,
18411 +         AND them with specified masks, shift them by specified amounts and
18412 +         test whether the results are in any of a set of specified ranges.
18413 +         The specification of what to extract is general enough to skip over
18414 +         headers with lengths stored in the packet, as in IP or TCP header
18415 +         lengths.
18416 +         
18417 +         Details and examples are in the kernel module source.
18418 +         
18419 +
18420 +
18421 +
18422 +config IP_NF_TARGET_TTL
18423 +       tristate  ' TTL target support'
18424 +       depends on IP_NF_IPTABLES
18425 +       help
18426 +         TTL target support
18427 +         CONFIG_IP_NF_TARGET_TTL
18428 +         This option adds a `TTL' target, which enables the user to set
18429 +         the TTL value or increment / decrement the TTL value by a given
18430 +         amount.
18431 +         
18432 +         If you want to compile it as a module, say M here and read
18433 +         Documentation/modules.txt.  If unsure, say `N'.
18434 +
18435 +
18436 +
18437 +config IP_NF_MATCH_TIME
18438 +       tristate  ' TIME match support (EXPERIMENTAL)'
18439 +       depends on IP_NF_IPTABLES
18440 +       help
18441 +         TIME patch support
18442 +         CONFIG_IP_NF_MATCH_TIME
18443 +         This option adds a `time' match, which allows you
18444 +         to matchbased on the packet arrival time
18445 +         (arrival time at the machine which the netfilter is running on) or
18446 +         departure time (for locally generated packets).
18447 +         
18448 +         If you say Y here, try iptables -m time --help for more information.
18449 +         
18450 +         If you want to compile it as a module, say M here and read
18451 +         Documentation/modules.txt.  If unsure, say `N'.
18452 +         
18453 +
18454 +
18455 +
18456 +config IP_NF_MATCH_REALM
18457 +       tristate  ' realm match support'
18458 +       depends on IP_NF_IPTABLES
18459 +       help
18460 +         REALM match support
18461 +         CONFIG_IP_NF_MATCH_REALM
18462 +         This option adds a `realm' match, which allows you to use the realm
18463 +         key from the routing subsytem inside iptables.
18464 +         
18465 +         This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
18466 +         in tc world.
18467 +         
18468 +         If you want to compile it as a module, say M here and read
18469 +         Documentation/modules.txt.  If unsure, say `N'.
18470 +         
18471 +
18472 +
18473 +
18474 +config IP_NF_MATCH_RANDOM
18475 +       tristate  ' random match support'
18476 +       depends on IP_NF_IPTABLES
18477 +       help
18478 +         Random match support
18479 +         CONFIG_IP_NF_MATCH_RANDOM
18480 +         This option adds a `random' match,
18481 +         which allow you to match packets randomly
18482 +         following a given probability.
18483 +         
18484 +         If you want to compile it as a module, say M here and read
18485 +         Documentation/modules.txt.  If unsure, say `N'.
18486 +         
18487 +
18488 +
18489 +
18490 +config IP_NF_MATCH_QUOTA
18491 +       tristate  ' quota match support'
18492 +       depends on IP_NF_IPTABLES
18493 +       help
18494 +         quota match support
18495 +         CONFIG_IP_NF_MATCH_QUOTA
18496 +         This match implements network quotas.
18497 +         
18498 +         If you want to compile it as a module, say M here and read
18499 +         Documentation/modules.txt.  If unsure, say `N'.
18500 +         
18501 +
18502 +
18503 +
18504 +config IP_NF_MATCH_PSD
18505 +       tristate  ' psd match support'
18506 +       depends on IP_NF_IPTABLES
18507 +       help
18508 +         psd match support
18509 +         CONFIG_IP_NF_MATCH_PSD
18510 +         This option adds a `psd' match, which allows you to create rules in
18511 +         any iptables table wich will detect TCP and UDP port scans.
18512 +         
18513 +         If you want to compile it as a module, say M here and read
18514 +         Documentation/modules.txt.  If unsure, say `N'.
18515 +         
18516 +
18517 +
18518 +
18519 +config IP_NF_POOL
18520 +       tristate  ' IP address pool support'
18521 +       depends on IP_NF_IPTABLES
18522 +config IP_POOL_STATISTICS
18523 +       bool  ' enable statistics on pool usage'
18524 +       help
18525 +         pool match and target support
18526 +         CONFIG_IP_NF_MATCH_POOL
18527 +         Pool matching lets you use bitmaps with one bit per address from some
18528 +         range of IP addresses; the match depends on whether a checked source
18529 +         or destination address has its bit set in the pool.
18530 +         
18531 +         There is also a POOL netfilter target, which can be used to set or remove
18532 +         the addresses of a packet from a pool.
18533 +         
18534 +         To define and use pools, you need userlevel utilities: a patched iptables,
18535 +         and the program ippool(8), which defines the pools and their bounds.
18536 +         The current release of pool matching is ippool-0.0.2, and can be found
18537 +         in the archives of the netfilter mailing list at
18538 +         http://lists.samba.org/netfilter/.
18539 +         
18540 +         If you want to compile it as a module, say M here and read
18541 +         Documentation/modules.txt.  If unsure, say `N'.
18542 +         
18543 +         pool match and target statistics gathering
18544 +         CONFIG_IP_POOL_STATISTICS
18545 +         This option controls whether usage gathering code is compiled into the
18546 +         ip_pool module.  Disabling statistics may be substantially faster.
18547 +
18548 +
18549 +
18550 +config IP_NF_MATCH_OSF
18551 +       tristate  ' OSF match support (EXPERIMENTAL)'
18552 +       depends on IP_NF_IPTABLES
18553 +       help
18554 +         OSF match support
18555 +         CONFIG_IP_NF_MATCH_OSF
18556 +         
18557 +         The idea of passive OS fingerprint matching exists for quite a long time,
18558 +         but was created as extension fo OpenBSD pf only some weeks ago.
18559 +         Original idea was lurked in some OpenBSD mailing list (thanks
18560 +         grange@open...) and than adopted for Linux netfilter in form of this code.
18561 +         
18562 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
18563 +         his excellent p0f and than changed a bit for more convenience.
18564 +         
18565 +         This module compares some data(WS, MSS, options and it's order, ttl,
18566 +         df and others) from first SYN packet (actually from packets with SYN
18567 +         bit set) with hardcoded in fingers[] table ones.
18568 +         
18569 +         If you say Y here, try iptables -m osf --help for more information.
18570 +         
18571 +         If you want to compile it as a module, say M here and read
18572 +         Documentation/modules.txt.  If unsure, say `N'.
18573 +
18574 +
18575 +
18576 +config IP_NF_MATCH_NTH
18577 +       tristate  ' Nth match support'
18578 +       depends on IP_NF_IPTABLES
18579 +       help
18580 +         Nth match support
18581 +         CONFIG_IP_NF_MATCH_NTH
18582 +         This option adds a `Nth' match, which allow you to make
18583 +         rules that match every Nth packet.  By default there are
18584 +         16 different counters.
18585 +         
18586 +         [options]
18587 +         --every     Nth              Match every Nth packet
18588 +         [--counter]  num              Use counter 0-15 (default:0)
18589 +         [--start]    num              Initialize the counter at the number 'num'
18590 +         instead of 0. Must be between 0 and Nth-1
18591 +         [--packet]   num              Match on 'num' packet. Must be between 0
18592 +         and Nth-1.
18593 +         
18594 +         If --packet is used for a counter than
18595 +         there must be Nth number of --packet
18596 +         rules, covering all values between 0 and
18597 +         Nth-1 inclusively.
18598 +         
18599 +         If you want to compile it as a module, say M here and read
18600 +         Documentation/modules.txt.  If unsure, say `N'.
18601 +         
18602 +
18603 +
18604 +
18605 +config IP_NF_MATCH_MPORT
18606 +       tristate  ' Multiple port with ranges match support'
18607 +       depends on IP_NF_IPTABLES
18608 +       help
18609 +         Multiple port with ranges match support
18610 +         CONFIG_IP_NF_MATCH_MPORT
18611 +         This is an enhanced multiport match which supports port
18612 +         ranges as well as single ports.
18613 +         
18614 +         If you want to compile it as a module, say M here and read
18615 +         Documentation/modules.txt.  If unsure, say `N'.
18616 +
18617 +
18618 +
18619 +config IP_NF_TARGET_IPV4OPTSSTRIP
18620 +       tristate  ' IPV4OPTSSTRIP target support'
18621 +       depends on IP_NF_FILTER
18622 +       help
18623 +         IPV4OPTSSTRIP target support
18624 +         CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP
18625 +         This option adds an IPV4OPTSSTRIP target.
18626 +         This target allows you to strip all IP options in a packet.
18627 +         
18628 +         If you want to compile it as a module, say M here and read
18629 +         Documentation/modules.txt.  If unsure, say `N'.
18630 +         
18631 +
18632 +
18633 +
18634 +config IP_NF_MATCH_IPV4OPTIONS
18635 +       tristate  ' IPV4OPTIONS match support (EXPERIMENTAL)'
18636 +       depends on IP_NF_IPTABLES
18637 +       help
18638 +         IPV4OPTIONS patch support
18639 +         CONFIG_IP_NF_MATCH_IPV4OPTIONS
18640 +         This option adds a IPV4OPTIONS match.
18641 +         It allows you to filter options like source routing,
18642 +         record route, timestamp and router-altert.
18643 +         
18644 +         If you say Y here, try iptables -m ipv4options --help for more information.
18645 +         
18646 +         If you want to compile it as a module, say M here and read
18647 +         Documentation/modules.txt.  If unsure, say `N'.
18648 +         
18649 +
18650 +
18651 +
18652 +config IP_NF_MATCH_FUZZY
18653 +       tristate  ' fuzzy match support'
18654 +       depends on IP_NF_IPTABLES
18655 +       help
18656 +         Fuzzy Logic Controller match support
18657 +         CONFIG_IP_NF_MATCH_FUZZY
18658 +         This option adds a `fuzzy' match,
18659 +         which allows you to match packets according to a fuzzy logic
18660 +         based law .
18661 +         
18662 +         If you want to compile it as a module, say M here and read
18663 +         Documentation/modules.txt.  If unsure, say `N'.
18664 +         
18665 +
18666 +
18667 +
18668 +config IP_NF_MATCH_DSTLIMIT
18669 +       tristate  ' dstlimit match support'
18670 +       depends on IP_NF_IPTABLES
18671 +
18672 +
18673 +
18674 +config IP_NF_MATCH_CONNLIMIT
18675 +       tristate  ' Connections/IP limit match support'
18676 +       depends on IP_NF_IPTABLES
18677 +       help
18678 +         Connections/IP limit match support
18679 +         CONFIG_IP_NF_MATCH_CONNLIMIT
18680 +         This match allows you to restrict the number of parallel TCP
18681 +         connections to a server per client IP address (or address block).
18682 +         
18683 +         If you want to compile it as a module, say M here and read
18684 +         Documentation/modules.txt.  If unsure, say `N'.
18685 +
18686 +
18687 +
18688  config IP_NF_CONNTRACK
18689         tristate "Connection tracking (required for masq/NAT)"
18690         ---help---
18691 @@ -197,6 +811,15 @@
18692  
18693           To compile it as a module, choose M here.  If unsure, say N.
18694  
18695 +config IP_NF_MATCH_SCTP
18696 +       tristate "SCTP match support"
18697 +       depends on IP_NF_IPTABLES
18698 +       help
18699 +         This match allows iptables to match on the SCTP header.
18700 +
18701 +         If you want to compile it as a module, say M here and read
18702 +         <file:Documentation/modules.txt>. If unsure, say `N'.
18703 +
18704  config IP_NF_MATCH_LENGTH
18705         tristate "LENGTH match support"
18706         depends on IP_NF_IPTABLES
18707 @@ -527,6 +1150,42 @@
18708  
18709           To compile it as a module, choose M here.  If unsure, say N.
18710  
18711 +config IP_NF_RAW
18712 +       tristate "Raw table"
18713 +       depends on IP_NF_IPTABLES
18714 +       help
18715 +         This option adds a `raw' table to iptables: see the man page for
18716 +         iptables(8).  This table is the very first in the netfilter
18717 +         framework and hooks in at the PREROUTING and OUTPUT chains.
18718 +         The TRACE and NOTRACK targets can be used in this table only.
18719 +
18720 +         To compile it as a module, choose M here.  If unsure, say N.
18721 +
18722 +config IP_NF_TARGET_TRACE
18723 +       tristate "TRACE target support"
18724 +       depends on IP_NF_RAW
18725 +       help
18726 +         The TRACE target allows packets to be traced as those matches
18727 +         any subsequent rule in any table/rule. The matched rule and
18728 +         the packet is logged with the prefix
18729 +         
18730 +         TRACE: tablename/chainname/rulenum
18731 +         
18732 +         if the ipt_LOG or ipt_ULOG targets are loaded in.
18733 +
18734 +         To compile it as a module, choose M here.  If unsure, say N.
18735 +
18736 +config IP_NF_TARGET_NOTRACK
18737 +       tristate "NOTRACK target support"
18738 +       depends on IP_NF_RAW
18739 +       help
18740 +         The NOTRACK target allows a select rule to specify which
18741 +         packets *not* to enter the conntrack/NAT subsystems
18742 +         with all the consequences (no ICMP error tracking,
18743 +         no protocol helpers for the selected packets).
18744 +
18745 +         To compile it as a module, choose M here.  If unsure, say N.
18746 +
18747  config IP_NF_ARPTABLES
18748         tristate "ARP tables support"
18749  
18750 diff -Nur linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile linux-2.6.0-test11/net/ipv4/netfilter/Makefile
18751 --- linux-2.6.0-test11.org/net/ipv4/netfilter/Makefile  2003-11-26 21:43:25.000000000 +0100
18752 +++ linux-2.6.0-test11/net/ipv4/netfilter/Makefile      2003-12-11 12:56:51.470541136 +0100
18753 @@ -19,37 +19,91 @@
18754  # connection tracking
18755  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
18756  
18757 +# talk protocol support
18758 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
18759 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
18760 +
18761
18762 +# H.323 support
18763 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
18764 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
18765 +
18766 +
18767  # connection tracking helpers
18768 +
18769 +# rtsp protocol support
18770 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
18771 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
18772 +
18773 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
18774 +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
18775 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
18776  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
18777  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
18778  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
18779 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
18780 +
18781 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
18782 +
18783  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
18784  
18785  # NAT helpers 
18786 +obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
18787 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
18788  obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
18789  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
18790  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
18791  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
18792 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
18793 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
18794  
18795  # generic IP tables 
18796  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
18797  
18798 -# the three instances of ip_tables
18799 +# the four instances of ip_tables
18800  obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
18801  obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
18802  obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
18803 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
18804  
18805  # matches
18806 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
18807 +
18808 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
18809  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
18810  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
18811 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
18812 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
18813  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
18814 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
18815  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
18816  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
18817  
18818  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
18819  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
18820 +
18821 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
18822 +
18823  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
18824  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
18825 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
18826 +
18827 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
18828 +
18829 +
18830 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
18831 +
18832 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
18833 +
18834 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
18835 +
18836 +
18837 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
18838 +
18839 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
18840 +
18841 +
18842 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
18843  
18844  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
18845  
18846 @@ -59,10 +113,17 @@
18847  
18848  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
18849  
18850 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
18851 +
18852 +
18853  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
18854  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
18855 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
18856 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
18857  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
18858  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
18859 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
18860 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
18861  
18862  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
18863  
18864 @@ -72,6 +133,7 @@
18865  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
18866  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
18867  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
18868 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
18869  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
18870  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
18871  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
18872 @@ -79,8 +141,16 @@
18873  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
18874  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
18875  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
18876 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
18877 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
18878 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
18879 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
18880 +
18881 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
18882  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
18883  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
18884 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
18885 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
18886  
18887  # generic ARP tables
18888  obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
18889 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
18890 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_filter.c 2003-11-26 21:42:56.000000000 +0100
18891 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_filter.c     2003-12-11 10:23:17.233318112 +0100
18892 @@ -52,7 +52,7 @@
18893                 0,
18894                 sizeof(struct ip6t_entry),
18895                 sizeof(struct ip6t_standard),
18896 -               0, { 0, 0 }, { } },
18897 +               0, NULL, 0, { 0, 0 }, { } },
18898               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18899                 -NF_ACCEPT - 1 } },
18900             /* FORWARD */
18901 @@ -60,7 +60,7 @@
18902                 0,
18903                 sizeof(struct ip6t_entry),
18904                 sizeof(struct ip6t_standard),
18905 -               0, { 0, 0 }, { } },
18906 +               0, NULL, 0, { 0, 0 }, { } },
18907               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18908                 -NF_ACCEPT - 1 } },
18909             /* LOCAL_OUT */
18910 @@ -68,7 +68,7 @@
18911                 0,
18912                 sizeof(struct ip6t_entry),
18913                 sizeof(struct ip6t_standard),
18914 -               0, { 0, 0 }, { } },
18915 +               0, NULL, 0, { 0, 0 }, { } },
18916               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18917                 -NF_ACCEPT - 1 } }
18918      },
18919 @@ -77,7 +77,7 @@
18920         0,
18921         sizeof(struct ip6t_entry),
18922         sizeof(struct ip6t_error),
18923 -       0, { 0, 0 }, { } },
18924 +       0, NULL, 0, { 0, 0 }, { } },
18925        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18926           { } },
18927         "ERROR"
18928 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
18929 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_mangle.c 2003-11-26 21:43:36.000000000 +0100
18930 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_mangle.c     2003-12-11 10:23:17.234317960 +0100
18931 @@ -66,7 +66,7 @@
18932                 0,
18933                 sizeof(struct ip6t_entry),
18934                 sizeof(struct ip6t_standard),
18935 -               0, { 0, 0 }, { } },
18936 +               0, NULL, 0, { 0, 0 }, { } },
18937               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18938                 -NF_ACCEPT - 1 } },
18939             /* LOCAL_IN */
18940 @@ -74,7 +74,7 @@
18941                 0,
18942                 sizeof(struct ip6t_entry),
18943                 sizeof(struct ip6t_standard),
18944 -               0, { 0, 0 }, { } },
18945 +               0, NULL, 0, { 0, 0 }, { } },
18946               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18947                 -NF_ACCEPT - 1 } },
18948             /* FORWARD */
18949 @@ -82,7 +82,7 @@
18950                 0,
18951                 sizeof(struct ip6t_entry),
18952                 sizeof(struct ip6t_standard),
18953 -               0, { 0, 0 }, { } },
18954 +               0, NULL, 0, { 0, 0 }, { } },
18955               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18956                 -NF_ACCEPT - 1 } },
18957             /* LOCAL_OUT */
18958 @@ -90,7 +90,7 @@
18959                 0,
18960                 sizeof(struct ip6t_entry),
18961                 sizeof(struct ip6t_standard),
18962 -               0, { 0, 0 }, { } },
18963 +               0, NULL, 0, { 0, 0 }, { } },
18964               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18965                 -NF_ACCEPT - 1 } },
18966             /* POST_ROUTING */
18967 @@ -98,7 +98,7 @@
18968                 0,
18969                 sizeof(struct ip6t_entry),
18970                 sizeof(struct ip6t_standard),
18971 -               0, { 0, 0 }, { } },
18972 +               0, NULL, 0, { 0, 0 }, { } },
18973               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18974                 -NF_ACCEPT - 1 } }
18975      },
18976 @@ -107,7 +107,7 @@
18977         0,
18978         sizeof(struct ip6t_entry),
18979         sizeof(struct ip6t_error),
18980 -       0, { 0, 0 }, { } },
18981 +       0, NULL, 0, { 0, 0 }, { } },
18982        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18983           { } },
18984         "ERROR"
18985 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
18986 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6table_raw.c    1970-01-01 01:00:00.000000000 +0100
18987 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6table_raw.c        2003-12-11 10:23:17.234317960 +0100
18988 @@ -0,0 +1,158 @@
18989 +/*
18990 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
18991 + *
18992 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
18993 + */
18994 +#include <linux/module.h>
18995 +#include <linux/netfilter_ipv6/ip6_tables.h>
18996 +
18997 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
18998 +
18999 +#if 0
19000 +#define DEBUGP(x, args...)     printk(KERN_DEBUG x, ## args)
19001 +#else
19002 +#define DEBUGP(x, args...)
19003 +#endif
19004 +
19005 +/* Standard entry. */
19006 +struct ip6t_standard
19007 +{
19008 +       struct ip6t_entry entry;
19009 +       struct ip6t_standard_target target;
19010 +};
19011 +
19012 +struct ip6t_error_target
19013 +{
19014 +       struct ip6t_entry_target target;
19015 +       char errorname[IP6T_FUNCTION_MAXNAMELEN];
19016 +};
19017 +
19018 +struct ip6t_error
19019 +{
19020 +       struct ip6t_entry entry;
19021 +       struct ip6t_error_target target;
19022 +};
19023 +
19024 +static struct
19025 +{
19026 +       struct ip6t_replace repl;
19027 +       struct ip6t_standard entries[2];
19028 +       struct ip6t_error term;
19029 +} initial_table __initdata 
19030 += { { "raw", RAW_VALID_HOOKS, 3,
19031 +      sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
19032 +      { [NF_IP6_PRE_ROUTING]   0,
19033 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
19034 +      { [NF_IP6_PRE_ROUTING]   0,
19035 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
19036 +      0, NULL, { } },
19037 +    {
19038 +           /* PRE_ROUTING */
19039 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19040 +               0,
19041 +               sizeof(struct ip6t_entry),
19042 +               sizeof(struct ip6t_standard),
19043 +               0, NULL, 0, { 0, 0 }, { } },
19044 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19045 +               -NF_ACCEPT - 1 } },
19046 +           /* LOCAL_OUT */
19047 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19048 +               0,
19049 +               sizeof(struct ip6t_entry),
19050 +               sizeof(struct ip6t_standard),
19051 +               0, NULL, 0, { 0, 0 }, { } },
19052 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
19053 +               -NF_ACCEPT - 1 } },
19054 +    },
19055 +    /* ERROR */
19056 +    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
19057 +       0,
19058 +       sizeof(struct ip6t_entry),
19059 +       sizeof(struct ip6t_error),
19060 +       0, NULL, 0, { 0, 0 }, { } },
19061 +      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
19062 +         { } },
19063 +       "ERROR"
19064 +      }
19065 +    }
19066 +};
19067 +
19068 +static struct ip6t_table packet_raw = { 
19069 +       .name = "raw",
19070 +       .table = &initial_table.repl,
19071 +       .valid_hooks = RAW_VALID_HOOKS,
19072 +       .lock = RW_LOCK_UNLOCKED,
19073 +       .me = THIS_MODULE
19074 +};
19075 +
19076 +/* The work comes in here from netfilter.c. */
19077 +static unsigned int
19078 +ip6t_hook(unsigned int hook,
19079 +        struct sk_buff **pskb,
19080 +        const struct net_device *in,
19081 +        const struct net_device *out,
19082 +        int (*okfn)(struct sk_buff *))
19083 +{
19084 +       return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
19085 +}
19086 +
19087 +static struct nf_hook_ops ip6t_ops[] = { 
19088 +       { /* PRE_ROUTING */
19089 +               .hook = ip6t_hook,
19090 +               .owner = THIS_MODULE,
19091 +               .pf = PF_INET6,
19092 +               .hooknum = NF_IP6_PRE_ROUTING,
19093 +               .priority = NF_IP6_PRI_FIRST,
19094 +       },
19095 +       { /* LOCAL_OUT */
19096 +               .hook = ip6t_hook, 
19097 +               .owner = THIS_MODULE,
19098 +               .pf = PF_INET6, 
19099 +               .hooknum = NF_IP6_LOCAL_OUT,
19100 +               .priority = NF_IP6_PRI_FIRST,
19101 +       },
19102 +};
19103 +
19104 +static int __init init(void)
19105 +{
19106 +       int ret;
19107 +
19108 +       /* Register table */
19109 +       ret = ip6t_register_table(&packet_raw);
19110 +       if (ret < 0)
19111 +               return ret;
19112 +
19113 +       /* Register hooks */
19114 +       ret = nf_register_hook(&ip6t_ops[0]);
19115 +       if (ret < 0)
19116 +               goto cleanup_table;
19117 +
19118 +       ret = nf_register_hook(&ip6t_ops[1]);
19119 +       if (ret < 0)
19120 +               goto cleanup_hook0;
19121 +
19122 +       return ret;
19123 +
19124 + cleanup_hook0:
19125 +       nf_unregister_hook(&ip6t_ops[0]);
19126 + cleanup_table:
19127 +       ip6t_unregister_table(&packet_raw);
19128 +
19129 +       return ret;
19130 +}
19131 +
19132 +static void __exit fini(void)
19133 +{
19134 +       unsigned int i;
19135 +
19136 +       for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
19137 +               nf_unregister_hook(&ip6t_ops[i]);
19138 +
19139 +       ip6t_unregister_table(&packet_raw);
19140 +}
19141 +
19142 +module_init(init);
19143 +module_exit(fini);
19144 +MODULE_LICENSE("GPL");
19145 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19146 +MODULE_DESCRIPTION("IPv6 raw table");
19147 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
19148 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6_tables.c      2003-11-26 21:45:30.000000000 +0100
19149 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6_tables.c  2003-12-11 10:23:17.233318112 +0100
19150 @@ -12,6 +12,7 @@
19151   */
19152  #include <linux/config.h>
19153  #include <linux/skbuff.h>
19154 +#include <linux/socket.h>
19155  #include <linux/kmod.h>
19156  #include <linux/vmalloc.h>
19157  #include <linux/netdevice.h>
19158 @@ -24,8 +25,17 @@
19159  #include <asm/semaphore.h>
19160  #include <linux/proc_fs.h>
19161  
19162 +#include <linux/netfilter.h>
19163  #include <linux/netfilter_ipv6/ip6_tables.h>
19164  
19165 +static const char *hook6names[] = { 
19166 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
19167 +       [NF_IP6_LOCAL_IN] "INPUT",
19168 +       [NF_IP6_FORWARD] "FORWARD",
19169 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
19170 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
19171 +};
19172 +
19173  MODULE_LICENSE("GPL");
19174  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19175  MODULE_DESCRIPTION("IPv6 packet filter");
19176 @@ -403,6 +413,12 @@
19177  
19178                         t = ip6t_get_target(e);
19179                         IP_NF_ASSERT(t->u.kernel.target);
19180 +
19181 +                       /* The packet traced and the rule isn't an unconditional return/END. */
19182 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
19183 +                               nf_log_packet(AF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
19184 +                                                 table->name, e->chainname, e->rulenum);
19185 +                       }
19186                         /* Standard target? */
19187                         if (!t->u.kernel.target->target) {
19188                                 int v;
19189 @@ -556,6 +572,29 @@
19190         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
19191  }
19192  
19193 +static inline int
19194 +find_error_target(struct ip6t_entry *s, 
19195 +                 struct ip6t_entry *e,
19196 +                 char **chainname)
19197 +{
19198 +       struct ip6t_entry_target *t;
19199 +       static struct ip6t_entry *found = NULL;
19200 +
19201 +       if (s == e) {
19202 +               if (!found)
19203 +                       return 0;
19204 +               t = ip6t_get_target(found);
19205 +               if (strcmp(t->u.user.name, 
19206 +                          IP6T_ERROR_TARGET) == 0) {
19207 +                       *chainname = t->data;
19208 +                       return 1;
19209 +               }
19210 +       } else
19211 +               found = s;
19212 +       
19213 +       return 0;
19214 +}
19215 +
19216  /* All zeroes == unconditional rule. */
19217  static inline int
19218  unconditional(const struct ip6t_ip6 *ipv6)
19219 @@ -575,6 +614,8 @@
19220  mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
19221  {
19222         unsigned int hook;
19223 +       char *chainname = NULL;
19224 +       u_int32_t rulenum;
19225  
19226         /* No recursion; use packet counter to save back ptrs (reset
19227            to 0 as we leave), and comefrom to save source hook bitmask */
19228 @@ -588,6 +629,8 @@
19229  
19230                 /* Set initial back pointer. */
19231                 e->counters.pcnt = pos;
19232 +               rulenum = 1;
19233 +               chainname = (char *) hook6names[hook];
19234  
19235                 for (;;) {
19236                         struct ip6t_standard_target *t
19237 @@ -600,6 +643,8 @@
19238                         }
19239                         e->comefrom
19240                                 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
19241 +                       e->rulenum = rulenum++;
19242 +                       e->chainname = chainname;
19243  
19244                         /* Unconditional return/END. */
19245                         if (e->target_offset == sizeof(struct ip6t_entry)
19246 @@ -609,6 +654,10 @@
19247                             && unconditional(&e->ipv6)) {
19248                                 unsigned int oldpos, size;
19249  
19250 +                               /* Set unconditional rulenum to zero. */
19251 +                               e->rulenum = 0;
19252 +                               e->counters.bcnt = 0;
19253 +
19254                                 /* Return: backtrack through the last
19255                                    big jump. */
19256                                 do {
19257 @@ -634,6 +683,11 @@
19258                                                 (newinfo->entries + pos);
19259                                 } while (oldpos == pos + e->next_offset);
19260  
19261 +                               /* Restore chainname, rulenum. */
19262 +                               chainname = e->chainname;
19263 +                               rulenum = e->counters.bcnt;
19264 +                               e->counters.bcnt = 0;
19265 +
19266                                 /* Move along one */
19267                                 size = e->next_offset;
19268                                 e = (struct ip6t_entry *)
19269 @@ -649,6 +703,17 @@
19270                                         /* This a jump; chase it. */
19271                                         duprintf("Jump rule %u -> %u\n",
19272                                                  pos, newpos);
19273 +                                       e->counters.bcnt = rulenum++;
19274 +                                       rulenum = 1;
19275 +                                       e = (struct ip6t_entry *)
19276 +                                               (newinfo->entries + newpos);
19277 +                                       if (IP6T_ENTRY_ITERATE(newinfo->entries,
19278 +                                                              newinfo->size,
19279 +                                                              find_error_target,
19280 +                                                              e, &chainname) == 0) {
19281 +                                               printk("ip6_tables: table screwed up!\n");
19282 +                                               return 0;
19283 +                                       }
19284                                 } else {
19285                                         /* ... this is a fallthru */
19286                                         newpos = pos + e->next_offset;
19287 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
19288 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_condition.c  1970-01-01 01:00:00.000000000 +0100
19289 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_condition.c      2003-12-11 10:23:45.446029128 +0100
19290 @@ -0,0 +1,254 @@
19291 +/*-------------------------------------------*\
19292 +|    Netfilter Condition Module for IPv6      |
19293 +|                                             |
19294 +|  Description: This module allows firewall   |
19295 +|    rules to match using condition variables |
19296 +|    stored in /proc files.                   |
19297 +|                                             |
19298 +|  Author: Stephane Ouellette     2003-02-10  |
19299 +|          <ouellettes@videotron.ca>          |
19300 +|                                             |
19301 +|  This software is distributed under the     |
19302 +|  terms of the GNU GPL.                      |
19303 +\*-------------------------------------------*/
19304 +
19305 +#include<linux/module.h>
19306 +#include<linux/proc_fs.h>
19307 +#include<linux/spinlock.h>
19308 +#include<linux/string.h>
19309 +#include<asm/atomic.h>
19310 +#include<linux/netfilter_ipv6/ip6_tables.h>
19311 +#include<linux/netfilter_ipv6/ip6t_condition.h>
19312 +
19313 +
19314 +#ifndef CONFIG_PROC_FS
19315 +#error  "Proc file system support is required for this module"
19316 +#endif
19317 +
19318 +
19319 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
19320 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
19321 +MODULE_LICENSE("GPL");
19322 +
19323 +
19324 +struct condition_variable {
19325 +       struct condition_variable *next;
19326 +       struct proc_dir_entry *status_proc;
19327 +       atomic_t refcount;
19328 +        int enabled; /* TRUE == 1, FALSE == 0 */
19329 +};
19330 +
19331 +
19332 +static rwlock_t list_lock;
19333 +static struct condition_variable *head = NULL;
19334 +static struct proc_dir_entry *proc_net_condition = NULL;
19335 +
19336 +
19337 +static int
19338 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
19339 +                       int length, int *eof, void *data)
19340 +{
19341 +       struct condition_variable *var =
19342 +           (struct condition_variable *) data;
19343 +
19344 +       if (offset == 0) {
19345 +               *start = buffer;
19346 +               buffer[0] = (var->enabled) ? '1' : '0';
19347 +               buffer[1] = '\n';
19348 +               return 2;
19349 +       }
19350 +
19351 +       *eof = 1;
19352 +       return 0;
19353 +}
19354 +
19355 +
19356 +static int
19357 +ipt_condition_write_info(struct file *file, const char *buffer,
19358 +                        unsigned long length, void *data)
19359 +{
19360 +       struct condition_variable *var =
19361 +           (struct condition_variable *) data;
19362 +
19363 +       if (length) {
19364 +               /* Match only on the first character */
19365 +               switch (buffer[0]) {
19366 +               case '0':
19367 +                       var->enabled = 0;
19368 +                       break;
19369 +               case '1':
19370 +                       var->enabled = 1;
19371 +               }
19372 +       }
19373 +
19374 +       return (int) length;
19375 +}
19376 +
19377 +
19378 +static int
19379 +match(const struct sk_buff *skb, const struct net_device *in,
19380 +      const struct net_device *out, const void *matchinfo, int offset,
19381 +      const void *hdr, u_int16_t datalen, int *hotdrop)
19382 +{
19383 +       const struct condition6_info *info =
19384 +           (const struct condition6_info *) matchinfo;
19385 +       struct condition_variable *var;
19386 +       int condition_status = 0;
19387 +
19388 +       read_lock(&list_lock);
19389 +
19390 +       for (var = head; var; var = var->next) {
19391 +               if (strcmp(info->name, var->status_proc->name) == 0) {
19392 +                       condition_status = var->enabled;
19393 +                       break;
19394 +               }
19395 +       }
19396 +
19397 +       read_unlock(&list_lock);
19398 +
19399 +       return condition_status ^ info->invert;
19400 +}
19401 +
19402 +
19403 +
19404 +static int
19405 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
19406 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
19407 +{
19408 +       struct condition6_info *info =
19409 +           (struct condition6_info *) matchinfo;
19410 +       struct condition_variable *var, *newvar;
19411 +
19412 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19413 +               return 0;
19414 +
19415 +       /* The first step is to check if the condition variable already exists. */
19416 +       /* Here, a read lock is sufficient because we won't change the list */
19417 +       read_lock(&list_lock);
19418 +
19419 +       for (var = head; var; var = var->next) {
19420 +               if (strcmp(info->name, var->status_proc->name) == 0) {
19421 +                       atomic_inc(&var->refcount);
19422 +                       read_unlock(&list_lock);
19423 +                       return 1;
19424 +               }
19425 +       }
19426 +
19427 +       read_unlock(&list_lock);
19428 +
19429 +       /* At this point, we need to allocate a new condition variable */
19430 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
19431 +
19432 +       if (!newvar)
19433 +               return -ENOMEM;
19434 +
19435 +       /* Create the condition variable's proc file entry */
19436 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
19437 +
19438 +       if (!newvar->status_proc) {
19439 +         /*
19440 +          * There are two possibilities:
19441 +          *  1- Another condition variable with the same name has been created, which is valid.
19442 +          *  2- There was a memory allocation error.
19443 +          */
19444 +               kfree(newvar);
19445 +               read_lock(&list_lock);
19446 +
19447 +               for (var = head; var; var = var->next) {
19448 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
19449 +                               atomic_inc(&var->refcount);
19450 +                               read_unlock(&list_lock);
19451 +                               return 1;
19452 +                       }
19453 +               }
19454 +
19455 +               read_unlock(&list_lock);
19456 +               return -ENOMEM;
19457 +       }
19458 +
19459 +       atomic_set(&newvar->refcount, 1);
19460 +       newvar->enabled = 0;
19461 +       newvar->status_proc->owner = THIS_MODULE;
19462 +       newvar->status_proc->data = newvar;
19463 +       wmb();
19464 +       newvar->status_proc->read_proc = ipt_condition_read_info;
19465 +       newvar->status_proc->write_proc = ipt_condition_write_info;
19466 +
19467 +       write_lock(&list_lock);
19468 +
19469 +       newvar->next = head;
19470 +       head = newvar;
19471 +
19472 +       write_unlock(&list_lock);
19473 +
19474 +       return 1;
19475 +}
19476 +
19477 +
19478 +static void
19479 +destroy(void *matchinfo, unsigned int matchsize)
19480 +{
19481 +       struct condition6_info *info =
19482 +           (struct condition6_info *) matchinfo;
19483 +       struct condition_variable *var, *prev = NULL;
19484 +
19485 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
19486 +               return;
19487 +
19488 +       write_lock(&list_lock);
19489 +
19490 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
19491 +            prev = var, var = var->next);
19492 +
19493 +       if (var && atomic_dec_and_test(&var->refcount)) {
19494 +               if (prev)
19495 +                       prev->next = var->next;
19496 +               else
19497 +                       head = var->next;
19498 +
19499 +               write_unlock(&list_lock);
19500 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
19501 +               kfree(var);
19502 +       } else
19503 +               write_unlock(&list_lock);
19504 +}
19505 +
19506 +
19507 +static struct ip6t_match condition_match = {
19508 +       .name = "condition",
19509 +       .match = &match,
19510 +       .checkentry = &checkentry,
19511 +       .destroy = &destroy,
19512 +       .me = THIS_MODULE
19513 +};
19514 +
19515 +
19516 +static int __init
19517 +init(void)
19518 +{
19519 +       int errorcode;
19520 +
19521 +       rwlock_init(&list_lock);
19522 +       proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
19523 +
19524 +       if (proc_net_condition) {
19525 +               errorcode = ipt_register_match(&condition_match);
19526 +
19527 +               if (errorcode)
19528 +                       remove_proc_entry("ip6t_condition", proc_net);
19529 +       } else
19530 +               errorcode = -EACCES;
19531 +
19532 +       return errorcode;
19533 +}
19534 +
19535 +
19536 +static void __exit
19537 +fini(void)
19538 +{
19539 +       ipt_unregister_match(&condition_match);
19540 +       remove_proc_entry("ip6t_condition", proc_net);
19541 +}
19542 +
19543 +module_init(init);
19544 +module_exit(fini);
19545 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
19546 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_fuzzy.c      1970-01-01 01:00:00.000000000 +0100
19547 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_fuzzy.c  2003-12-11 10:23:21.621650984 +0100
19548 @@ -0,0 +1,189 @@
19549 +/*
19550 + * This module implements a simple TSK FLC
19551 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
19552 + * to limit , in an adaptive and flexible way , the packet rate crossing
19553 + * a given stream . It serves as an initial and very simple (but effective)
19554 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
19555 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
19556 + * into our code in a precise , adaptive and efficient manner.
19557 + *  The goal is very similar to that of "limit" match , but using techniques of
19558 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
19559 + * avoiding over and undershoots - and stuff like that .
19560 + *
19561 + *
19562 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
19563 + * 2002-08-17  : Changed to eliminate floating point operations .
19564 + * 2002-08-23  : Coding style changes .
19565 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
19566 + */
19567 +
19568 +#include <linux/module.h>
19569 +#include <linux/skbuff.h>
19570 +#include <linux/ipv6.h>
19571 +#include <linux/random.h>
19572 +#include <net/tcp.h>
19573 +#include <linux/spinlock.h>
19574 +#include <linux/netfilter_ipv6/ip6_tables.h>
19575 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
19576 +
19577 +/*
19578 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
19579 + Expressed in percentage
19580 +*/
19581 +
19582 +#define PAR_LOW                1/100
19583 +#define PAR_HIGH       1
19584 +
19585 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
19586 +
19587 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
19588 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
19589 +MODULE_LICENSE("GPL");
19590 +
19591 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19592 +{
19593 +       if (tx >= maxi) return 100;
19594 +
19595 +       if (tx <= mini) return 0;
19596 +
19597 +       return ((100 * (tx-mini)) / (maxi-mini));
19598 +}
19599 +
19600 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19601 +{
19602 +       if (tx <= mini) return 100;
19603 +
19604 +       if (tx >= maxi) return 0;
19605 +
19606 +       return ((100 * (maxi - tx)) / (maxi - mini));
19607 +
19608 +}
19609 +
19610 +static int
19611 +ip6t_fuzzy_match(const struct sk_buff *pskb,
19612 +              const struct net_device *in,
19613 +              const struct net_device *out,
19614 +              const void *matchinfo,
19615 +              int offset,
19616 +              const void *hdr,
19617 +              u_int16_t datalen,
19618 +              int *hotdrop)
19619 +{
19620 +       /* From userspace */
19621 +
19622 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
19623 +
19624 +       u_int8_t random_number;
19625 +       unsigned long amount;
19626 +       u_int8_t howhigh, howlow;
19627 +
19628 +
19629 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
19630 +
19631 +       info->bytes_total += pskb->len;
19632 +       info->packets_total++;
19633 +
19634 +       info->present_time = jiffies;
19635 +
19636 +       if (info->present_time >= info->previous_time)
19637 +               amount = info->present_time - info->previous_time;
19638 +       else {
19639 +               /* There was a transition : I choose to re-sample
19640 +                  and keep the old acceptance rate...
19641 +               */
19642 +
19643 +               amount = 0;
19644 +               info->previous_time = info->present_time;
19645 +               info->bytes_total = info->packets_total = 0;
19646 +            };
19647 +
19648 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
19649 +
19650 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
19651 +                                       / amount);
19652 +
19653 +               info->previous_time = info->present_time;
19654 +               info->bytes_total = info->packets_total = 0;
19655 +
19656 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
19657 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
19658 +
19659 +               info->acceptance_rate = (u_int8_t) \
19660 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
19661 +
19662 +       /* In fact, the above defuzzification would require a denominator
19663 +        * proportional to (howhigh+howlow) but, in this particular case,
19664 +        * that expression is constant.
19665 +        * An imediate consequence is that it is not necessary to call
19666 +        * both mf_high and mf_low - but to keep things understandable,
19667 +        * I did so.
19668 +        */
19669 +
19670 +       }
19671 +
19672 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
19673 +
19674 +
19675 +       if (info->acceptance_rate < 100)
19676 +       {
19677 +               get_random_bytes((void *)(&random_number), 1);
19678 +
19679 +               /*  If within the acceptance , it can pass => don't match */
19680 +               if (random_number <= (255 * info->acceptance_rate) / 100)
19681 +                       return 0;
19682 +               else
19683 +                       return 1; /* It can't pass (It matches) */
19684 +       };
19685 +
19686 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
19687 +
19688 +}
19689 +
19690 +static int
19691 +ip6t_fuzzy_checkentry(const char *tablename,
19692 +                  const struct ip6t_ip6 *ip,
19693 +                  void *matchinfo,
19694 +                  unsigned int matchsize,
19695 +                  unsigned int hook_mask)
19696 +{
19697 +
19698 +       const struct ip6t_fuzzy_info *info = matchinfo;
19699 +
19700 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
19701 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
19702 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
19703 +               return 0;
19704 +       }
19705 +
19706 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
19707 +        || (info->minimum_rate >= info->maximum_rate)) {
19708 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
19709 +               return 0;
19710 +       }
19711 +
19712 +       return 1;
19713 +}
19714 +
19715 +static struct ip6t_match ip6t_fuzzy_reg = {
19716 +       {NULL, NULL},
19717 +       "fuzzy",
19718 +       ip6t_fuzzy_match,
19719 +       ip6t_fuzzy_checkentry,
19720 +       NULL,
19721 +       THIS_MODULE };
19722 +
19723 +static int __init init(void)
19724 +{
19725 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
19726 +               return -EINVAL;
19727 +
19728 +       return 0;
19729 +}
19730 +
19731 +static void __exit fini(void)
19732 +{
19733 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
19734 +}
19735 +
19736 +module_init(init);
19737 +module_exit(fini);
19738 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
19739 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
19740 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_HL.c     2003-12-11 10:23:23.851312024 +0100
19741 @@ -0,0 +1,105 @@
19742 +/* 
19743 + * Hop Limit modification target for ip6tables
19744 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
19745 + * Based on HW's TTL module
19746 + *
19747 + * This software is distributed under the terms of GNU GPL
19748 + */
19749 +
19750 +#include <linux/module.h>
19751 +#include <linux/skbuff.h>
19752 +#include <linux/ip.h>
19753 +
19754 +#include <linux/netfilter_ipv6/ip6_tables.h>
19755 +#include <linux/netfilter_ipv6/ip6t_HL.h>
19756 +
19757 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
19758 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
19759 +MODULE_LICENSE("GPL");
19760 +
19761 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
19762 +               const struct net_device *in, const struct net_device *out,
19763 +               const void *targinfo, void *userinfo)
19764 +{
19765 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
19766 +       const struct ip6t_HL_info *info = targinfo;
19767 +       u_int16_t diffs[2];
19768 +       int new_hl;
19769 +                        
19770 +       switch (info->mode) {
19771 +               case IP6T_HL_SET:
19772 +                       new_hl = info->hop_limit;
19773 +                       break;
19774 +               case IP6T_HL_INC:
19775 +                       new_hl = ip6h->hop_limit + info->hop_limit;
19776 +                       if (new_hl > 255)
19777 +                               new_hl = 255;
19778 +                       break;
19779 +               case IP6T_HL_DEC:
19780 +                       new_hl = ip6h->hop_limit + info->hop_limit;
19781 +                       if (new_hl < 0)
19782 +                               new_hl = 0;
19783 +                       break;
19784 +               default:
19785 +                       new_hl = ip6h->hop_limit;
19786 +                       break;
19787 +       }
19788 +
19789 +       if (new_hl != ip6h->hop_limit) {
19790 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
19791 +               ip6h->hop_limit = new_hl;
19792 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
19793 +       }
19794 +
19795 +       return IP6T_CONTINUE;
19796 +}
19797 +
19798 +static int ip6t_hl_checkentry(const char *tablename,
19799 +               const struct ip6t_entry *e,
19800 +               void *targinfo,
19801 +               unsigned int targinfosize,
19802 +               unsigned int hook_mask)
19803 +{
19804 +       struct ip6t_HL_info *info = targinfo;
19805 +
19806 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
19807 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
19808 +                               targinfosize,
19809 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
19810 +               return 0;       
19811 +       }       
19812 +
19813 +       if (strcmp(tablename, "mangle")) {
19814 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
19815 +               return 0;
19816 +       }
19817 +
19818 +       if (info->mode > IP6T_HL_MAXMODE) {
19819 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
19820 +                       info->mode);
19821 +               return 0;
19822 +       }
19823 +
19824 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
19825 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
19826 +               return 0;
19827 +       }
19828 +       
19829 +       return 1;
19830 +}
19831 +
19832 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
19833 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
19834 +
19835 +static int __init init(void)
19836 +{
19837 +       return ip6t_register_target(&ip6t_HL);
19838 +}
19839 +
19840 +static void __exit fini(void)
19841 +{
19842 +       ip6t_unregister_target(&ip6t_HL);
19843 +}
19844 +
19845 +module_init(init);
19846 +module_exit(fini);
19847 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
19848 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_LOG.c        2003-11-26 21:43:30.000000000 +0100
19849 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_LOG.c    2003-12-11 10:23:14.924669080 +0100
19850 @@ -3,18 +3,24 @@
19851   */
19852  #include <linux/module.h>
19853  #include <linux/skbuff.h>
19854 +#include <linux/socket.h>
19855  #include <linux/ip.h>
19856  #include <linux/spinlock.h>
19857  #include <linux/icmpv6.h>
19858  #include <net/udp.h>
19859  #include <net/tcp.h>
19860  #include <net/ipv6.h>
19861 +#include <linux/netfilter.h>
19862  #include <linux/netfilter_ipv6/ip6_tables.h>
19863  
19864  MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
19865  MODULE_DESCRIPTION("IP6 tables LOG target module");
19866  MODULE_LICENSE("GPL");
19867  
19868 +static unsigned int nflog = 1;
19869 +MODULE_PARM(nflog, "i");
19870 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
19871 +
19872  struct in_device;
19873  #include <net/route.h>
19874  #include <linux/netfilter_ipv6/ip6t_LOG.h>
19875 @@ -256,40 +262,38 @@
19876         }
19877  }
19878  
19879 -static unsigned int
19880 -ip6t_log_target(struct sk_buff **pskb,
19881 -               unsigned int hooknum,
19882 -               const struct net_device *in,
19883 -               const struct net_device *out,
19884 -               const void *targinfo,
19885 -               void *userinfo)
19886 +static void
19887 +ip6t_log_packet(unsigned int hooknum,
19888 +               const struct sk_buff *skb,
19889 +               const struct net_device *in,
19890 +               const struct net_device *out,
19891 +               const struct ip6t_log_info *loginfo,
19892 +               const char *level_string,
19893 +               const char *prefix)
19894  {
19895 -       struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
19896 -       const struct ip6t_log_info *loginfo = targinfo;
19897 -       char level_string[4] = "< >";
19898 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
19899  
19900 -       level_string[1] = '0' + (loginfo->level % 8);
19901         spin_lock_bh(&log_lock);
19902         printk(level_string);
19903         printk("%sIN=%s OUT=%s ",
19904 -               loginfo->prefix,
19905 +               prefix == NULL ? loginfo->prefix : prefix,
19906                 in ? in->name : "",
19907                 out ? out->name : "");
19908         if (in && !out) {
19909                 /* MAC logging for input chain only. */
19910                 printk("MAC=");
19911 -               if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) {
19912 -                       if ((*pskb)->dev->type != ARPHRD_SIT){
19913 +               if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
19914 +                       if (skb->dev->type != ARPHRD_SIT){
19915                           int i;
19916 -                         unsigned char *p = (*pskb)->mac.raw;
19917 -                         for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++)
19918 +                         unsigned char *p = skb->mac.raw;
19919 +                         for (i = 0; i < skb->dev->hard_header_len; i++,p++)
19920                                 printk("%02x%c", *p,
19921 -                                       i==(*pskb)->dev->hard_header_len - 1
19922 +                                       i==skb->dev->hard_header_len - 1
19923                                         ? ' ':':');
19924                         } else {
19925                           int i;
19926 -                         unsigned char *p = (*pskb)->mac.raw;
19927 -                         if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){
19928 +                         unsigned char *p = skb->mac.raw;
19929 +                         if ( p - (ETH_ALEN*2+2) > skb->head ){
19930                             p -= (ETH_ALEN+2);
19931                             for (i = 0; i < (ETH_ALEN); i++,p++)
19932                                 printk("%02x%s", *p,
19933 @@ -300,10 +304,10 @@
19934                                         i == ETH_ALEN-1 ? ' ' : ':');
19935                           }
19936                           
19937 -                         if (((*pskb)->dev->addr_len == 4) &&
19938 -                             (*pskb)->dev->hard_header_len > 20){
19939 +                         if ((skb->dev->addr_len == 4) &&
19940 +                             skb->dev->hard_header_len > 20){
19941                             printk("TUNNEL=");
19942 -                           p = (*pskb)->mac.raw + 12;
19943 +                           p = skb->mac.raw + 12;
19944                             for (i = 0; i < 4; i++,p++)
19945                                 printk("%3d%s", *p,
19946                                         i == 3 ? "->" : ".");
19947 @@ -319,10 +323,41 @@
19948         dump_packet(loginfo, ipv6h, 1);
19949         printk("\n");
19950         spin_unlock_bh(&log_lock);
19951 +}
19952 +
19953 +static unsigned int
19954 +ip6t_log_target(struct sk_buff **pskb,
19955 +               unsigned int hooknum,
19956 +               const struct net_device *in,
19957 +               const struct net_device *out,
19958 +               const void *targinfo,
19959 +               void *userinfo)
19960 +{
19961 +       const struct ip6t_log_info *loginfo = targinfo;
19962 +       char level_string[4] = "< >";
19963 +
19964 +       level_string[1] = '0' + (loginfo->level % 8);
19965 +       ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
19966  
19967         return IP6T_CONTINUE;
19968  }
19969  
19970 +static void
19971 +ip6t_logfn(unsigned int hooknum,
19972 +          const struct sk_buff *skb,
19973 +          const struct net_device *in,
19974 +          const struct net_device *out,
19975 +          const char *prefix)
19976 +{
19977 +       struct ip6t_log_info loginfo = { 
19978 +               .level = 0, 
19979 +               .logflags = IP6T_LOG_MASK, 
19980 +               .prefix = "" 
19981 +       };
19982 +
19983 +       ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
19984 +}
19985 +
19986  static int ip6t_log_checkentry(const char *tablename,
19987                                const struct ip6t_entry *e,
19988                                void *targinfo,
19989 @@ -359,12 +394,17 @@
19990  {
19991         if (ip6t_register_target(&ip6t_log_reg))
19992                 return -EINVAL;
19993 +       if (nflog)
19994 +               nf_log_register(PF_INET6, &ip6t_logfn);
19995  
19996         return 0;
19997  }
19998  
19999  static void __exit fini(void)
20000  {
20001 +       if (nflog)
20002 +               nf_log_register(PF_INET6, &ip6t_logfn);
20003 +
20004         ip6t_unregister_target(&ip6t_log_reg);
20005  }
20006  
20007 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
20008 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_nth.c        1970-01-01 01:00:00.000000000 +0100
20009 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_nth.c    2003-12-11 10:23:29.533448208 +0100
20010 @@ -0,0 +1,173 @@
20011 +/*
20012 +  This is a module which is used for match support for every Nth packet
20013 +  This file is distributed under the terms of the GNU General Public
20014 +  License (GPL). Copies of the GPL can be obtained from:
20015 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
20016 +
20017 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20018 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
20019 +        * added support for multiple counters
20020 +        * added support for matching on individual packets
20021 +          in the counter cycle
20022 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20023 +
20024 +*/
20025 +
20026 +#include <linux/module.h>
20027 +#include <linux/skbuff.h>
20028 +#include <linux/ip.h>
20029 +#include <net/tcp.h>
20030 +#include <linux/spinlock.h>
20031 +#include <linux/netfilter_ipv6/ip6_tables.h>
20032 +#include <linux/netfilter_ipv6/ip6t_nth.h>
20033 +
20034 +MODULE_LICENSE("GPL");
20035 +
20036 +/*
20037 + * State information.
20038 + */
20039 +struct state {
20040 +       spinlock_t lock;
20041 +       u_int16_t number;
20042 +};
20043 +
20044 +static struct state states[IP6T_NTH_NUM_COUNTERS];
20045 +
20046 +static int
20047 +ip6t_nth_match(const struct sk_buff *pskb,
20048 +             const struct net_device *in,
20049 +             const struct net_device *out,
20050 +             const void *matchinfo,
20051 +             int offset,
20052 +             const void *hdr,
20053 +             u_int16_t datalen,
20054 +             int *hotdrop)
20055 +{
20056 +       /* Parameters from userspace */
20057 +       const struct ip6t_nth_info *info = matchinfo;
20058 +        unsigned counter = info->counter;
20059 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
20060 +       {
20061 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20062 +               return 0;
20063 +        };
20064 +
20065 +        spin_lock(&states[counter].lock);
20066 +
20067 +        /* Are we matching every nth packet?*/
20068 +        if (info->packet == 0xFF)
20069 +        {
20070 +               /* We're matching every nth packet and only every nth packet*/
20071 +               /* Do we match or invert match? */
20072 +               if (info->not == 0)
20073 +               {
20074 +                       if (states[counter].number == 0)
20075 +                       {
20076 +                               ++states[counter].number;
20077 +                               goto match;
20078 +                       }
20079 +                       if (states[counter].number >= info->every)
20080 +                               states[counter].number = 0; /* reset the counter */
20081 +                       else
20082 +                               ++states[counter].number;
20083 +                       goto dontmatch;
20084 +               }
20085 +               else
20086 +               {
20087 +                       if (states[counter].number == 0)
20088 +                       {
20089 +                               ++states[counter].number;
20090 +                               goto dontmatch;
20091 +                       }
20092 +                       if (states[counter].number >= info->every)
20093 +                               states[counter].number = 0;
20094 +                       else
20095 +                               ++states[counter].number;
20096 +                       goto match;
20097 +               }
20098 +        }
20099 +        else
20100 +        {
20101 +               /* We're using the --packet, so there must be a rule for every value */
20102 +               if (states[counter].number == info->packet)
20103 +               {
20104 +                       /* only increment the counter when a match happens */
20105 +                       if (states[counter].number >= info->every)
20106 +                               states[counter].number = 0; /* reset the counter */
20107 +                       else
20108 +                               ++states[counter].number;
20109 +                       goto match;
20110 +               }
20111 +               else
20112 +                       goto dontmatch;
20113 +       }
20114 +
20115 + dontmatch:
20116 +       /* don't match */
20117 +       spin_unlock(&states[counter].lock);
20118 +       return 0;
20119 +
20120 + match:
20121 +       spin_unlock(&states[counter].lock);
20122 +       return 1;
20123 +}
20124 +
20125 +static int
20126 +ip6t_nth_checkentry(const char *tablename,
20127 +                  const struct ip6t_ip6 *e,
20128 +                  void *matchinfo,
20129 +                  unsigned int matchsize,
20130 +                  unsigned int hook_mask)
20131 +{
20132 +       /* Parameters from userspace */
20133 +       const struct ip6t_nth_info *info = matchinfo;
20134 +        unsigned counter = info->counter;
20135 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
20136 +       {
20137 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
20138 +                       return 0;
20139 +               };
20140 +
20141 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
20142 +               printk("nth: matchsize %u != %u\n", matchsize,
20143 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
20144 +               return 0;
20145 +       }
20146 +
20147 +       states[counter].number = info->startat;
20148 +
20149 +       return 1;
20150 +}
20151 +
20152 +static struct ip6t_match ip6t_nth_reg = { 
20153 +       {NULL, NULL},
20154 +       "nth",
20155 +       ip6t_nth_match,
20156 +       ip6t_nth_checkentry,
20157 +       NULL,
20158 +       THIS_MODULE };
20159 +
20160 +static int __init init(void)
20161 +{
20162 +       unsigned counter;
20163 +        memset(&states, 0, sizeof(states));
20164 +       if (ip6t_register_match(&ip6t_nth_reg))
20165 +               return -EINVAL;
20166 +
20167 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
20168 +       {
20169 +               spin_lock_init(&(states[counter].lock));
20170 +        };
20171 +
20172 +       printk("ip6t_nth match loaded\n");
20173 +       return 0;
20174 +}
20175 +
20176 +static void __exit fini(void)
20177 +{
20178 +       ip6t_unregister_match(&ip6t_nth_reg);
20179 +       printk("ip6t_nth match unloaded\n");
20180 +}
20181 +
20182 +module_init(init);
20183 +module_exit(fini);
20184 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
20185 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_owner.c      2003-11-26 21:45:19.000000000 +0100
20186 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_owner.c  1970-01-01 01:00:00.000000000 +0100
20187 @@ -1,163 +0,0 @@
20188 -/* Kernel module to match various things tied to sockets associated with
20189 -   locally generated outgoing packets.
20190 -
20191 -   Copyright (C) 2000,2001 Marc Boucher
20192 - */
20193 -#include <linux/module.h>
20194 -#include <linux/skbuff.h>
20195 -#include <linux/file.h>
20196 -#include <net/sock.h>
20197 -
20198 -#include <linux/netfilter_ipv6/ip6t_owner.h>
20199 -#include <linux/netfilter_ipv6/ip6_tables.h>
20200 -
20201 -MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20202 -MODULE_DESCRIPTION("IP6 tables owner matching module");
20203 -MODULE_LICENSE("GPL");
20204 -
20205 -static int
20206 -match_pid(const struct sk_buff *skb, pid_t pid)
20207 -{
20208 -       struct task_struct *p;
20209 -       struct files_struct *files;
20210 -       int i;
20211 -
20212 -       read_lock(&tasklist_lock);
20213 -       p = find_task_by_pid(pid);
20214 -       if (!p)
20215 -               goto out;
20216 -       task_lock(p);
20217 -       files = p->files;
20218 -       if(files) {
20219 -               spin_lock(&files->file_lock);
20220 -               for (i=0; i < files->max_fds; i++) {
20221 -                       if (fcheck_files(files, i) == skb->sk->sk_socket->file) {
20222 -                               spin_unlock(&files->file_lock);
20223 -                               task_unlock(p);
20224 -                               read_unlock(&tasklist_lock);
20225 -                               return 1;
20226 -                       }
20227 -               }
20228 -               spin_unlock(&files->file_lock);
20229 -       }
20230 -       task_unlock(p);
20231 -out:
20232 -       read_unlock(&tasklist_lock);
20233 -       return 0;
20234 -}
20235 -
20236 -static int
20237 -match_sid(const struct sk_buff *skb, pid_t sid)
20238 -{
20239 -       struct task_struct *g, *p;
20240 -       struct file *file = skb->sk->sk_socket->file;
20241 -       int i, found=0;
20242 -
20243 -       read_lock(&tasklist_lock);
20244 -       do_each_thread(g, p) {
20245 -               struct files_struct *files;
20246 -               if (p->session != sid)
20247 -                       continue;
20248 -
20249 -               task_lock(p);
20250 -               files = p->files;
20251 -               if (files) {
20252 -                       spin_lock(&files->file_lock);
20253 -                       for (i=0; i < files->max_fds; i++) {
20254 -                               if (fcheck_files(files, i) == file) {
20255 -                                       found = 1;
20256 -                                       break;
20257 -                               }
20258 -                       }
20259 -                       spin_unlock(&files->file_lock);
20260 -               }
20261 -               task_unlock(p);
20262 -               if (found)
20263 -                       goto out;
20264 -       } while_each_thread(g, p);
20265 -out:
20266 -       read_unlock(&tasklist_lock);
20267 -
20268 -       return found;
20269 -}
20270 -
20271 -static int
20272 -match(const struct sk_buff *skb,
20273 -      const struct net_device *in,
20274 -      const struct net_device *out,
20275 -      const void *matchinfo,
20276 -      int offset,
20277 -      const void *hdr,
20278 -      u_int16_t datalen,
20279 -      int *hotdrop)
20280 -{
20281 -       const struct ip6t_owner_info *info = matchinfo;
20282 -
20283 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
20284 -               return 0;
20285 -
20286 -       if(info->match & IP6T_OWNER_UID) {
20287 -               if((skb->sk->sk_socket->file->f_uid != info->uid) ^
20288 -                   !!(info->invert & IP6T_OWNER_UID))
20289 -                       return 0;
20290 -       }
20291 -
20292 -       if(info->match & IP6T_OWNER_GID) {
20293 -               if((skb->sk->sk_socket->file->f_gid != info->gid) ^
20294 -                   !!(info->invert & IP6T_OWNER_GID))
20295 -                       return 0;
20296 -       }
20297 -
20298 -       if(info->match & IP6T_OWNER_PID) {
20299 -               if (!match_pid(skb, info->pid) ^
20300 -                   !!(info->invert & IP6T_OWNER_PID))
20301 -                       return 0;
20302 -       }
20303 -
20304 -       if(info->match & IP6T_OWNER_SID) {
20305 -               if (!match_sid(skb, info->sid) ^
20306 -                   !!(info->invert & IP6T_OWNER_SID))
20307 -                       return 0;
20308 -       }
20309 -
20310 -       return 1;
20311 -}
20312 -
20313 -static int
20314 -checkentry(const char *tablename,
20315 -           const struct ip6t_ip6 *ip,
20316 -           void *matchinfo,
20317 -           unsigned int matchsize,
20318 -           unsigned int hook_mask)
20319 -{
20320 -        if (hook_mask
20321 -            & ~((1 << NF_IP6_LOCAL_OUT) | (1 << NF_IP6_POST_ROUTING))) {
20322 -                printk("ip6t_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
20323 -                return 0;
20324 -        }
20325 -
20326 -       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_owner_info)))
20327 -               return 0;
20328 -
20329 -       return 1;
20330 -}
20331 -
20332 -static struct ip6t_match owner_match = {
20333 -       .name           = "owner",
20334 -       .match          = &match,
20335 -       .checkentry     = &checkentry,
20336 -       .me             = THIS_MODULE,
20337 -};
20338 -
20339 -static int __init init(void)
20340 -{
20341 -       return ip6t_register_match(&owner_match);
20342 -}
20343 -
20344 -static void __exit fini(void)
20345 -{
20346 -       ip6t_unregister_match(&owner_match);
20347 -}
20348 -
20349 -module_init(init);
20350 -module_exit(fini);
20351 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
20352 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_random.c     1970-01-01 01:00:00.000000000 +0100
20353 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_random.c 2003-12-11 10:23:36.320416432 +0100
20354 @@ -0,0 +1,97 @@
20355 +/*
20356 +  This is a module which is used for a "random" match support.
20357 +  This file is distributed under the terms of the GNU General Public
20358 +  License (GPL). Copies of the GPL can be obtained from:
20359 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
20360 +
20361 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20362 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
20363 +*/
20364 +
20365 +#include <linux/module.h>
20366 +#include <linux/skbuff.h>
20367 +#include <linux/ip.h>
20368 +#include <linux/random.h>
20369 +#include <net/tcp.h>
20370 +#include <linux/spinlock.h>
20371 +#include <linux/netfilter_ipv6/ip6_tables.h>
20372 +#include <linux/netfilter_ipv6/ip6t_random.h>
20373 +
20374 +MODULE_LICENSE("GPL");
20375 +
20376 +static int
20377 +ip6t_rand_match(const struct sk_buff *pskb,
20378 +              const struct net_device *in,
20379 +              const struct net_device *out,
20380 +              const void *matchinfo,
20381 +              int offset,
20382 +              const void *hdr,
20383 +              u_int16_t datalen,
20384 +              int *hotdrop)
20385 +{
20386 +       /* Parameters from userspace */
20387 +       const struct ip6t_rand_info *info = matchinfo;
20388 +       u_int8_t random_number;
20389 +
20390 +       /* get 1 random number from the kernel random number generation routine */
20391 +       get_random_bytes((void *)(&random_number), 1);
20392 +
20393 +       /* Do we match ? */
20394 +       if (random_number <= info->average)
20395 +               return 1;
20396 +       else
20397 +               return 0;
20398 +}
20399 +
20400 +static int
20401 +ip6t_rand_checkentry(const char *tablename,
20402 +                  const struct ip6t_ip6 *e,
20403 +                  void *matchinfo,
20404 +                  unsigned int matchsize,
20405 +                  unsigned int hook_mask)
20406 +{
20407 +       /* Parameters from userspace */
20408 +       const struct ip6t_rand_info *info = matchinfo;
20409 +
20410 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
20411 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
20412 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
20413 +               return 0;
20414 +       }
20415 +
20416 +       /* must be  1 <= average % <= 99 */
20417 +       /* 1  x 2.55 = 2   */
20418 +       /* 99 x 2.55 = 252 */
20419 +       if ((info->average < 2) || (info->average > 252)) {
20420 +               printk("ip6t_random:  invalid average %u\n", info->average);
20421 +               return 0;
20422 +       }
20423 +
20424 +       return 1;
20425 +}
20426 +
20427 +static struct ip6t_match ip6t_rand_reg = { 
20428 +       {NULL, NULL},
20429 +       "random",
20430 +       ip6t_rand_match,
20431 +       ip6t_rand_checkentry,
20432 +       NULL,
20433 +       THIS_MODULE };
20434 +
20435 +static int __init init(void)
20436 +{
20437 +       if (ip6t_register_match(&ip6t_rand_reg))
20438 +               return -EINVAL;
20439 +
20440 +       printk("ip6t_random match loaded\n");
20441 +       return 0;
20442 +}
20443 +
20444 +static void __exit fini(void)
20445 +{
20446 +       ip6t_unregister_match(&ip6t_rand_reg);
20447 +       printk("ip6t_random match unloaded\n");
20448 +}
20449 +
20450 +module_init(init);
20451 +module_exit(fini);
20452 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
20453 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_REJECT.c     1970-01-01 01:00:00.000000000 +0100
20454 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_REJECT.c 2003-12-11 10:23:39.703902064 +0100
20455 @@ -0,0 +1,274 @@
20456 +/*
20457 + * This is a module which is used for rejecting packets.
20458 + *     Added support for customized reject packets (Jozsef Kadlecsik).
20459 + * Sun 12 Nov 2000
20460 + *     Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
20461 + */
20462 +#include <linux/config.h>
20463 +#include <linux/module.h>
20464 +#include <linux/skbuff.h>
20465 +#include <linux/icmpv6.h>
20466 +#include <net/tcp.h>
20467 +#include <linux/netfilter_ipv6/ip6_tables.h>
20468 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
20469 +
20470 +#if 1
20471 +#define DEBUGP printk
20472 +#else
20473 +#define DEBUGP(format, args...)
20474 +#endif
20475 +
20476 +#if 0
20477 +/* Send RST reply */
20478 +static void send_reset(struct sk_buff *oldskb)
20479 +{
20480 +       struct sk_buff *nskb;
20481 +       struct tcphdr *otcph, *tcph;
20482 +       struct rtable *rt;
20483 +       unsigned int otcplen;
20484 +       int needs_ack;
20485 +
20486 +       /* IP header checks: fragment, too short. */
20487 +       if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
20488 +           || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
20489 +               return;
20490 +
20491 +       otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
20492 +       otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
20493 +
20494 +       /* No RST for RST. */
20495 +       if (otcph->rst)
20496 +               return;
20497 +
20498 +       /* Check checksum. */
20499 +       if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
20500 +                        oldskb->nh.iph->daddr,
20501 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
20502 +               return;
20503 +
20504 +       /* Copy skb (even if skb is about to be dropped, we can't just
20505 +           clone it because there may be other things, such as tcpdump,
20506 +           interested in it) */
20507 +       nskb = skb_copy(oldskb, GFP_ATOMIC);
20508 +       if (!nskb)
20509 +               return;
20510 +
20511 +       /* This packet will not be the same as the other: clear nf fields */
20512 +       nf_conntrack_put(nskb->nfct);
20513 +       nskb->nfct = NULL;
20514 +       nskb->nfcache = 0;
20515 +#ifdef CONFIG_NETFILTER_DEBUG
20516 +       nskb->nf_debug = 0;
20517 +#endif
20518 +
20519 +       tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
20520 +
20521 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
20522 +       tcph->source = xchg(&tcph->dest, tcph->source);
20523 +
20524 +       /* Truncate to length (no data) */
20525 +       tcph->doff = sizeof(struct tcphdr)/4;
20526 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
20527 +       nskb->nh.iph->tot_len = htons(nskb->len);
20528 +
20529 +       if (tcph->ack) {
20530 +               needs_ack = 0;
20531 +               tcph->seq = otcph->ack_seq;
20532 +               tcph->ack_seq = 0;
20533 +       } else {
20534 +               needs_ack = 1;
20535 +               tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
20536 +                                     + otcplen - (otcph->doff<<2));
20537 +               tcph->seq = 0;
20538 +       }
20539 +
20540 +       /* Reset flags */
20541 +       ((u_int8_t *)tcph)[13] = 0;
20542 +       tcph->rst = 1;
20543 +       tcph->ack = needs_ack;
20544 +
20545 +       tcph->window = 0;
20546 +       tcph->urg_ptr = 0;
20547 +
20548 +       /* Adjust TCP checksum */
20549 +       tcph->check = 0;
20550 +       tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
20551 +                                  nskb->nh.iph->saddr,
20552 +                                  nskb->nh.iph->daddr,
20553 +                                  csum_partial((char *)tcph,
20554 +                                               sizeof(struct tcphdr), 0));
20555 +
20556 +       /* Adjust IP TTL, DF */
20557 +       nskb->nh.iph->ttl = MAXTTL;
20558 +       /* Set DF, id = 0 */
20559 +       nskb->nh.iph->frag_off = htons(IP_DF);
20560 +       nskb->nh.iph->id = 0;
20561 +
20562 +       /* Adjust IP checksum */
20563 +       nskb->nh.iph->check = 0;
20564 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
20565 +                                          nskb->nh.iph->ihl);
20566 +
20567 +       /* Routing */
20568 +       if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
20569 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
20570 +                           0) != 0)
20571 +               goto free_nskb;
20572 +
20573 +       dst_release(nskb->dst);
20574 +       nskb->dst = &rt->u.dst;
20575 +
20576 +       /* "Never happens" */
20577 +       if (nskb->len > nskb->dst->pmtu)
20578 +               goto free_nskb;
20579 +
20580 +       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
20581 +               ip_finish_output);
20582 +       return;
20583 +
20584 + free_nskb:
20585 +       kfree_skb(nskb);
20586 +}
20587 +#endif
20588 +
20589 +static unsigned int reject6_target(struct sk_buff **pskb,
20590 +                          unsigned int hooknum,
20591 +                          const struct net_device *in,
20592 +                          const struct net_device *out,
20593 +                          const void *targinfo,
20594 +                          void *userinfo)
20595 +{
20596 +       const struct ip6t_reject_info *reject = targinfo;
20597 +
20598 +       /* WARNING: This code causes reentry within ip6tables.
20599 +          This means that the ip6tables jump stack is now crap.  We
20600 +          must return an absolute verdict. --RR */
20601 +       DEBUGP("REJECTv6: calling icmpv6_send\n");
20602 +       switch (reject->with) {
20603 +       case IP6T_ICMP6_NO_ROUTE:
20604 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
20605 +               break;
20606 +       case IP6T_ICMP6_ADM_PROHIBITED:
20607 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
20608 +               break;
20609 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
20610 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
20611 +               break;
20612 +       case IP6T_ICMP6_ADDR_UNREACH:
20613 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
20614 +               break;
20615 +       case IP6T_ICMP6_PORT_UNREACH:
20616 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
20617 +               break;
20618 +#if 0
20619 +       case IPT_ICMP_ECHOREPLY: {
20620 +               struct icmp6hdr *icmph  = (struct icmphdr *)
20621 +                       ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
20622 +               unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
20623 +
20624 +               /* Not non-head frags, or truncated */
20625 +               if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
20626 +                   && datalen >= 4) {
20627 +                       /* Usually I don't like cut & pasting code,
20628 +                           but dammit, my party is starting in 45
20629 +                           mins! --RR */
20630 +                       struct icmp_bxm icmp_param;
20631 +
20632 +                       icmp_param.icmph=*icmph;
20633 +                       icmp_param.icmph.type=ICMP_ECHOREPLY;
20634 +                       icmp_param.data_ptr=(icmph+1);
20635 +                       icmp_param.data_len=datalen;
20636 +                       icmp_reply(&icmp_param, *pskb);
20637 +               }
20638 +       }
20639 +       break;
20640 +       case IPT_TCP_RESET:
20641 +               send_reset(*pskb);
20642 +               break;
20643 +#endif
20644 +       default:
20645 +               printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
20646 +               break;
20647 +       }
20648 +
20649 +       return NF_DROP;
20650 +}
20651 +
20652 +static inline int find_ping_match(const struct ip6t_entry_match *m)
20653 +{
20654 +       const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
20655 +
20656 +       if (strcmp(m->u.kernel.match->name, "icmp6") == 0
20657 +           && icmpinfo->type == ICMPV6_ECHO_REQUEST
20658 +           && !(icmpinfo->invflags & IP6T_ICMP_INV))
20659 +               return 1;
20660 +
20661 +       return 0;
20662 +}
20663 +
20664 +static int check(const char *tablename,
20665 +                const struct ip6t_entry *e,
20666 +                void *targinfo,
20667 +                unsigned int targinfosize,
20668 +                unsigned int hook_mask)
20669 +{
20670 +       const struct ip6t_reject_info *rejinfo = targinfo;
20671 +
20672 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
20673 +               DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
20674 +               return 0;
20675 +       }
20676 +
20677 +       /* Only allow these for packet filtering. */
20678 +       if (strcmp(tablename, "filter") != 0) {
20679 +               DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
20680 +               return 0;
20681 +       }
20682 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
20683 +                          | (1 << NF_IP6_FORWARD)
20684 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
20685 +               DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
20686 +               return 0;
20687 +       }
20688 +
20689 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
20690 +               /* Must specify that it's an ICMP ping packet. */
20691 +               if (e->ipv6.proto != IPPROTO_ICMPV6
20692 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20693 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
20694 +                       return 0;
20695 +               }
20696 +               /* Must contain ICMP match. */
20697 +               if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
20698 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
20699 +                       return 0;
20700 +               }
20701 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
20702 +               /* Must specify that it's a TCP packet */
20703 +               if (e->ipv6.proto != IPPROTO_TCP
20704 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
20705 +                       DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
20706 +                       return 0;
20707 +               }
20708 +       }
20709 +
20710 +       return 1;
20711 +}
20712 +
20713 +static struct ip6t_target ip6t_reject_reg
20714 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
20715 +
20716 +static int __init init(void)
20717 +{
20718 +       if (ip6t_register_target(&ip6t_reject_reg))
20719 +               return -EINVAL;
20720 +       return 0;
20721 +}
20722 +
20723 +static void __exit fini(void)
20724 +{
20725 +       ip6t_unregister_target(&ip6t_reject_reg);
20726 +}
20727 +
20728 +module_init(init);
20729 +module_exit(fini);
20730 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
20731 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_ROUTE.c      1970-01-01 01:00:00.000000000 +0100
20732 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_ROUTE.c  2003-12-11 10:24:03.166335232 +0100
20733 @@ -0,0 +1,289 @@
20734 +/*
20735 + * This implements the ROUTE v6 target, which enables you to setup unusual
20736 + * routes not supported by the standard kernel routing table.
20737 + *
20738 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
20739 + *
20740 + * v 1.0 2003/08/05
20741 + *
20742 + * This software is distributed under GNU GPL v2, 1991
20743 + */
20744 +
20745 +#include <linux/module.h>
20746 +#include <linux/skbuff.h>
20747 +#include <linux/ipv6.h>
20748 +#include <linux/netfilter_ipv6/ip6_tables.h>
20749 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
20750 +#include <linux/netdevice.h>
20751 +#include <net/ipv6.h>
20752 +#include <net/ndisc.h>
20753 +#include <net/ip6_route.h>
20754 +#include <linux/icmpv6.h>
20755 +
20756 +#if 1
20757 +#define DEBUGP printk
20758 +#else
20759 +#define DEBUGP(format, args...)
20760 +#endif
20761 +
20762 +#define NIP6(addr) \
20763 +       ntohs((addr).s6_addr16[0]), \
20764 +       ntohs((addr).s6_addr16[1]), \
20765 +       ntohs((addr).s6_addr16[2]), \
20766 +       ntohs((addr).s6_addr16[3]), \
20767 +       ntohs((addr).s6_addr16[4]), \
20768 +       ntohs((addr).s6_addr16[5]), \
20769 +       ntohs((addr).s6_addr16[6]), \
20770 +       ntohs((addr).s6_addr16[7])
20771 +
20772 +/* Route the packet according to the routing keys specified in
20773 + * route_info. Keys are :
20774 + *  - ifindex : 
20775 + *      0 if no oif preferred, 
20776 + *      otherwise set to the index of the desired oif
20777 + *  - route_info->gw :
20778 + *      0 if no gateway specified,
20779 + *      otherwise set to the next host to which the pkt must be routed
20780 + * If success, skb->dev is the output device to which the packet must 
20781 + * be sent and skb->dst is not NULL
20782 + *
20783 + * RETURN:  1 if the packet was succesfully routed to the 
20784 + *            destination desired
20785 + *          0 if the kernel routing table could not route the packet
20786 + *            according to the keys specified
20787 + */
20788 +static int 
20789 +route6(struct sk_buff *skb,
20790 +       unsigned int ifindex,
20791 +       const struct ip6t_route_target_info *route_info)
20792 +{
20793 +       struct rt6_info *rt = NULL;
20794 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
20795 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
20796 +
20797 +       DEBUGP("ip6t_ROUTE: called with: ");
20798 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
20799 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
20800 +       DEBUGP("OUT=%s\n", route_info->oif);
20801 +       
20802 +       if (ipv6_addr_any(gw))
20803 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
20804 +       else
20805 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
20806 +
20807 +       if (!rt)
20808 +               goto no_route;
20809 +
20810 +       DEBUGP("ip6t_ROUTE: routing gives: ");
20811 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
20812 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
20813 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
20814 +
20815 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
20816 +               goto wrong_route;
20817 +       
20818 +       if (!rt->rt6i_nexthop) {
20819 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
20820 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
20821 +       }
20822 +
20823 +       /* Drop old route. */
20824 +       dst_release(skb->dst);
20825 +       skb->dst = &rt->u.dst;
20826 +       skb->dev = rt->rt6i_dev;
20827 +       return 1;
20828 +
20829 + wrong_route:
20830 +       dst_release(&rt->u.dst);
20831 + no_route:
20832 +       if (!net_ratelimit())
20833 +               return 0;
20834 +
20835 +       printk("ip6t_ROUTE: no explicit route found ");
20836 +       if (ifindex)
20837 +               printk("via interface %s ", route_info->oif);
20838 +       if (!ipv6_addr_any(gw))
20839 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
20840 +       printk("\n");
20841 +       return 0;
20842 +}
20843 +
20844 +
20845 +/* Stolen from ip6_output_finish
20846 + * PRE : skb->dev is set to the device we are leaving by
20847 + *       skb->dst is not NULL
20848 + * POST: the packet is sent with the link layer header pushed
20849 + *       the packet is destroyed
20850 + */
20851 +static void ip_direct_send(struct sk_buff *skb)
20852 +{
20853 +       struct dst_entry *dst = skb->dst;
20854 +       struct hh_cache *hh = dst->hh;
20855 +
20856 +       if (hh) {
20857 +               read_lock_bh(&hh->hh_lock);
20858 +               memcpy(skb->data - 16, hh->hh_data, 16);
20859 +               read_unlock_bh(&hh->hh_lock);
20860 +               skb_push(skb, hh->hh_len);
20861 +               hh->hh_output(skb);
20862 +       } else if (dst->neighbour)
20863 +               dst->neighbour->output(skb);
20864 +       else {
20865 +               if (net_ratelimit())
20866 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
20867 +               kfree_skb(skb);
20868 +       }
20869 +}
20870 +
20871 +
20872 +static unsigned int 
20873 +route6_oif(const struct ip6t_route_target_info *route_info,
20874 +          struct sk_buff *skb) 
20875 +{
20876 +       unsigned int ifindex = 0;
20877 +       struct net_device *dev_out = NULL;
20878 +
20879 +       /* The user set the interface name to use.
20880 +        * Getting the current interface index.
20881 +        */
20882 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
20883 +               ifindex = dev_out->ifindex;
20884 +       } else {
20885 +               /* Unknown interface name : packet dropped */
20886 +               if (net_ratelimit()) 
20887 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
20888 +
20889 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
20890 +                       return IP6T_CONTINUE;
20891 +               else
20892 +                       return NF_DROP;
20893 +       }
20894 +
20895 +       /* Trying the standard way of routing packets */
20896 +       if (route6(skb, ifindex, route_info)) {
20897 +               dev_put(dev_out);
20898 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
20899 +                       return IP6T_CONTINUE;
20900 +               
20901 +               ip_direct_send(skb);
20902 +               return NF_STOLEN;
20903 +       } else 
20904 +               return NF_DROP;
20905 +}
20906 +
20907 +
20908 +static unsigned int 
20909 +route6_gw(const struct ip6t_route_target_info *route_info,
20910 +         struct sk_buff *skb) 
20911 +{
20912 +       if (route6(skb, 0, route_info)) {
20913 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
20914 +                       return IP6T_CONTINUE;
20915 +
20916 +               ip_direct_send(skb);
20917 +               return NF_STOLEN;
20918 +       } else
20919 +               return NF_DROP;
20920 +}
20921 +
20922 +
20923 +static unsigned int 
20924 +ip6t_route_target(struct sk_buff **pskb,
20925 +                 unsigned int hooknum,
20926 +                 const struct net_device *in,
20927 +                 const struct net_device *out,
20928 +                 const void *targinfo,
20929 +                 void *userinfo)
20930 +{
20931 +       const struct ip6t_route_target_info *route_info = targinfo;
20932 +       struct sk_buff *skb = *pskb;
20933 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
20934 +
20935 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
20936 +               goto do_it;
20937 +
20938 +       /* If we are at PREROUTING or INPUT hook
20939 +        * the TTL isn't decreased by the IP stack
20940 +        */
20941 +       if (hooknum == NF_IP6_PRE_ROUTING ||
20942 +           hooknum == NF_IP6_LOCAL_IN) {
20943 +
20944 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
20945 +
20946 +               if (ipv6h->hop_limit <= 1) {
20947 +                       /* Force OUTPUT device used as source address */
20948 +                       skb->dev = skb->dst->dev;
20949 +
20950 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
20951 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
20952 +
20953 +                       return NF_DROP;
20954 +               }
20955 +
20956 +               ipv6h->hop_limit--;
20957 +       }
20958 +
20959 +
20960 + do_it:
20961 +       if (route_info->oif[0]) 
20962 +               return route6_oif(route_info, *pskb);
20963 +       
20964 +       if (!ipv6_addr_any(gw))
20965 +               return route6_gw(route_info, *pskb);
20966 +
20967 +       if (net_ratelimit()) 
20968 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
20969 +
20970 +       return IP6T_CONTINUE;
20971 +}
20972 +
20973 +
20974 +static int 
20975 +ip6t_route_checkentry(const char *tablename,
20976 +                     const struct ip6t_entry *e,
20977 +                     void *targinfo,
20978 +                     unsigned int targinfosize,
20979 +                     unsigned int hook_mask)
20980 +{
20981 +       if (strcmp(tablename, "mangle") != 0) {
20982 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
20983 +               return 0;
20984 +       }
20985 +
20986 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
20987 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
20988 +                      targinfosize,
20989 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
20990 +               return 0;
20991 +       }
20992 +
20993 +       return 1;
20994 +}
20995 +
20996 +
20997 +static struct ip6t_target ip6t_route_reg = {
20998 +       .name       = "ROUTE",
20999 +       .target     = ip6t_route_target,
21000 +       .checkentry = ip6t_route_checkentry,
21001 +       .me         = THIS_MODULE
21002 +};
21003 +
21004 +
21005 +static int __init init(void)
21006 +{
21007 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
21008 +       if (ip6t_register_target(&ip6t_route_reg))
21009 +               return -EINVAL;
21010 +
21011 +       return 0;
21012 +}
21013 +
21014 +
21015 +static void __exit fini(void)
21016 +{
21017 +       ip6t_unregister_target(&ip6t_route_reg);
21018 +}
21019 +
21020 +module_init(init);
21021 +module_exit(fini);
21022 +MODULE_LICENSE("GPL");
21023 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
21024 --- linux-2.6.0-test11.org/net/ipv6/netfilter/ip6t_TRACE.c      1970-01-01 01:00:00.000000000 +0100
21025 +++ linux-2.6.0-test11/net/ipv6/netfilter/ip6t_TRACE.c  2003-12-11 10:23:17.233318112 +0100
21026 @@ -0,0 +1,69 @@
21027 +/* This is a module which is used for setting
21028 + * the NFC_TRACE flag in the nfcache field of an skb. 
21029 + */
21030 +#include <linux/module.h>
21031 +#include <linux/skbuff.h>
21032 +
21033 +#include <linux/netfilter_ipv6/ip6_tables.h>
21034 +
21035 +static unsigned int
21036 +target(struct sk_buff **pskb,
21037 +       unsigned int hooknum,
21038 +       const struct net_device *in,
21039 +       const struct net_device *out,
21040 +       const void *targinfo,
21041 +       void *userinfo)
21042 +{
21043 +       (*pskb)->nfcache |= NFC_TRACE;
21044 +       return IP6T_CONTINUE;
21045 +}
21046 +
21047 +static int 
21048 +checkentry(const char *tablename,
21049 +                  const struct ip6t_entry *e,
21050 +           void *targinfo,
21051 +           unsigned int targinfosize,
21052 +           unsigned int hook_mask)
21053 +{
21054 +       if (targinfosize != 0) {
21055 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
21056 +                      targinfosize);
21057 +               return 0;
21058 +       }
21059 +
21060 +       if (strcmp(tablename, "raw") != 0) {
21061 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
21062 +               return 0;
21063 +       }
21064 +
21065 +       return 1;
21066 +}
21067 +
21068 +static struct ip6t_target ip6t_trace_reg = {
21069 +       .name = "TRACE",
21070 +       .target = target,
21071 +       .checkentry = checkentry,
21072 +       .destroy = NULL,
21073 +       .me = THIS_MODULE,
21074 +};
21075 +
21076 +static int __init init(void)
21077 +{
21078 +       if (ip6t_register_target(&ip6t_trace_reg))
21079 +               return -EINVAL;
21080 +
21081 +       return 0;
21082 +}
21083 +
21084 +static void __exit fini(void)
21085 +{
21086 +       ip6t_unregister_target(&ip6t_trace_reg);
21087 +}
21088 +
21089 +module_init(init);
21090 +module_exit(fini);
21091 +
21092 +MODULE_LICENSE("GPL");
21093 +MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
21094 +MODULE_DESCRIPTION("IPv6 TRACE target");
21095
21096 \ Brak znaku nowej linii na koñcu pliku
21097 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig linux-2.6.0-test11/net/ipv6/netfilter/Kconfig
21098 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Kconfig   2003-11-26 21:45:28.000000000 +0100
21099 +++ linux-2.6.0-test11/net/ipv6/netfilter/Kconfig       2003-12-11 12:59:02.951552984 +0100
21100 @@ -5,6 +5,122 @@
21101  menu "IPv6: Netfilter Configuration"
21102         depends on INET && IPV6!=n && NETFILTER
21103  
21104 +config IP6_NF_TARGET_ROUTE
21105 +       bool ' ROUTE target support'
21106 +       help
21107 +         CONFIG_IP6_NF_TARGET_ROUTE
21108 +         This option adds a `ROUTE' target, which enables you to setup unusual
21109 +         routes. The ROUTE target is also able to change the incoming interface
21110 +         of a packet.
21111 +
21112 +         The target can be or not a final target. It has to be used inside the
21113 +         mangle table.
21114 +
21115 +         Not working as a module.
21116 +         
21117 +config IP6_NF_MATCH_CONDITION
21118 +       tristate  ' Condition variable match support'
21119 +       depends on IP6_NF_IPTABLES
21120 +       help
21121 +         Condition variable match support
21122 +         CONFIG_IP6_NF_MATCH_CONDITION
21123 +         This option allows you to match firewall rules against condition
21124 +         variables stored in the /proc/net/ipt_condition directory.
21125 +         
21126 +         If you want to compile it as a module, say M here and read
21127 +         Documentation/modules.txt.  If unsure, say `N'.
21128 +
21129 +
21130 +
21131 +config IP6_NF_TARGET_REJECT
21132 +       tristate  ' REJECT target support'
21133 +       depends on IP6_NF_FILTER
21134 +       help
21135 +         REJECT target support
21136 +         CONFIG_IP6_NF_TARGET_REJECT
21137 +         The REJECT target allows a filtering rule to specify that an ICMPv6
21138 +         error should be issued in response to an incoming packet, rather
21139 +         than silently being dropped.
21140 +         
21141 +         If you want to compile it as a module, say M here and read
21142 +         Documentation/modules.txt.  If unsure, say `N'.
21143 +
21144 +
21145 +
21146 +config IP6_NF_MATCH_RANDOM
21147 +       tristate  ' Random match support'
21148 +       depends on IP6_NF_IPTABLES
21149 +       help
21150 +         Random match support
21151 +         CONFIG_IP6_NF_MATCH_RANDOM
21152 +         This option adds a `random' match,
21153 +         which allow you to match packets randomly
21154 +         following a given probability.
21155 +         
21156 +         If you want to compile it as a module, say M here and read
21157 +         Documentation/modules.txt.  If unsure, say `N'.
21158 +         
21159 +
21160 +
21161 +
21162 +config IP6_NF_MATCH_NTH
21163 +       tristate  ' Nth match support'
21164 +       depends on IP6_NF_IPTABLES
21165 +       help
21166 +         Nth match support
21167 +         CONFIG_IP6_NF_MATCH_NTH
21168 +         This option adds a `Nth' match, which allow you to make
21169 +         rules that match every Nth packet.  By default there are
21170 +         16 different counters.
21171 +         
21172 +         [options]
21173 +         --every     Nth              Match every Nth packet
21174 +         [--counter]  num              Use counter 0-15 (default:0)
21175 +         [--start]    num              Initialize the counter at the number 'num'
21176 +         instead of 0. Must be between 0 and Nth-1
21177 +         [--packet]   num              Match on 'num' packet. Must be between 0
21178 +         and Nth-1.
21179 +         
21180 +         If --packet is used for a counter than
21181 +         there must be Nth number of --packet
21182 +         rules, covering all values between 0 and
21183 +         Nth-1 inclusively.
21184 +         
21185 +         If you want to compile it as a module, say M here and read
21186 +         Documentation/modules.txt.  If unsure, say `N'.
21187 +         
21188 +
21189 +
21190 +
21191 +config IP6_NF_TARGET_HL
21192 +       tristate  ' HL target support'
21193 +       depends on IP6_NF_FILTER
21194 +       help
21195 +         HL target support
21196 +         CONFIG_IP6_NF_TARGET_HL
21197 +         This option adds a `HL' target, which allows you to modify the value of
21198 +         IPv6 Hop Limit field.
21199 +         
21200 +         If you want to compile it as a module, say M here and read
21201 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
21202 +
21203 +
21204 +
21205 +config IP6_NF_MATCH_FUZZY
21206 +       tristate  ' Fuzzy match support'
21207 +       depends on IP6_NF_FILTER
21208 +       help
21209 +         Fuzzy Logic Controller match support
21210 +         CONFIG_IP6_NF_MATCH_FUZZY
21211 +         This option adds a `fuzzy' match, which allows you to match
21212 +         packets according to a fuzzy logic based law.
21213 +         
21214 +         If you want to compile it as a module, say M here and read
21215 +         Documentation/modules.txt.  If unsure, say `N'.
21216 +         
21217 +
21218 +
21219 +
21220  #tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
21221  #if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
21222  #  dep_tristate '  FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK
21223 @@ -102,15 +218,6 @@
21224  
21225           To compile it as a module, choose M here.  If unsure, say N.
21226  
21227 -config IP6_NF_MATCH_OWNER
21228 -       tristate "Owner match support"
21229 -       depends on IP6_NF_IPTABLES
21230 -       help
21231 -         Packet owner matching allows you to match locally-generated packets
21232 -         based on who created them: the user, group, process or session.
21233 -
21234 -         To compile it as a module, choose M here.  If unsure, say N.
21235 -
21236  #  dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
21237  config IP6_NF_MATCH_MARK
21238         tristate "netfilter MARK match support"
21239 @@ -217,6 +324,31 @@
21240  
21241           To compile it as a module, choose M here.  If unsure, say N.
21242  
21243 +config IP6_NF_RAW
21244 +       tristate "Raw table"
21245 +       depends on IP6_NF_IPTABLES
21246 +       help
21247 +         This option adds a `raw' table to iptables: see the man page for
21248 +         iptables(8).  This table is the very first in the netfilter
21249 +         framework and hooks in at the PREROUTING and OUTPUT chains.
21250 +         The TRACE target can be used in this table only.
21251 +
21252 +         To compile it as a module, choose M here.  If unsure, say N.
21253 +
21254 +config IP6_NF_TARGET_TRACE
21255 +       tristate "TRACE target support"
21256 +       depends on IP6_NF_RAW
21257 +       help
21258 +         The TRACE target allows packets to be traced as those matches
21259 +         any subsequent rule in any IPv6 netfilter table/rule. The matched 
21260 +         rule and the packet is logged with the prefix
21261 +         
21262 +         TRACE: tablename/chainname/rulenum
21263 +         
21264 +         if the ip6t_LOG target is loaded in.
21265 +
21266 +         To compile it as a module, choose M here.  If unsure, say N.
21267 +
21268  #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
21269  endmenu
21270  
21271 diff -Nur linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile linux-2.6.0-test11/net/ipv6/netfilter/Makefile
21272 --- linux-2.6.0-test11.org/net/ipv6/netfilter/Makefile  2003-11-26 21:44:26.000000000 +0100
21273 +++ linux-2.6.0-test11/net/ipv6/netfilter/Makefile      2003-12-11 12:59:09.998481688 +0100
21274 @@ -6,8 +6,10 @@
21275  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
21276  obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
21277  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
21278 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
21279  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
21280  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
21281 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
21282  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
21283  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
21284  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
21285 @@ -15,10 +17,18 @@
21286  obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
21287  obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
21288  obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
21289 -obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
21290  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
21291  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
21292 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
21293  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
21294 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
21295 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
21296  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
21297  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
21298 +
21299 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
21300 +
21301 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
21302 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
21303 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
21304  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
21305 diff -Nur linux-2.6.0-test11.org/netfilter-patch-o-matic/patches linux-2.6.0-test11/netfilter-patch-o-matic/patches
21306 --- linux-2.6.0-test11.org/netfilter-patch-o-matic/patches      1970-01-01 01:00:00.000000000 +0100
21307 +++ linux-2.6.0-test11/netfilter-patch-o-matic/patches  2003-12-11 12:58:41.483816576 +0100
21308 @@ -0,0 +1,82 @@
21309 +./base/01_sctp_match.patch
21310 +./base/connlimit.patch
21311 +./base/dstlimit.patch
21312 +./base/fuzzy6.patch.ipv6
21313 +./base/fuzzy.patch
21314 +./base/HL.patch.ipv6
21315 +./base/iprange.patch
21316 +./base/ipv4options.patch
21317 +./base/IPV4OPTSSTRIP.patch
21318 +./base/mport.patch
21319 +./base/NETLINK.patch
21320 +./base/nth6.patch.ipv6
21321 +./base/nth.patch
21322 +./base/osf.patch
21323 +./base/pool.patch
21324 +./base/psd.patch
21325 +./base/quota.patch
21326 +./base/random6.patch.ipv6
21327 +./base/random.patch
21328 +./base/realm.patch
21329 +./base/REJECT.patch.ipv6
21330 +./base/SAME.patch
21331 +./base/time.patch
21332 +./base/TTL.patch
21333 +./base/u32.patch
21334 +./extra/addrtype.patch
21335 +./extra/CLASSIFY.patch
21336 +./extra/condition6.patch.ipv6
21337 +./extra/condition.patch
21338 +./extra/CONNMARK.patch
21339 +./extra/cuseeme-nat.patch
21340 +./extra/eggdrop-conntrack.patch
21341 +./extra/h323-conntrack-nat.patch
21342 +./extra/IPMARK.patch
21343 +./extra/iptables-loopcheck-speedup.patch
21344 +./extra/mms-conntrack-nat.patch
21345 +./extra/netfilter-docbook.patch                        manual change
21346 +./extra/pptp-conntrack-nat.patch               manual change
21347 +./extra/quake3-conntrack.patch
21348 +./extra/ROUTE.patch.ipv6
21349 +./extra/rpc.patch
21350 +./extra/rsh.patch
21351 +./extra/rtsp-conntrack.patch
21352 +./extra/talk-conntrack-nat.patch
21353 +./extra/TCPLAG.patch
21354 +./extra/TRACE.patch
21355 +./extra/TRACE.patch.ipv6
21356 +./extra/XOR.patch
21357 +./optimizations/ip_ct_refresh_optimization.patch
21358 +./optimizations/ip_ct_refresh_optimization_pptp.patch
21359 +./pending/23_REJECT-headroom-tcprst.patch
21360 +./pending/24_rcu.patch
21361 +./pending/25-err-ptr.patch
21362 +./pending/26-memsets.patch
21363 +./pending/40_nf-log.patch
21364 +./pending/70_expect-evict-order.patch
21365 +./pending/71_raw.patch
21366 +./submited/02_REJECT-headroom-tcprst.patch
21367 +./submited/03_260t4-mirror-remove.patch
21368 +./submited/03_physdev_bridged.patch
21369 +./submited/04_260t4-unclean-remove.patch
21370 +./submited/05_260t4-unexperimental.patch
21371 +./submited/06_260t4-cosmetic.patch
21372 +./submited/07_260t4-newmodules_iprange_SAME_NETMAP_CLASSIFY.patch
21373 +./submited/07_nonlinear_skb.patch
21374 +./submited/08_260t4_ipt-helper-kconfig.patch
21375 +./submited/09_260t4-cosmetic-physdev-author.patch
21376 +./submited/75_nathelper-udp-csum.patch
21377 +./submited/76_mangle_udp-sizecheck.patch
21378 +./submited/77_destroy-conntrack.patch
21379 +./submited/78_reject-localout.patch
21380 +./submited/80_ip_conntrack-proc.patch
21381 +./submited/82_irc-conntrack-mirc-serverlookup.patch
21382 +./submited/83_nolocalout.patch
21383 +./submited/84_local-nullbinding.patch
21384 +./submited/85_ipv6header.patch
21385 +./submited/86_getorigdst-tuple-zero.patch
21386 +./submited/87_compat-nat_setup_info.patch
21387 +./submited/89_ip_queue-maxlen.patch
21388 +./userspace/ip_queue_vwmark.patch
21389 +./userspace/ipt_REJECT-fake-source.patch
21390 +./userspace/mark-bitwise-ops.patch
This page took 1.934286 seconds and 3 git commands to generate.