]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.7-pom-ng-20040907.patch
- obsolete
[packages/kernel.git] / 2.6.7-pom-ng-20040907.patch
1         info about patch: 
2   Already applied: 
3   updates/01_linux-2.6.4.patch 
4   updates/02_iptables-1.2.11-multi.patch 
5   updates/02_linux-2.6.5.patch 
6   updates/03_linux-2.6.6.patch 
7   updates/04_linux-2.6.6-helper_reassign.patch 
8   updates/05_linux-2.6.6-orphaned_expect.patch 
9   updates/06_linux-2.6.6-skb_len_check.patch 
10   updates/07_linux-2.6.7.patch 
11   updates/08_linux-2.6.7-user_attr.patch 
12   updates/09_linux-2.6.7-ipt_LOG_doff_fix.patch 
13   updates/10_linux-2.6.7-tcp_opt.patch 
14   pending/CLASSIFY_more-hooks amanda_offset-fix 
15   pending/conntrack-acct 
16   pending/conntrack-cacheline-opt 
17   pending/conntrack-seqfile 
18   pending/conntrack_error-api 
19   pending/early-drop-norandom 
20   pending/expect-evict-order 
21   pending/expect-slab-cache 
22   pending/init_conntrack-optimize 
23   pending/ip_nat_helper_static 
24   pending/ip_queue_nonlinear_skbs 
25   pending/ipt_helper-invert-fix 
26   pending/mangle-reroute 
27   pending/nf_reset 
28   pending/owner-broken 
29   pending/proc_net_conntrack-permissions 
30   pending/proc-no-internal-targets 
31   pending/sctp 
32   base/HOPLIMIT 
33   base/IPV4OPTSSTRIP  + require fix: s/<linux/ip.h>/<net/ip.h>/ in net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
34   base/NETMAP 
35   base/REJECT 
36   base/SAME 
37   base/TTL 
38   base/connlimit 
39   base/dstlimit 
40   base/fuzzy 
41   base/iprange 
42   base/ipv4options 
43   base/mport 
44   base/nf-log 
45   base/nth 
46   base/osf 
47   base/psd 
48   base/quota 
49   base/raw 
50   base/realm 
51   base/time
52   base/u32
53  
54  
55 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h
56 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-09-07 12:07:45.184838544 +0200
57 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h     2004-09-07 12:32:45.881697944 +0200
58 @@ -156,6 +156,12 @@
59         union ip_conntrack_expect_help help;
60  };
61  
62 +struct ip_conntrack_counter
63 +{
64 +       u_int64_t packets;
65 +       u_int64_t bytes;
66 +};
67 +
68  struct ip_conntrack_helper;
69  
70  struct ip_conntrack
71 @@ -164,15 +170,17 @@
72             plus 1 for any connection(s) we are `master' for */
73         struct nf_conntrack ct_general;
74  
75 -       /* These are my tuples; original and reply */
76 -       struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
77 -
78         /* Have we seen traffic both ways yet? (bitset) */
79         unsigned long status;
80  
81         /* Timer function; drops refcnt when it goes off. */
82         struct timer_list timeout;
83  
84 +#ifdef CONFIG_IP_NF_CT_ACCT
85 +       /* Accounting Information (same cache line as other written members) */
86 +       struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
87 +#endif
88 +
89         /* If we're expecting another related connection, this will be
90             in expected linked list */
91         struct list_head sibling_list;
92 @@ -207,6 +215,9 @@
93         } nat;
94  #endif /* CONFIG_IP_NF_NAT_NEEDED */
95  
96 +       /* Traversed often, so hopefully in different cacheline to top */
97 +       /* These are my tuples; original and reply */
98 +       struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
99  };
100  
101  /* get master conntrack via master expectation */
102 @@ -245,8 +256,10 @@
103                           const struct ip_conntrack_tuple *orig);
104  
105  /* Refresh conntrack for this many jiffies */
106 -extern void ip_ct_refresh(struct ip_conntrack *ct,
107 -                         unsigned long extra_jiffies);
108 +extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
109 +                              enum ip_conntrack_info ctinfo,
110 +                              const struct sk_buff *skb,
111 +                              unsigned long extra_jiffies);
112  
113  /* These are for NAT.  Icky. */
114  /* Call me when a conntrack is destroyed. */
115 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h
116 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h    2004-09-07 12:07:45.184838544 +0200
117 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h        2004-09-07 12:32:47.916388624 +0200
118 @@ -21,15 +21,17 @@
119  extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
120  extern struct list_head protocol_list;
121  
122 -/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */
123 -extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
124 -                                            enum ip_conntrack_info *ctinfo,
125 -                                            unsigned int hooknum);
126 -extern int get_tuple(const struct iphdr *iph,
127 -                    const struct sk_buff *skb,
128 -                    unsigned int dataoff,
129 -                    struct ip_conntrack_tuple *tuple,
130 -                    const struct ip_conntrack_protocol *protocol);
131 +extern int
132 +ip_ct_get_tuple(const struct iphdr *iph,
133 +               const struct sk_buff *skb,
134 +               unsigned int dataoff,
135 +               struct ip_conntrack_tuple *tuple,
136 +               const struct ip_conntrack_protocol *protocol);
137 +
138 +extern int
139 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
140 +                  const struct ip_conntrack_tuple *orig,
141 +                  const struct ip_conntrack_protocol *protocol);
142  
143  /* Find a connection corresponding to a tuple. */
144  struct ip_conntrack_tuple_hash *
145 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
146 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h        2004-09-07 12:07:45.184838544 +0200
147 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h    2004-09-07 12:32:47.917388472 +0200
148 @@ -3,6 +3,11 @@
149  #define _IP_CONNTRACK_PROTOCOL_H
150  #include <linux/netfilter_ipv4/ip_conntrack.h>
151  
152 +/* length of buffer to which print_tuple/print_conntrack members are
153 + * writing */
154 +
155 +#define IP_CT_PRINT_BUFLEN 100
156 +
157  struct ip_conntrack_protocol
158  {
159         /* Next pointer. */
160 @@ -50,6 +55,9 @@
161         int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
162                                const struct sk_buff *skb);
163  
164 +       int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
165 +                    unsigned int hooknum);
166 +
167         /* Module (if any) which this is connected to. */
168         struct module *me;
169  };
170 @@ -63,4 +71,17 @@
171  extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
172  extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
173  extern int ip_conntrack_protocol_tcp_init(void);
174 +
175 +/* Log invalid packets */
176 +extern unsigned int ip_ct_log_invalid;
177 +
178 +#ifdef DEBUG_INVALID_PACKETS
179 +#define LOG_INVALID(proto) \
180 +       (ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
181 +#else
182 +#define LOG_INVALID(proto) \
183 +       ((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
184 +        && net_ratelimit())
185 +#endif
186 +
187  #endif /*_IP_CONNTRACK_PROTOCOL_H*/
188 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.6.7/include/linux/netfilter_ipv4/ip_nat_helper.h
189 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_nat_helper.h        2004-09-07 12:07:45.156842800 +0200
190 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_nat_helper.h    2004-09-07 12:32:56.182132040 +0200
191 @@ -38,11 +38,12 @@
192                                struct ip_nat_info *info);
193  };
194  
195 -extern struct list_head helpers;
196 -
197  extern int ip_nat_helper_register(struct ip_nat_helper *me);
198  extern void ip_nat_helper_unregister(struct ip_nat_helper *me);
199  
200 +extern struct ip_nat_helper *
201 +ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
202 +
203  /* These return true or false. */
204  extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
205                                 struct ip_conntrack *ct,
206 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.7/include/linux/netfilter_ipv4/ip_tables.h
207 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_tables.h    2004-09-07 12:07:45.184838544 +0200
208 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_tables.h        2004-09-07 12:32:37.051040408 +0200
209 @@ -336,6 +336,7 @@
210   *     Main firewall chains definitions and global var's definitions.
211   */
212  #ifdef __KERNEL__
213 +extern struct semaphore ipt_mutex;
214  static DECLARE_MUTEX(ipt_mutex);
215  
216  #include <linux/init.h>
217 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h
218 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h      1970-01-01 01:00:00.000000000 +0100
219 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h  2004-09-07 12:33:09.040177320 +0200
220 @@ -0,0 +1,21 @@
221 +/* TTL modification module for IP tables
222 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
223 +
224 +#ifndef _IPT_TTL_H
225 +#define _IPT_TTL_H
226 +
227 +enum {
228 +       IPT_TTL_SET = 0,
229 +       IPT_TTL_INC,
230 +       IPT_TTL_DEC
231 +};
232 +
233 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
234 +
235 +struct ipt_TTL_info {
236 +       u_int8_t        mode;
237 +       u_int8_t        ttl;
238 +};
239 +
240 +
241 +#endif
242 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_connlimit.h
243 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connlimit.h        1970-01-01 01:00:00.000000000 +0100
244 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_connlimit.h    2004-09-07 12:33:10.090017720 +0200
245 @@ -0,0 +1,12 @@
246 +#ifndef _IPT_CONNLIMIT_H
247 +#define _IPT_CONNLIMIT_H
248 +
249 +struct ipt_connlimit_data;
250 +
251 +struct ipt_connlimit_info {
252 +       int limit;
253 +       int inverse;
254 +       u_int32_t mask;
255 +       struct ipt_connlimit_data *data;
256 +};
257 +#endif /* _IPT_CONNLIMIT_H */
258 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h
259 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
260 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h     2004-09-07 12:33:11.098864352 +0200
261 @@ -0,0 +1,39 @@
262 +#ifndef _IPT_DSTLIMIT_H
263 +#define _IPT_DSTLIMIT_H
264 +
265 +/* timings are in milliseconds. */
266 +#define IPT_DSTLIMIT_SCALE 10000
267 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
268 +   seconds, or one every 59 hours. */
269 +
270 +/* details of this structure hidden by the implementation */
271 +struct ipt_dstlimit_htable;
272 +
273 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
274 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
275 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
276 +
277 +struct dstlimit_cfg {
278 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
279 +       u_int32_t avg;    /* Average secs between packets * scale */
280 +       u_int32_t burst;  /* Period multiplier for upper limit. */
281 +
282 +       /* user specified */
283 +       u_int32_t size;         /* how many buckets */
284 +       u_int32_t max;          /* max number of entries */
285 +       u_int32_t gc_interval;  /* gc interval */
286 +       u_int32_t expire;       /* when do entries expire? */
287 +};
288 +
289 +struct ipt_dstlimit_info {
290 +       char name [IFNAMSIZ];           /* name */
291 +       struct dstlimit_cfg cfg;
292 +       struct ipt_dstlimit_htable *hinfo;
293 +
294 +       /* Used internally by the kernel */
295 +       union {
296 +               void *ptr;
297 +               struct ipt_dstlimit_info *master;
298 +       } u;
299 +};
300 +#endif /*_IPT_DSTLIMIT_H*/
301 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h
302 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h    1970-01-01 01:00:00.000000000 +0100
303 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h        2004-09-07 12:33:12.079715240 +0200
304 @@ -0,0 +1,21 @@
305 +#ifndef _IPT_FUZZY_H
306 +#define _IPT_FUZZY_H
307 +
308 +#include <linux/param.h>
309 +#include <linux/types.h>
310 +
311 +#define MAXFUZZYRATE 10000000
312 +#define MINFUZZYRATE 3
313 +
314 +struct ipt_fuzzy_info {
315 +       u_int32_t minimum_rate;
316 +       u_int32_t maximum_rate;
317 +       u_int32_t packets_total;
318 +       u_int32_t bytes_total;
319 +       u_int32_t previous_time;
320 +       u_int32_t present_time;
321 +       u_int32_t mean_rate;
322 +       u_int8_t acceptance_rate;
323 +};
324 +
325 +#endif /*_IPT_FUZZY_H*/
326 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h
327 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h      1970-01-01 01:00:00.000000000 +0100
328 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h  2004-09-07 12:33:15.333220632 +0200
329 @@ -0,0 +1,21 @@
330 +#ifndef __ipt_ipv4options_h_included__
331 +#define __ipt_ipv4options_h_included__
332 +
333 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
334 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
335 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
336 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
337 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
338 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
339 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
340 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
341 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
342 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
343 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
344 +
345 +struct ipt_ipv4options_info {
346 +       u_int16_t options;
347 +};
348 +
349 +
350 +#endif /* __ipt_ipv4options_h_included__ */
351 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h
352 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h    1970-01-01 01:00:00.000000000 +0100
353 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h        2004-09-07 12:33:16.383061032 +0200
354 @@ -0,0 +1,24 @@
355 +#ifndef _IPT_MPORT_H
356 +#define _IPT_MPORT_H
357 +#include <linux/netfilter_ipv4/ip_tables.h>
358 +
359 +#define IPT_MPORT_SOURCE (1<<0)
360 +#define IPT_MPORT_DESTINATION (1<<1)
361 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
362 +
363 +#define IPT_MULTI_PORTS        15
364 +
365 +/* Must fit inside union ipt_matchinfo: 32 bytes */
366 +/* every entry in ports[] except for the last one has one bit in pflags
367 + * associated with it. If this bit is set, the port is the first port of
368 + * a portrange, with the next entry being the last.
369 + * End of list is marked with pflags bit set and port=65535.
370 + * If 14 ports are used (last one does not have a pflag), the last port
371 + * is repeated to fill the last entry in ports[] */
372 +struct ipt_mport
373 +{
374 +       u_int8_t flags:2;                       /* Type of comparison */
375 +       u_int16_t pflags:14;                    /* Port flags */
376 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
377 +};
378 +#endif /*_IPT_MPORT_H*/
379 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h
380 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h      1970-01-01 01:00:00.000000000 +0100
381 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h  2004-09-07 12:33:17.546884104 +0200
382 @@ -0,0 +1,19 @@
383 +#ifndef _IPT_NTH_H
384 +#define _IPT_NTH_H
385 +
386 +#include <linux/param.h>
387 +#include <linux/types.h>
388 +
389 +#ifndef IPT_NTH_NUM_COUNTERS
390 +#define IPT_NTH_NUM_COUNTERS 16
391 +#endif
392 +
393 +struct ipt_nth_info {
394 +       u_int8_t every;
395 +       u_int8_t not;
396 +       u_int8_t startat;
397 +       u_int8_t counter;
398 +       u_int8_t packet;
399 +};
400 +
401 +#endif /*_IPT_NTH_H*/
402 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h
403 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h      1970-01-01 01:00:00.000000000 +0100
404 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h  2004-09-07 12:33:18.674712648 +0200
405 @@ -0,0 +1,149 @@
406 +/*
407 + * ipt_osf.h
408 + *
409 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
410 + *
411 + *
412 + * This program is free software; you can redistribute it and/or modify
413 + * it under the terms of the GNU General Public License as published by
414 + * the Free Software Foundation; either version 2 of the License, or
415 + * (at your option) any later version.
416 + *
417 + * This program is distributed in the hope that it will be useful,
418 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
419 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
420 + * GNU General Public License for more details.
421 + *
422 + * You should have received a copy of the GNU General Public License
423 + * along with this program; if not, write to the Free Software
424 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
425 + */
426 +
427 +#ifndef _IPT_OSF_H
428 +#define _IPT_OSF_H
429 +
430 +#define MAXGENRELEN            32
431 +#define MAXDETLEN              64
432 +
433 +#define IPT_OSF_GENRE          1
434 +#define        IPT_OSF_SMART           2
435 +#define IPT_OSF_LOG            4
436 +#define IPT_OSF_NETLINK                8
437 +
438 +#define IPT_OSF_LOGLEVEL_ALL   0
439 +#define IPT_OSF_LOGLEVEL_FIRST 1
440 +
441 +#include <linux/list.h>
442 +#include <net/tcp.h>
443 +
444 +#ifndef __KERNEL__
445 +#include <netinet/ip.h>
446 +#include <netinet/tcp.h>
447 +
448 +struct list_head
449 +{
450 +       struct list_head *prev, *next;
451 +};
452 +#endif
453 +
454 +struct ipt_osf_info
455 +{
456 +       char                    genre[MAXGENRELEN];
457 +       int                     len;
458 +       unsigned long           flags;
459 +       int                     loglevel;
460 +       int                     invert; /* UNSUPPORTED */
461 +};
462 +
463 +struct osf_wc
464 +{
465 +       char                    wc;
466 +       unsigned long           val;
467 +};
468 +
469 +/* This struct represents IANA options
470 + * http://www.iana.org/assignments/tcp-parameters
471 + */
472 +struct osf_opt
473 +{
474 +       unsigned char           kind;
475 +       unsigned char           length;
476 +       struct osf_wc           wc;
477 +};
478 +
479 +struct osf_finger
480 +{
481 +       struct list_head        flist;
482 +       struct osf_wc           wss;
483 +       unsigned char           ttl;
484 +       unsigned char           df;
485 +       unsigned long           ss;
486 +       unsigned char           genre[MAXGENRELEN];
487 +       unsigned char           version[MAXGENRELEN], subtype[MAXGENRELEN];
488 +
489 +       /* Not needed, but for consistency with original table from Michal Zalewski */
490 +       unsigned char           details[MAXDETLEN]; 
491 +
492 +       int                     opt_num;
493 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
494 +
495 +};
496 +
497 +struct ipt_osf_nlmsg
498 +{
499 +       struct osf_finger       f;
500 +       struct iphdr            ip;
501 +       struct tcphdr           tcp;
502 +};
503 +
504 +#ifdef __KERNEL__
505 +
506 +/* Defines for IANA option kinds */
507 +
508 +#define OSFOPT_EOL             0       /* End of options */
509 +#define OSFOPT_NOP             1       /* NOP */
510 +#define OSFOPT_MSS             2       /* Maximum segment size */
511 +#define OSFOPT_WSO             3       /* Window scale option */
512 +#define OSFOPT_SACKP           4       /* SACK permitted */
513 +#define OSFOPT_SACK            5       /* SACK */
514 +#define OSFOPT_ECHO            6
515 +#define OSFOPT_ECHOREPLY       7
516 +#define OSFOPT_TS              8       /* Timestamp option */
517 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
518 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
519 +/* Others are not used in current OSF */
520 +
521 +static struct osf_opt IANA_opts[] = 
522 +{
523 +       {0, 1,},
524 +       {1, 1,},
525 +       {2, 4,},
526 +       {3, 3,},
527 +       {4, 2,},
528 +       {5, 1 ,}, /* SACK length is not defined */
529 +       {6, 6,},
530 +       {7, 6,},
531 +       {8, 10,},
532 +       {9, 2,},
533 +       {10, 3,},
534 +       {11, 1,}, /* CC: Suppose 1 */
535 +       {12, 1,}, /* the same */
536 +       {13, 1,}, /* and here too */
537 +       {14, 3,},
538 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
539 +       {16, 1,},
540 +       {17, 1,},
541 +       {18, 3,},
542 +       {19, 18,},
543 +       {20, 1,},
544 +       {21, 1,},
545 +       {22, 1,},
546 +       {23, 1,},
547 +       {24, 1,},
548 +       {25, 1,},
549 +       {26, 1,},
550 +};
551 +
552 +#endif /* __KERNEL__ */
553 +
554 +#endif /* _IPT_OSF_H */
555 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h
556 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h      1970-01-01 01:00:00.000000000 +0100
557 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h  2004-09-07 12:33:19.723553200 +0200
558 @@ -0,0 +1,40 @@
559 +#ifndef _IPT_PSD_H
560 +#define _IPT_PSD_H
561 +
562 +#include <linux/param.h>
563 +#include <linux/types.h>
564 +
565 +/*
566 + * High port numbers have a lower weight to reduce the frequency of false
567 + * positives, such as from passive mode FTP transfers.
568 + */
569 +#define PORT_WEIGHT_PRIV               3
570 +#define PORT_WEIGHT_HIGH               1
571 +
572 +/*
573 + * Port scan detection thresholds: at least COUNT ports need to be scanned
574 + * from the same source, with no longer than DELAY ticks between ports.
575 + */
576 +#define SCAN_MIN_COUNT                 7
577 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
578 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
579 +#define SCAN_DELAY_THRESHOLD           (300) /* old usage of HZ here was erroneously and broke under uml */
580 +
581 +/*
582 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
583 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
584 + * HASH_MAX source addresses per the same hash value.
585 + */
586 +#define LIST_SIZE                      0x100
587 +#define HASH_LOG                       9
588 +#define HASH_SIZE                      (1 << HASH_LOG)
589 +#define HASH_MAX                       0x10
590 +
591 +struct ipt_psd_info {
592 +       unsigned int weight_threshold;
593 +       unsigned int delay_threshold;
594 +       unsigned short lo_ports_weight;
595 +       unsigned short hi_ports_weight;
596 +};
597 +
598 +#endif /*_IPT_PSD_H*/
599 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h
600 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h    1970-01-01 01:00:00.000000000 +0100
601 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h        2004-09-07 12:33:20.689406368 +0200
602 @@ -0,0 +1,11 @@
603 +#ifndef _IPT_QUOTA_H
604 +#define _IPT_QUOTA_H
605 +
606 +/* print debug info in both kernel/netfilter module & iptable library */
607 +//#define DEBUG_IPT_QUOTA
608 +
609 +struct ipt_quota_info {
610 +        u_int64_t quota;
611 +};
612 +
613 +#endif /*_IPT_QUOTA_H*/
614 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h
615 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h     1970-01-01 01:00:00.000000000 +0100
616 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h 2004-09-07 12:33:05.389732272 +0200
617 @@ -0,0 +1,107 @@
618 +#ifndef _IPT_SCTP_H_
619 +#define _IPT_SCTP_H_
620 +
621 +#define IPT_SCTP_SRC_PORTS             0x01
622 +#define IPT_SCTP_DEST_PORTS            0x02
623 +#define IPT_SCTP_CHUNK_TYPES           0x04
624 +
625 +#define IPT_SCTP_VALID_FLAGS           0x07
626 +
627 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
628 +
629 +
630 +struct ipt_sctp_flag_info {
631 +       u_int8_t chunktype;
632 +       u_int8_t flag;
633 +       u_int8_t flag_mask;
634 +};
635 +
636 +#define IPT_NUM_SCTP_FLAGS     4
637 +
638 +struct ipt_sctp_info {
639 +       u_int16_t dpts[2];  /* Min, Max */
640 +       u_int16_t spts[2];  /* Min, Max */
641 +
642 +       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
643 +
644 +#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
645 +#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
646 +#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
647 +
648 +       u_int32_t chunk_match_type;
649 +       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
650 +       int flag_count;
651 +
652 +       u_int32_t flags;
653 +       u_int32_t invflags;
654 +};
655 +
656 +#define bytes(type) (sizeof(type) * 8)
657 +
658 +#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
659 +       do {                                            \
660 +               chunkmap[type / bytes(u_int32_t)] |=    \
661 +                       1 << (type % bytes(u_int32_t)); \
662 +       } while (0)
663 +
664 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
665 +       do {                                                    \
666 +               chunkmap[type / bytes(u_int32_t)] &=            \
667 +                       ~(1 << (type % bytes(u_int32_t)));      \
668 +       } while (0)
669 +
670 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
671 +({                                                             \
672 +       (chunkmap[type / bytes (u_int32_t)] &                   \
673 +               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
674 +})
675 +
676 +#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
677 +       do {                                                    \
678 +               int i;                                          \
679 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
680 +                       chunkmap[i] = 0;                        \
681 +       } while (0)
682 +
683 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
684 +       do {                                                    \
685 +               int i;                                          \
686 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
687 +                       chunkmap[i] = ~0;                       \
688 +       } while (0)
689 +
690 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
691 +       do {                                                    \
692 +               int i;                                          \
693 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
694 +                       destmap[i] = srcmap[i];                 \
695 +       } while (0)
696 +
697 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
698 +({                                                     \
699 +       int i;                                          \
700 +       int flag = 1;                                   \
701 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
702 +               if (chunkmap[i]) {                      \
703 +                       flag = 0;                       \
704 +                       break;                          \
705 +               }                                       \
706 +       }                                               \
707 +        flag;                                          \
708 +})
709 +
710 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
711 +({                                                     \
712 +       int i;                                          \
713 +       int flag = 1;                                   \
714 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
715 +               if (chunkmap[i] != ~0) {                \
716 +                       flag = 0;                       \
717 +                               break;                  \
718 +               }                                       \
719 +       }                                               \
720 +        flag;                                          \
721 +})
722 +
723 +#endif /* _IPT_SCTP_H_ */
724 +
725 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h
726 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h     1970-01-01 01:00:00.000000000 +0100
727 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h 2004-09-07 12:33:22.072196152 +0200
728 @@ -0,0 +1,15 @@
729 +#ifndef __ipt_time_h_included__
730 +#define __ipt_time_h_included__
731 +
732 +
733 +struct ipt_time_info {
734 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
735 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
736 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
737 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
738 +       time_t    date_start;
739 +       time_t    date_stop;
740 +};
741 +
742 +
743 +#endif /* __ipt_time_h_included__ */
744 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h
745 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h      1970-01-01 01:00:00.000000000 +0100
746 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h  2004-09-07 12:38:33.376870648 +0200
747 @@ -0,0 +1,40 @@
748 +#ifndef _IPT_U32_H
749 +#define _IPT_U32_H
750 +#include <linux/netfilter_ipv4/ip_tables.h>
751 +
752 +enum ipt_u32_ops
753 +{
754 +       IPT_U32_AND,
755 +       IPT_U32_LEFTSH,
756 +       IPT_U32_RIGHTSH,
757 +       IPT_U32_AT
758 +};
759 +
760 +struct ipt_u32_location_element
761 +{
762 +       u_int32_t number;
763 +       u_int8_t nextop;
764 +};
765 +struct ipt_u32_value_element
766 +{
767 +       u_int32_t min;
768 +       u_int32_t max;
769 +};
770 +/* *** any way to allow for an arbitrary number of elements?
771 +   for now I settle for a limit of 10 of each */
772 +#define U32MAXSIZE 10
773 +struct ipt_u32_test
774 +{
775 +       u_int8_t nnums;
776 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
777 +       u_int8_t nvalues;
778 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
779 +};
780 +
781 +struct ipt_u32
782 +{
783 +       u_int8_t ntests;
784 +       struct ipt_u32_test tests[U32MAXSIZE+1];
785 +};
786 +
787 +#endif /*_IPT_U32_H*/
788 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h
789 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h      1970-01-01 01:00:00.000000000 +0100
790 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h  2004-09-07 12:33:06.516560968 +0200
791 @@ -0,0 +1,22 @@
792 +/* Hop Limit modification module for ip6tables
793 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
794 + * Based on HW's TTL module */
795 +
796 +#ifndef _IP6T_HL_H
797 +#define _IP6T_HL_H
798 +
799 +enum {
800 +       IP6T_HL_SET = 0,
801 +       IP6T_HL_INC,
802 +       IP6T_HL_DEC
803 +};
804 +
805 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
806 +
807 +struct ip6t_HL_info {
808 +       u_int8_t        mode;
809 +       u_int8_t        hop_limit;
810 +};
811 +
812 +
813 +#endif
814 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h
815 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-09-07 12:07:45.155842952 +0200
816 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-09-07 12:33:08.262295576 +0200
817 @@ -2,15 +2,17 @@
818  #define _IP6T_REJECT_H
819  
820  enum ip6t_reject_with {
821 -       IP6T_ICMP_NET_UNREACHABLE,
822 -       IP6T_ICMP_HOST_UNREACHABLE,
823 -       IP6T_ICMP_PROT_UNREACHABLE,
824 -       IP6T_ICMP_PORT_UNREACHABLE,
825 -       IP6T_ICMP_ECHOREPLY
826 +       IP6T_ICMP6_NO_ROUTE,
827 +       IP6T_ICMP6_ADM_PROHIBITED,
828 +       IP6T_ICMP6_NOT_NEIGHBOUR,
829 +       IP6T_ICMP6_ADDR_UNREACH,
830 +       IP6T_ICMP6_PORT_UNREACH,
831 +       IP6T_ICMP6_ECHOREPLY,
832 +       IP6T_TCP_RESET
833  };
834  
835  struct ip6t_reject_info {
836         enum ip6t_reject_with with;      /* reject type */
837  };
838  
839 -#endif /*_IPT_REJECT_H*/
840 +#endif /*_IP6T_REJECT_H*/
841 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h
842 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h   1970-01-01 01:00:00.000000000 +0100
843 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h       2004-09-07 12:33:12.080715088 +0200
844 @@ -0,0 +1,21 @@
845 +#ifndef _IP6T_FUZZY_H
846 +#define _IP6T_FUZZY_H
847 +
848 +#include <linux/param.h>
849 +#include <linux/types.h>
850 +
851 +#define MAXFUZZYRATE 10000000
852 +#define MINFUZZYRATE 3
853 +
854 +struct ip6t_fuzzy_info {
855 +       u_int32_t minimum_rate;
856 +       u_int32_t maximum_rate;
857 +       u_int32_t packets_total;
858 +       u_int32_t bytes_total;
859 +       u_int32_t previous_time;
860 +       u_int32_t present_time;
861 +       u_int32_t mean_rate;
862 +       u_int8_t acceptance_rate;
863 +};
864 +
865 +#endif /*_IP6T_FUZZY_H*/
866 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h
867 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h     1970-01-01 01:00:00.000000000 +0100
868 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h 2004-09-07 12:33:17.547883952 +0200
869 @@ -0,0 +1,19 @@
870 +#ifndef _IP6T_NTH_H
871 +#define _IP6T_NTH_H
872 +
873 +#include <linux/param.h>
874 +#include <linux/types.h>
875 +
876 +#ifndef IP6T_NTH_NUM_COUNTERS
877 +#define IP6T_NTH_NUM_COUNTERS 16
878 +#endif
879 +
880 +struct ip6t_nth_info {
881 +       u_int8_t every;
882 +       u_int8_t not;
883 +       u_int8_t startat;
884 +       u_int8_t counter;
885 +       u_int8_t packet;
886 +};
887 +
888 +#endif /*_IP6T_NTH_H*/
889 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/sysctl.h linux-2.6.7/include/linux/sysctl.h
890 --- linux-2.6.7.org/include/linux/sysctl.h      2004-09-07 12:07:45.225832312 +0200
891 +++ linux-2.6.7/include/linux/sysctl.h  2004-09-07 12:32:47.918388320 +0200
892 @@ -410,6 +410,7 @@
893         NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
894         NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
895         NET_IPV4_NF_CONNTRACK_BUCKETS=14,
896 +       NET_IPV4_NF_CONNTRACK_LOG_INVALID=15,
897  };
898   
899  /* /proc/sys/net/ipv6 */
900 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Kconfig linux-2.6.7/net/ipv4/netfilter/Kconfig
901 --- linux-2.6.7.org/net/ipv4/netfilter/Kconfig  2004-09-07 12:07:46.566628480 +0200
902 +++ linux-2.6.7/net/ipv4/netfilter/Kconfig      2004-09-07 12:38:33.380870040 +0200
903 @@ -628,5 +628,174 @@
904           If you want to compile it as a module, say M here and read
905           Documentation/modules.txt.  If unsure, say `N'.
906  
907 +config IP_NF_CT_ACCT
908 +       bool "Connection tracking flow accounting"
909 +       depends on IP_NF_CONNTRACK
910 +
911 +config IP_NF_MATCH_SCTP
912 +       tristate  'SCTP protocol match support'
913 +       depends on IP_NF_IPTABLES
914 +
915 +config IP_NF_TARGET_IPV4OPTSSTRIP
916 +       tristate  'IPV4OPTSSTRIP target support'
917 +       depends on IP_NF_MANGLE
918 +       help
919 +         This option adds an IPV4OPTSSTRIP target.
920 +         This target allows you to strip all IP options in a packet.
921 +        
922 +         If you want to compile it as a module, say M here and read
923 +         Documentation/modules.txt.  If unsure, say `N'.
924 +
925 +config IP_NF_TARGET_TTL
926 +       tristate  'TTL target support'
927 +       depends on IP_NF_MANGLE
928 +       help
929 +         This option adds a `TTL' target, which enables the user to set
930 +         the TTL value or increment / decrement the TTL value by a given
931 +         amount.
932 +       
933 +         If you want to compile it as a module, say M here and read
934 +         Documentation/modules.txt.  If unsure, say `N'.
935 +
936 +config IP_NF_MATCH_CONNLIMIT
937 +       tristate  'Connections/IP limit match support'
938 +       depends on IP_NF_IPTABLES
939 +       help
940 +         This match allows you to restrict the number of parallel TCP
941 +         connections to a server per client IP address (or address block).
942 +       
943 +         If you want to compile it as a module, say M here and read
944 +         Documentation/modules.txt.  If unsure, say `N'.
945 +
946 +config IP_NF_MATCH_DSTLIMIT
947 +       tristate  'dstlimit match support'
948 +       depends on IP_NF_IPTABLES
949 +
950 +config IP_NF_MATCH_FUZZY
951 +       tristate  'fuzzy match support'
952 +       depends on IP_NF_IPTABLES
953 +       help
954 +         This option adds a `fuzzy' match, which allows you to match
955 +         packets according to a fuzzy logic based law.
956 +       
957 +         If you want to compile it as a module, say M here and read
958 +         Documentation/modules.txt.  If unsure, say `N'.
959 +
960 +config IP_NF_MATCH_IPV4OPTIONS
961 +       tristate  'IPV4OPTIONS match support'
962 +       depends on IP_NF_IPTABLES
963 +       help
964 +         This option adds a IPV4OPTIONS match.
965 +         It allows you to filter options like source routing,
966 +         record route, timestamp and router-altert.
967 +       
968 +         If you say Y here, try iptables -m ipv4options --help for more information.
969 +        
970 +         If you want to compile it as a module, say M here and read
971 +         Documentation/modules.txt.  If unsure, say `N'.
972 +
973 +config IP_NF_MATCH_MPORT
974 +       tristate  'Multiple port with ranges match support'
975 +       depends on IP_NF_IPTABLES
976 +       help
977 +         This is an enhanced multiport match which supports port
978 +         ranges as well as single ports.
979 +       
980 +         If you want to compile it as a module, say M here and read
981 +         Documentation/modules.txt.  If unsure, say `N'.
982 +
983 +config IP_NF_MATCH_NTH
984 +       tristate  'Nth match support'
985 +       depends on IP_NF_IPTABLES
986 +       help
987 +         This option adds a `Nth' match, which allow you to make
988 +         rules that match every Nth packet.  By default there are 
989 +         16 different counters.
990 +       
991 +         [options]
992 +          --every     Nth              Match every Nth packet
993 +         [--counter]  num              Use counter 0-15 (default:0)
994 +         [--start]    num              Initialize the counter at the number 'num'
995 +                                       instead of 0. Must be between 0 and Nth-1
996 +         [--packet]   num              Match on 'num' packet. Must be between 0
997 +                                       and Nth-1.
998 +       
999 +                                       If --packet is used for a counter than
1000 +                                       there must be Nth number of --packet
1001 +                                       rules, covering all values between 0 and
1002 +                                       Nth-1 inclusively.
1003 +        
1004 +         If you want to compile it as a module, say M here and read
1005 +         Documentation/modules.txt.  If unsure, say `N'.
1006 +
1007 +config IP_NF_MATCH_OSF
1008 +       tristate  'OSF match support'
1009 +       depends on IP_NF_IPTABLES
1010 +       help
1011 +       
1012 +         The idea of passive OS fingerprint matching exists for quite a long time,
1013 +         but was created as extension fo OpenBSD pf only some weeks ago.
1014 +         Original idea was lurked in some OpenBSD mailing list (thanks
1015 +         grange@open...) and than adopted for Linux netfilter in form of this code.
1016 +       
1017 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
1018 +         his excellent p0f and than changed a bit for more convenience.
1019 +       
1020 +         This module compares some data(WS, MSS, options and it's order, ttl,
1021 +         df and others) from first SYN packet (actually from packets with SYN
1022 +         bit set) with hardcoded in fingers[] table ones.
1023 +       
1024 +         If you say Y here, try iptables -m osf --help for more information.
1025 +        
1026 +         If you want to compile it as a module, say M here and read
1027 +         Documentation/modules.txt.  If unsure, say `N'.
1028 +
1029 +config IP_NF_MATCH_PSD
1030 +       tristate  'psd match support'
1031 +       depends on IP_NF_IPTABLES
1032 +       help
1033 +         This option adds a `psd' match, which allows you to create rules in
1034 +         any iptables table wich will detect TCP and UDP port scans.
1035 +        
1036 +         If you want to compile it as a module, say M here and read
1037 +         Documentation/modules.txt.  If unsure, say `N'.
1038 +
1039 +config IP_NF_MATCH_QUOTA
1040 +       tristate  'quota match support'
1041 +       depends on IP_NF_IPTABLES
1042 +       help
1043 +         This match implements network quotas.
1044 +       
1045 +         If you want to compile it as a module, say M here and read
1046 +         Documentation/modules.txt.  If unsure, say `N'.
1047 +       
1048 +
1049 +config IP_NF_MATCH_TIME
1050 +       tristate  'TIME match support'
1051 +       depends on IP_NF_IPTABLES
1052 +       help
1053 +         This option adds a `time' match, which allows you
1054 +         to match based on the packet arrival time/date
1055 +         (arrival time/date at the machine which netfilter is running on) or
1056 +         departure time/date (for locally generated packets).
1057 +       
1058 +         If you say Y here, try iptables -m time --help for more information.
1059 +        
1060 +         If you want to compile it as a module, say M here and read
1061 +         Documentation/modules.txt.  If unsure, say `N'.
1062 +
1063 +config IP_NF_MATCH_U32
1064 +       tristate  'U32 match support'
1065 +       depends on IP_NF_IPTABLES
1066 +       help
1067 +         U32 allows you to extract quantities of up to 4 bytes from a packet,
1068 +         AND them with specified masks, shift them by specified amounts and
1069 +         test whether the results are in any of a set of specified ranges.
1070 +         The specification of what to extract is general enough to skip over
1071 +         headers with lengths stored in the packet, as in IP or TCP header
1072 +         lengths.
1073 +       
1074 +         Details and examples are in the kernel module source.
1075 +
1076  endmenu
1077  
1078 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Makefile linux-2.6.7/net/ipv4/netfilter/Makefile
1079 --- linux-2.6.7.org/net/ipv4/netfilter/Makefile 2004-09-07 12:07:46.565628632 +0200
1080 +++ linux-2.6.7/net/ipv4/netfilter/Makefile     2004-09-07 12:38:33.381869888 +0200
1081 @@ -43,15 +43,36 @@
1082  # matches
1083  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1084  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1085 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
1086 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
1087 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1088  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
1089  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
1090  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
1091  
1092  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
1093  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1094 +
1095 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1096 +
1097  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1098  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1099  
1100 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1101 +
1102 +
1103 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
1104 +
1105 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
1106 +
1107 +
1108 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
1109 +
1110 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
1111 +
1112 +
1113 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
1114 +
1115  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
1116  
1117  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
1118 @@ -60,8 +81,12 @@
1119  
1120  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
1121  
1122 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1123 +
1124 +
1125  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1126  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1127 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1128  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1129  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1130  obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1131 @@ -82,6 +107,8 @@
1132  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1133  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1134  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1135 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1136 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1137  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1138  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1139  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
1140 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_amanda.c
1141 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_amanda.c    2004-09-07 12:07:46.566628480 +0200
1142 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_amanda.c        2004-09-07 12:32:44.773866360 +0200
1143 @@ -58,7 +58,7 @@
1144  
1145         /* increase the UDP timeout of the master connection as replies from
1146          * Amanda clients to the server can be quite delayed */
1147 -       ip_ct_refresh(ct, master_timeout * HZ);
1148 +       ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ);
1149  
1150         /* No data? */
1151         dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr);
1152 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c
1153 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c      2004-09-07 12:07:46.565628632 +0200
1154 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c  2004-09-07 12:32:54.736351832 +0200
1155 @@ -58,6 +58,7 @@
1156  
1157  DECLARE_RWLOCK(ip_conntrack_lock);
1158  DECLARE_RWLOCK(ip_conntrack_expect_tuple_lock);
1159 +static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
1160  
1161  void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
1162  LIST_HEAD(ip_conntrack_expect_list);
1163 @@ -65,9 +66,9 @@
1164  static LIST_HEAD(helpers);
1165  unsigned int ip_conntrack_htable_size = 0;
1166  int ip_conntrack_max;
1167 -static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
1168  struct list_head *ip_conntrack_hash;
1169  static kmem_cache_t *ip_conntrack_cachep;
1170 +static kmem_cache_t *ip_conntrack_expect_cachep;
1171  struct ip_conntrack ip_conntrack_untracked;
1172  
1173  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
1174 @@ -127,11 +128,11 @@
1175  }
1176  
1177  int
1178 -get_tuple(const struct iphdr *iph,
1179 -         const struct sk_buff *skb,
1180 -         unsigned int dataoff,
1181 -         struct ip_conntrack_tuple *tuple,
1182 -         const struct ip_conntrack_protocol *protocol)
1183 +ip_ct_get_tuple(const struct iphdr *iph,
1184 +               const struct sk_buff *skb,
1185 +               unsigned int dataoff,
1186 +               struct ip_conntrack_tuple *tuple,
1187 +               const struct ip_conntrack_protocol *protocol)
1188  {
1189         /* Never happen */
1190         if (iph->frag_off & htons(IP_OFFSET)) {
1191 @@ -147,10 +148,10 @@
1192         return protocol->pkt_to_tuple(skb, dataoff, tuple);
1193  }
1194  
1195 -static int
1196 -invert_tuple(struct ip_conntrack_tuple *inverse,
1197 -            const struct ip_conntrack_tuple *orig,
1198 -            const struct ip_conntrack_protocol *protocol)
1199 +int
1200 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
1201 +                  const struct ip_conntrack_tuple *orig,
1202 +                  const struct ip_conntrack_protocol *protocol)
1203  {
1204         inverse->src.ip = orig->dst.ip;
1205         inverse->dst.ip = orig->src.ip;
1206 @@ -177,7 +178,7 @@
1207         IP_NF_ASSERT(atomic_read(&exp->use) == 0);
1208         IP_NF_ASSERT(!timer_pending(&exp->timeout));
1209  
1210 -       kfree(exp);
1211 +       kmem_cache_free(ip_conntrack_expect_cachep, exp);
1212  }
1213  
1214  inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
1215 @@ -336,7 +337,7 @@
1216                         list_del(&ct->master->expected_list);
1217                         master = ct->master->expectant;
1218                 }
1219 -               kfree(ct->master);
1220 +               kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
1221         }
1222         WRITE_UNLOCK(&ip_conntrack_lock);
1223  
1224 @@ -496,83 +497,6 @@
1225         return h != NULL;
1226  }
1227  
1228 -/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
1229 -struct ip_conntrack *
1230 -icmp_error_track(struct sk_buff *skb,
1231 -                enum ip_conntrack_info *ctinfo,
1232 -                unsigned int hooknum)
1233 -{
1234 -       struct ip_conntrack_tuple innertuple, origtuple;
1235 -       struct {
1236 -               struct icmphdr icmp;
1237 -               struct iphdr ip;
1238 -       } inside;
1239 -       struct ip_conntrack_protocol *innerproto;
1240 -       struct ip_conntrack_tuple_hash *h;
1241 -       int dataoff;
1242 -
1243 -       IP_NF_ASSERT(skb->nfct == NULL);
1244 -
1245 -       /* Not enough header? */
1246 -       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
1247 -               return NULL;
1248 -
1249 -       if (inside.icmp.type != ICMP_DEST_UNREACH
1250 -           && inside.icmp.type != ICMP_SOURCE_QUENCH
1251 -           && inside.icmp.type != ICMP_TIME_EXCEEDED
1252 -           && inside.icmp.type != ICMP_PARAMETERPROB
1253 -           && inside.icmp.type != ICMP_REDIRECT)
1254 -               return NULL;
1255 -
1256 -       /* Ignore ICMP's containing fragments (shouldn't happen) */
1257 -       if (inside.ip.frag_off & htons(IP_OFFSET)) {
1258 -               DEBUGP("icmp_error_track: fragment of proto %u\n",
1259 -                      inside.ip.protocol);
1260 -               return NULL;
1261 -       }
1262 -
1263 -       innerproto = ip_ct_find_proto(inside.ip.protocol);
1264 -       dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
1265 -       /* Are they talking about one of our connections? */
1266 -       if (!get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
1267 -               DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
1268 -               return NULL;
1269 -       }
1270 -
1271 -       /* Ordinarily, we'd expect the inverted tupleproto, but it's
1272 -          been preserved inside the ICMP. */
1273 -       if (!invert_tuple(&innertuple, &origtuple, innerproto)) {
1274 -               DEBUGP("icmp_error_track: Can't invert tuple\n");
1275 -               return NULL;
1276 -       }
1277 -
1278 -       *ctinfo = IP_CT_RELATED;
1279 -
1280 -       h = ip_conntrack_find_get(&innertuple, NULL);
1281 -       if (!h) {
1282 -               /* Locally generated ICMPs will match inverted if they
1283 -                  haven't been SNAT'ed yet */
1284 -               /* FIXME: NAT code has to handle half-done double NAT --RR */
1285 -               if (hooknum == NF_IP_LOCAL_OUT)
1286 -                       h = ip_conntrack_find_get(&origtuple, NULL);
1287 -
1288 -               if (!h) {
1289 -                       DEBUGP("icmp_error_track: no match\n");
1290 -                       return NULL;
1291 -               }
1292 -               /* Reverse direction from that found */
1293 -               if (DIRECTION(h) != IP_CT_DIR_REPLY)
1294 -                       *ctinfo += IP_CT_IS_REPLY;
1295 -       } else {
1296 -               if (DIRECTION(h) == IP_CT_DIR_REPLY)
1297 -                       *ctinfo += IP_CT_IS_REPLY;
1298 -       }
1299 -
1300 -       /* Update skb to refer to this connection */
1301 -       skb->nfct = &h->ctrack->infos[*ctinfo];
1302 -       return h->ctrack;
1303 -}
1304 -
1305  /* There's a small race here where we may free a just-assured
1306     connection.  Too bad: we're in trouble anyway. */
1307  static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
1308 @@ -628,7 +552,6 @@
1309         size_t hash;
1310         struct ip_conntrack_expect *expected;
1311         int i;
1312 -       static unsigned int drop_next;
1313  
1314         if (!ip_conntrack_hash_rnd_initted) {
1315                 get_random_bytes(&ip_conntrack_hash_rnd, 4);
1316 @@ -637,15 +560,10 @@
1317  
1318         hash = hash_conntrack(tuple);
1319  
1320 -       if (ip_conntrack_max &&
1321 -           atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
1322 -               /* Try dropping from random chain, or else from the
1323 -                   chain about to put into (in case they're trying to
1324 -                   bomb one hash chain). */
1325 -               unsigned int next = (drop_next++)%ip_conntrack_htable_size;
1326 -
1327 -               if (!early_drop(&ip_conntrack_hash[next])
1328 -                   && !early_drop(&ip_conntrack_hash[hash])) {
1329 +       if (ip_conntrack_max
1330 +           && atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
1331 +               /* Try dropping from this hash chain. */
1332 +               if (!early_drop(&ip_conntrack_hash[hash])) {
1333                         if (net_ratelimit())
1334                                 printk(KERN_WARNING
1335                                        "ip_conntrack: table full, dropping"
1336 @@ -654,7 +572,7 @@
1337                 }
1338         }
1339  
1340 -       if (!invert_tuple(&repl_tuple, tuple, protocol)) {
1341 +       if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
1342                 DEBUGP("Can't invert tuple.\n");
1343                 return NULL;
1344         }
1345 @@ -693,41 +611,48 @@
1346                              struct ip_conntrack_expect *, tuple);
1347         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
1348  
1349 -       /* If master is not in hash table yet (ie. packet hasn't left
1350 -          this machine yet), how can other end know about expected?
1351 -          Hence these are not the droids you are looking for (if
1352 -          master ct never got confirmed, we'd hold a reference to it
1353 -          and weird things would happen to future packets). */
1354 -       if (expected && !is_confirmed(expected->expectant))
1355 -               expected = NULL;
1356 -
1357 -       /* Look up the conntrack helper for master connections only */
1358 -       if (!expected)
1359 -               conntrack->helper = ip_ct_find_helper(&repl_tuple);
1360 +       if (expected) {
1361 +               /* If master is not in hash table yet (ie. packet hasn't left
1362 +                  this machine yet), how can other end know about expected?
1363 +                  Hence these are not the droids you are looking for (if
1364 +                  master ct never got confirmed, we'd hold a reference to it
1365 +                  and weird things would happen to future packets). */
1366 +               if (!is_confirmed(expected->expectant)) {
1367 +                       conntrack->helper = ip_ct_find_helper(&repl_tuple);
1368 +                       goto end;
1369 +               }
1370  
1371 -       /* If the expectation is dying, then this is a loser. */
1372 -       if (expected
1373 -           && expected->expectant->helper->timeout
1374 -           && ! del_timer(&expected->timeout))
1375 -               expected = NULL;
1376 +               /* Expectation is dying... */
1377 +               if (expected->expectant->helper->timeout
1378 +                   && !del_timer(&expected->timeout))
1379 +                       goto end;       
1380  
1381 -       if (expected) {
1382                 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
1383                         conntrack, expected);
1384                 /* Welcome, Mr. Bond.  We've been expecting you... */
1385 +               IP_NF_ASSERT(master_ct(conntrack));
1386                 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1387                 conntrack->master = expected;
1388                 expected->sibling = conntrack;
1389                 LIST_DELETE(&ip_conntrack_expect_list, expected);
1390                 expected->expectant->expecting--;
1391                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1392 -       }
1393 -       atomic_inc(&ip_conntrack_count);
1394 +
1395 +               /* this is a braindead... --pablo */
1396 +               atomic_inc(&ip_conntrack_count);
1397 +               WRITE_UNLOCK(&ip_conntrack_lock);
1398 +
1399 +               if (expected->expectfn)
1400 +                       expected->expectfn(conntrack);
1401 +
1402 +               goto ret;
1403 +       } else 
1404 +               conntrack->helper = ip_ct_find_helper(&repl_tuple);
1405 +
1406 +end:   atomic_inc(&ip_conntrack_count);
1407         WRITE_UNLOCK(&ip_conntrack_lock);
1408  
1409 -       if (expected && expected->expectfn)
1410 -               expected->expectfn(conntrack);
1411 -       return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1412 +ret:   return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1413  }
1414  
1415  /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
1416 @@ -743,7 +668,8 @@
1417  
1418         IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
1419  
1420 -       if (!get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, &tuple, proto))
1421 +       if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, 
1422 +                               &tuple,proto))
1423                 return NULL;
1424  
1425         /* look for tuple match */
1426 @@ -828,10 +754,12 @@
1427  
1428         proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
1429  
1430 -       /* It may be an icmp error... */
1431 -       if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 
1432 -           && icmp_error_track(*pskb, &ctinfo, hooknum))
1433 -               return NF_ACCEPT;
1434 +       /* It may be an special packet, error, unclean...
1435 +        * inverse of the return code tells to the netfilter
1436 +        * core what to do with the packet. */
1437 +       if (proto->error != NULL 
1438 +           && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0)
1439 +               return -ret;
1440  
1441         if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
1442                 /* Not valid part of a connection */
1443 @@ -869,7 +797,8 @@
1444  int invert_tuplepr(struct ip_conntrack_tuple *inverse,
1445                    const struct ip_conntrack_tuple *orig)
1446  {
1447 -       return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
1448 +       return ip_ct_invert_tuple(inverse, orig, 
1449 +                                 ip_ct_find_proto(orig->dst.protonum));
1450  }
1451  
1452  static inline int resent_expect(const struct ip_conntrack_expect *i,
1453 @@ -923,9 +852,8 @@
1454  ip_conntrack_expect_alloc(void)
1455  {
1456         struct ip_conntrack_expect *new;
1457 -       
1458 -       new = (struct ip_conntrack_expect *)
1459 -               kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
1460 +
1461 +       new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
1462         if (!new) {
1463                 DEBUGP("expect_related: OOM allocating expect\n");
1464                 return NULL;
1465 @@ -933,6 +861,7 @@
1466  
1467         /* tuple_cmp compares whole union, we have to initialized cleanly */
1468         memset(new, 0, sizeof(struct ip_conntrack_expect));
1469 +       atomic_set(&new->use, 1);
1470  
1471         return new;
1472  }
1473 @@ -944,7 +873,6 @@
1474         DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
1475         new->expectant = related_to;
1476         new->sibling = NULL;
1477 -       atomic_set(&new->use, 1);
1478  
1479         /* add to expected list for this connection */
1480         list_add_tail(&new->expected_list, &related_to->sibling_list);
1481 @@ -997,7 +925,8 @@
1482                 }
1483  
1484                 WRITE_UNLOCK(&ip_conntrack_lock);
1485 -               kfree(expect);
1486 +               /* This expectation is not inserted so no need to lock */
1487 +               kmem_cache_free(ip_conntrack_expect_cachep, expect);
1488                 return -EEXIST;
1489  
1490         } else if (related_to->helper->max_expected && 
1491 @@ -1015,7 +944,7 @@
1492                                        related_to->helper->name,
1493                                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
1494                                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
1495 -                       kfree(expect);
1496 +                       kmem_cache_free(ip_conntrack_expect_cachep, expect);
1497                         return -EPERM;
1498                 }
1499                 DEBUGP("ip_conntrack: max number of expected "
1500 @@ -1049,7 +978,7 @@
1501                 WRITE_UNLOCK(&ip_conntrack_lock);
1502                 DEBUGP("expect_related: busy!\n");
1503  
1504 -               kfree(expect);
1505 +               kmem_cache_free(ip_conntrack_expect_cachep, expect);
1506                 return -EBUSY;
1507         }
1508  
1509 @@ -1164,21 +1093,39 @@
1510         synchronize_net();
1511  }
1512  
1513 -/* Refresh conntrack for this many jiffies. */
1514 -void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
1515 +static inline void ct_add_counters(struct ip_conntrack *ct,
1516 +                                  enum ip_conntrack_info ctinfo,
1517 +                                  const struct sk_buff *skb)
1518 +{
1519 +#ifdef CONFIG_IP_NF_CT_ACCT
1520 +       if (skb) {
1521 +               ct->counters[CTINFO2DIR(ctinfo)].packets++;
1522 +               ct->counters[CTINFO2DIR(ctinfo)].bytes += 
1523 +                                       ntohs(skb->nh.iph->tot_len);
1524 +       }
1525 +#endif
1526 +}
1527 +
1528 +/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */
1529 +void ip_ct_refresh_acct(struct ip_conntrack *ct, 
1530 +                       enum ip_conntrack_info ctinfo,
1531 +                       const struct sk_buff *skb,
1532 +                       unsigned long extra_jiffies)
1533  {
1534         IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
1535  
1536         /* If not in hash table, timer will not be active yet */
1537 -       if (!is_confirmed(ct))
1538 +       if (!is_confirmed(ct)) {
1539                 ct->timeout.expires = extra_jiffies;
1540 -       else {
1541 +               ct_add_counters(ct, ctinfo, skb);
1542 +       } else {
1543                 WRITE_LOCK(&ip_conntrack_lock);
1544                 /* Need del_timer for race avoidance (may already be dying). */
1545                 if (del_timer(&ct->timeout)) {
1546                         ct->timeout.expires = jiffies + extra_jiffies;
1547                         add_timer(&ct->timeout);
1548                 }
1549 +               ct_add_counters(ct, ctinfo, skb);
1550                 WRITE_UNLOCK(&ip_conntrack_lock);
1551         }
1552  }
1553 @@ -1368,6 +1315,7 @@
1554         }
1555  
1556         kmem_cache_destroy(ip_conntrack_cachep);
1557 +       kmem_cache_destroy(ip_conntrack_expect_cachep);
1558         vfree(ip_conntrack_hash);
1559         nf_unregister_sockopt(&so_getorigdst);
1560  }
1561 @@ -1420,6 +1368,15 @@
1562                 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
1563                 goto err_free_hash;
1564         }
1565 +
1566 +       ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
1567 +                                       sizeof(struct ip_conntrack_expect),
1568 +                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
1569 +       if (!ip_conntrack_expect_cachep) {
1570 +               printk(KERN_ERR "Unable to create ip_expect slab cache\n");
1571 +               goto err_free_conntrack_slab;
1572 +       }
1573 +
1574         /* Don't NEED lock here, but good form anyway. */
1575         WRITE_LOCK(&ip_conntrack_lock);
1576         /* Sew in builtin protocols. */
1577 @@ -1447,6 +1404,8 @@
1578  
1579         return ret;
1580  
1581 +err_free_conntrack_slab:
1582 +       kmem_cache_destroy(ip_conntrack_cachep);
1583  err_free_hash:
1584         vfree(ip_conntrack_hash);
1585  err_unreg_sockopt:
1586 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c
1587 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c     2004-09-07 12:07:46.565628632 +0200
1588 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-09-07 12:32:47.921387864 +0200
1589 @@ -50,9 +50,9 @@
1590  /* Returns verdict for packet, or -1 for invalid. */
1591  static int packet(struct ip_conntrack *conntrack,
1592                   const struct sk_buff *skb,
1593 -                 enum ip_conntrack_info conntrackinfo)
1594 +                 enum ip_conntrack_info ctinfo)
1595  {
1596 -       ip_ct_refresh(conntrack, ip_ct_generic_timeout);
1597 +       ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_generic_timeout);
1598         return NF_ACCEPT;
1599  }
1600  
1601 @@ -62,8 +62,14 @@
1602         return 1;
1603  }
1604  
1605 -struct ip_conntrack_protocol ip_conntrack_generic_protocol
1606 -= { { NULL, NULL }, 0, "unknown",
1607 -    generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
1608 -    generic_print_conntrack, packet, new, NULL, NULL, NULL };
1609 -
1610 +struct ip_conntrack_protocol ip_conntrack_generic_protocol =
1611 +{
1612 +       .proto                  = 0,
1613 +       .name                   = "unknown",
1614 +       .pkt_to_tuple           = generic_pkt_to_tuple,
1615 +       .invert_tuple           = generic_invert_tuple,
1616 +       .print_tuple            = generic_print_tuple,
1617 +       .print_conntrack        = generic_print_conntrack,
1618 +       .packet                 = packet,
1619 +       .new                    = new,
1620 +};
1621 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
1622 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c        2004-09-07 12:07:46.565628632 +0200
1623 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c    2004-09-07 12:32:47.930386496 +0200
1624 @@ -12,6 +12,11 @@
1625  #include <linux/netfilter.h>
1626  #include <linux/in.h>
1627  #include <linux/icmp.h>
1628 +#include <net/ip.h>
1629 +#include <net/checksum.h>
1630 +#include <linux/netfilter.h>
1631 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1632 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
1633  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
1634  
1635  unsigned long ip_ct_icmp_timeout = 30*HZ;
1636 @@ -94,7 +99,7 @@
1637                         ct->timeout.function((unsigned long)ct);
1638         } else {
1639                 atomic_inc(&ct->proto.icmp.count);
1640 -               ip_ct_refresh(ct, ip_ct_icmp_timeout);
1641 +               ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
1642         }
1643  
1644         return NF_ACCEPT;
1645 @@ -122,7 +127,147 @@
1646         return 1;
1647  }
1648  
1649 -struct ip_conntrack_protocol ip_conntrack_protocol_icmp
1650 -= { { NULL, NULL }, IPPROTO_ICMP, "icmp",
1651 -    icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
1652 -    icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
1653 +static int
1654 +icmp_error_message(struct sk_buff *skb,
1655 +                  enum ip_conntrack_info *ctinfo,
1656 +                  unsigned int hooknum)
1657 +{
1658 +       struct ip_conntrack_tuple innertuple, origtuple;
1659 +       struct {
1660 +               struct icmphdr icmp;
1661 +               struct iphdr ip;
1662 +       } inside;
1663 +       struct ip_conntrack_protocol *innerproto;
1664 +       struct ip_conntrack_tuple_hash *h;
1665 +       int dataoff;
1666 +
1667 +       IP_NF_ASSERT(skb->nfct == NULL);
1668 +
1669 +       /* Not enough header? */
1670 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
1671 +               return NF_ACCEPT;
1672 +
1673 +       /* Ignore ICMP's containing fragments (shouldn't happen) */
1674 +       if (inside.ip.frag_off & htons(IP_OFFSET)) {
1675 +               DEBUGP("icmp_error_track: fragment of proto %u\n",
1676 +                      inside.ip.protocol);
1677 +               return NF_ACCEPT;
1678 +       }
1679 +
1680 +       innerproto = ip_ct_find_proto(inside.ip.protocol);
1681 +       dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
1682 +       /* Are they talking about one of our connections? */
1683 +       if (!ip_ct_get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
1684 +               DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
1685 +               return NF_ACCEPT;
1686 +       }
1687 +
1688 +       /* Ordinarily, we'd expect the inverted tupleproto, but it's
1689 +          been preserved inside the ICMP. */
1690 +       if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
1691 +               DEBUGP("icmp_error_track: Can't invert tuple\n");
1692 +               return NF_ACCEPT;
1693 +       }
1694 +
1695 +       *ctinfo = IP_CT_RELATED;
1696 +
1697 +       h = ip_conntrack_find_get(&innertuple, NULL);
1698 +       if (!h) {
1699 +               /* Locally generated ICMPs will match inverted if they
1700 +                  haven't been SNAT'ed yet */
1701 +               /* FIXME: NAT code has to handle half-done double NAT --RR */
1702 +               if (hooknum == NF_IP_LOCAL_OUT)
1703 +                       h = ip_conntrack_find_get(&origtuple, NULL);
1704 +
1705 +               if (!h) {
1706 +                       DEBUGP("icmp_error_track: no match\n");
1707 +                       return NF_ACCEPT;
1708 +               }
1709 +               /* Reverse direction from that found */
1710 +               if (DIRECTION(h) != IP_CT_DIR_REPLY)
1711 +                       *ctinfo += IP_CT_IS_REPLY;
1712 +       } else {
1713 +               if (DIRECTION(h) == IP_CT_DIR_REPLY)
1714 +                       *ctinfo += IP_CT_IS_REPLY;
1715 +       }
1716 +
1717 +       /* Update skb to refer to this connection */
1718 +       skb->nfct = &h->ctrack->infos[*ctinfo];
1719 +       return -NF_ACCEPT;
1720 +}
1721 +
1722 +/* Small and modified version of icmp_rcv */
1723 +static int
1724 +icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
1725 +          unsigned int hooknum)
1726 +{
1727 +       struct icmphdr icmph;
1728 +
1729 +       /* Not enough header? */
1730 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph))!=0) {
1731 +               if (LOG_INVALID(IPPROTO_ICMP))
1732 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1733 +                                     "ip_ct_icmp: short packet ");
1734 +               return -NF_ACCEPT;
1735 +       }
1736 +
1737 +       /* See ip_conntrack_proto_tcp.c */
1738 +       if (hooknum != NF_IP_PRE_ROUTING)
1739 +               goto checksum_skipped;
1740 +
1741 +       switch (skb->ip_summed) {
1742 +       case CHECKSUM_HW:
1743 +               if (!(u16)csum_fold(skb->csum)) 
1744 +                       break;
1745 +               if (LOG_INVALID(IPPROTO_ICMP))
1746 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
1747 +                                     "ip_ct_icmp: bad HW ICMP checksum ");
1748 +               return -NF_ACCEPT;
1749 +       case CHECKSUM_NONE:
1750 +               if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
1751 +                       if (LOG_INVALID(IPPROTO_ICMP))
1752 +                               nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
1753 +                                             "ip_ct_icmp: bad ICMP checksum ");
1754 +                       return -NF_ACCEPT;
1755 +               }
1756 +       default:
1757 +               break;
1758 +       }
1759 +
1760 +checksum_skipped:
1761 +       /*
1762 +        *      18 is the highest 'known' ICMP type. Anything else is a mystery
1763 +        *
1764 +        *      RFC 1122: 3.2.2  Unknown ICMP messages types MUST be silently
1765 +        *                discarded.
1766 +        */
1767 +       if (icmph.type > NR_ICMP_TYPES) {
1768 +               if (LOG_INVALID(IPPROTO_ICMP))
1769 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1770 +                                     "ip_ct_icmp: invalid ICMP type ");
1771 +               return -NF_ACCEPT;
1772 +       }
1773 +
1774 +       /* Need to track icmp error message? */
1775 +       if (icmph.type != ICMP_DEST_UNREACH
1776 +           && icmph.type != ICMP_SOURCE_QUENCH
1777 +           && icmph.type != ICMP_TIME_EXCEEDED
1778 +           && icmph.type != ICMP_PARAMETERPROB
1779 +           && icmph.type != ICMP_REDIRECT)
1780 +               return NF_ACCEPT;
1781 +
1782 +       return icmp_error_message(skb, ctinfo, hooknum);
1783 +}
1784 +
1785 +struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
1786 +{
1787 +       .proto                  = IPPROTO_ICMP,
1788 +       .name                   = "icmp",
1789 +       .pkt_to_tuple           = icmp_pkt_to_tuple,
1790 +       .invert_tuple           = icmp_invert_tuple,
1791 +       .print_tuple            = icmp_print_tuple,
1792 +       .print_conntrack        = icmp_print_conntrack,
1793 +       .packet                 = icmp_packet,
1794 +       .new                    = icmp_new,
1795 +       .error                  = icmp_error,
1796 +};
1797 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
1798 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-09-07 12:07:46.566628480 +0200
1799 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c     2004-09-07 12:32:47.922387712 +0200
1800 @@ -225,7 +225,7 @@
1801                 set_bit(IPS_ASSURED_BIT, &conntrack->status);
1802  
1803  out:   WRITE_UNLOCK(&tcp_lock);
1804 -       ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
1805 +       ip_ct_refresh_acct(conntrack, ctinfo, skb, *tcp_timeouts[newconntrack]);
1806  
1807         return NF_ACCEPT;
1808  }
1809 @@ -268,7 +268,15 @@
1810         return between(exp->seq, ntohl(tcph.seq), ntohl(tcph.seq) + datalen);
1811  }
1812  
1813 -struct ip_conntrack_protocol ip_conntrack_protocol_tcp
1814 -= { { NULL, NULL }, IPPROTO_TCP, "tcp",
1815 -    tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
1816 -    tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
1817 +struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
1818 +{
1819 +       .proto                  = IPPROTO_TCP,
1820 +       .name                   = "tcp",
1821 +       .pkt_to_tuple           = tcp_pkt_to_tuple,
1822 +       .invert_tuple           = tcp_invert_tuple,
1823 +       .print_tuple            = tcp_print_tuple,
1824 +       .print_conntrack        = tcp_print_conntrack,
1825 +       .packet                 = tcp_packet,
1826 +       .new                    = tcp_new,
1827 +       .exp_matches_pkt        = tcp_exp_matches_pkt,
1828 +};
1829 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c
1830 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-09-07 12:07:46.565628632 +0200
1831 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c     2004-09-07 12:32:47.931386344 +0200
1832 @@ -12,6 +12,8 @@
1833  #include <linux/netfilter.h>
1834  #include <linux/in.h>
1835  #include <linux/udp.h>
1836 +#include <net/checksum.h>
1837 +#include <linux/netfilter.h>
1838  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
1839  
1840  unsigned long ip_ct_udp_timeout = 30*HZ;
1841 @@ -60,16 +62,17 @@
1842  /* Returns verdict for packet, and may modify conntracktype */
1843  static int udp_packet(struct ip_conntrack *conntrack,
1844                       const struct sk_buff *skb,
1845 -                     enum ip_conntrack_info conntrackinfo)
1846 +                     enum ip_conntrack_info ctinfo)
1847  {
1848         /* If we've seen traffic both ways, this is some kind of UDP
1849            stream.  Extend timeout. */
1850         if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
1851 -               ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
1852 +               ip_ct_refresh_acct(conntrack, ctinfo, skb, 
1853 +                                  ip_ct_udp_timeout_stream);
1854                 /* Also, more likely to be important, and not a probe */
1855                 set_bit(IPS_ASSURED_BIT, &conntrack->status);
1856         } else
1857 -               ip_ct_refresh(conntrack, ip_ct_udp_timeout);
1858 +               ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
1859  
1860         return NF_ACCEPT;
1861  }
1862 @@ -80,7 +83,60 @@
1863         return 1;
1864  }
1865  
1866 -struct ip_conntrack_protocol ip_conntrack_protocol_udp
1867 -= { { NULL, NULL }, IPPROTO_UDP, "udp",
1868 -    udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
1869 -    udp_packet, udp_new, NULL, NULL, NULL };
1870 +static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
1871 +                    unsigned int hooknum)
1872 +{
1873 +       struct iphdr *iph = skb->nh.iph;
1874 +       unsigned int udplen = skb->len - iph->ihl * 4;
1875 +       struct udphdr hdr;
1876 +
1877 +       /* Header is too small? */
1878 +       if (skb_copy_bits(skb, iph->ihl*4, &hdr, sizeof(hdr)) != 0) {
1879 +               if (LOG_INVALID(IPPROTO_UDP))
1880 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
1881 +                                 "ip_ct_udp: short packet ");
1882 +               return -NF_ACCEPT;
1883 +       }
1884 +       
1885 +       /* Truncated/malformed packets */
1886 +       if (ntohs(hdr.len) > udplen || ntohs(hdr.len) < sizeof(hdr)) {
1887 +               if (LOG_INVALID(IPPROTO_UDP))
1888 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
1889 +                                 "ip_ct_udp: truncated/malformed packet ");
1890 +               return -NF_ACCEPT;
1891 +       }
1892 +       
1893 +       /* Packet with no checksum */
1894 +       if (!hdr.check)
1895 +               return NF_ACCEPT;
1896 +
1897 +       /* Checksum invalid? Ignore.
1898 +        * We skip checking packets on the outgoing path
1899 +        * because the semantic of CHECKSUM_HW is different there 
1900 +        * and moreover root might send raw packets.
1901 +        * FIXME: Source route IP option packets --RR */
1902 +       if (hooknum == NF_IP_PRE_ROUTING
1903 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
1904 +                                skb->ip_summed == CHECKSUM_HW ? skb->csum
1905 +                                : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
1906 +               if (LOG_INVALID(IPPROTO_UDP))
1907 +                       nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
1908 +                                 "ip_ct_udp: bad UDP checksum ");
1909 +               return -NF_ACCEPT;
1910 +       }
1911 +       
1912 +       return NF_ACCEPT;
1913 +}
1914 +
1915 +struct ip_conntrack_protocol ip_conntrack_protocol_udp =
1916 +{
1917 +       .proto                  = IPPROTO_UDP,
1918 +       .name                   = "udp",
1919 +       .pkt_to_tuple           = udp_pkt_to_tuple,
1920 +       .invert_tuple           = udp_invert_tuple,
1921 +       .print_tuple            = udp_print_tuple,
1922 +       .print_conntrack        = udp_print_conntrack,
1923 +       .packet                 = udp_packet,
1924 +       .new                    = udp_new,
1925 +       .error                  = udp_error,
1926 +};
1927 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c
1928 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-09-07 12:07:46.565628632 +0200
1929 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-09-07 12:32:47.924387408 +0200
1930 @@ -20,6 +20,7 @@
1931  #include <linux/module.h>
1932  #include <linux/skbuff.h>
1933  #include <linux/proc_fs.h>
1934 +#include <linux/seq_file.h>
1935  #ifdef CONFIG_SYSCTL
1936  #include <linux/sysctl.h>
1937  #endif
1938 @@ -63,128 +64,225 @@
1939         return len;
1940  }
1941  
1942 -/* FIXME: Don't print source proto part. --RR */
1943 +#ifdef CONFIG_IP_NF_CT_ACCT
1944  static unsigned int
1945 -print_expect(char *buffer, const struct ip_conntrack_expect *expect)
1946 +seq_print_counters(struct seq_file *s, struct ip_conntrack_counter *counter)
1947  {
1948 -       unsigned int len;
1949 -
1950 -       if (expect->expectant->helper->timeout)
1951 -               len = sprintf(buffer, "EXPECTING: %lu ",
1952 -                             timer_pending(&expect->timeout)
1953 -                             ? (expect->timeout.expires - jiffies)/HZ : 0);
1954 -       else
1955 -               len = sprintf(buffer, "EXPECTING: - ");
1956 -       len += sprintf(buffer + len, "use=%u proto=%u ",
1957 -                     atomic_read(&expect->use), expect->tuple.dst.protonum);
1958 -       len += print_tuple(buffer + len, &expect->tuple,
1959 -                          __ip_ct_find_proto(expect->tuple.dst.protonum));
1960 -       len += sprintf(buffer + len, "\n");
1961 -       return len;
1962 +       return seq_printf(s, "packets=%llu bytes=%llu ",
1963 +                         counter->packets, counter->bytes);
1964  }
1965 +#else
1966 +#define seq_print_counters(x, y)       0
1967 +#endif
1968  
1969 -static unsigned int
1970 -print_conntrack(char *buffer, struct ip_conntrack *conntrack)
1971 +static void *ct_seq_start(struct seq_file *s, loff_t *pos)
1972  {
1973 -       unsigned int len;
1974 -       struct ip_conntrack_protocol *proto
1975 -               = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1976 -                              .tuple.dst.protonum);
1977 -
1978 -       len = sprintf(buffer, "%-8s %u %lu ",
1979 -                     proto->name,
1980 -                     conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1981 -                     .tuple.dst.protonum,
1982 -                     timer_pending(&conntrack->timeout)
1983 -                     ? (conntrack->timeout.expires - jiffies)/HZ : 0);
1984 +       unsigned int *bucket;
1985  
1986 -       len += proto->print_conntrack(buffer + len, conntrack);
1987 -       len += print_tuple(buffer + len,
1988 -                          &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1989 -                          proto);
1990 -       if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
1991 -               len += sprintf(buffer + len, "[UNREPLIED] ");
1992 -       len += print_tuple(buffer + len,
1993 -                          &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
1994 -                          proto);
1995 -       if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
1996 -               len += sprintf(buffer + len, "[ASSURED] ");
1997 -       len += sprintf(buffer + len, "use=%u ",
1998 -                      atomic_read(&conntrack->ct_general.use));
1999 -       len += sprintf(buffer + len, "\n");
2000 +       /* strange seq_file api calls stop even if we fail,
2001 +        * thus we need to grab lock since stop unlocks */
2002 +       READ_LOCK(&ip_conntrack_lock);
2003 +  
2004 +       if (*pos >= ip_conntrack_htable_size)
2005 +               return NULL;
2006  
2007 -       return len;
2008 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
2009 +       if (!bucket) {
2010 +               return ERR_PTR(-ENOMEM);
2011 +       }
2012 +  
2013 +       *bucket = *pos;
2014 +       return bucket;
2015  }
2016 +  
2017 +static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
2018 +{
2019 +       unsigned int *bucket = (unsigned int *) v;
2020  
2021 -/* Returns true when finished. */
2022 -static inline int
2023 -conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
2024 -                 char *buffer, off_t offset, off_t *upto,
2025 -                 unsigned int *len, unsigned int maxlen)
2026 +       *pos = ++(*bucket);
2027 +       if (*pos >= ip_conntrack_htable_size) {
2028 +               kfree(v);
2029 +               return NULL;
2030 +       }
2031 +       return bucket;
2032 +}
2033 +  
2034 +static void ct_seq_stop(struct seq_file *s, void *v)
2035  {
2036 -       unsigned int newlen;
2037 -       IP_NF_ASSERT(hash->ctrack);
2038 +       READ_UNLOCK(&ip_conntrack_lock);
2039 +}
2040 +
2041 +/* return 0 on success, 1 in case of error */
2042 +static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
2043 +                           struct seq_file *s)
2044 +{
2045 +       struct ip_conntrack *conntrack = hash->ctrack;
2046 +       struct ip_conntrack_protocol *proto;
2047 +       char buffer[IP_CT_PRINT_BUFLEN];
2048  
2049         MUST_BE_READ_LOCKED(&ip_conntrack_lock);
2050  
2051 -       /* Only count originals */
2052 +       IP_NF_ASSERT(conntrack);
2053 +
2054 +       /* we only want to print DIR_ORIGINAL */
2055         if (DIRECTION(hash))
2056                 return 0;
2057  
2058 -       if ((*upto)++ < offset)
2059 -               return 0;
2060 +       proto = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
2061 +                              .tuple.dst.protonum);
2062 +       IP_NF_ASSERT(proto);
2063  
2064 -       newlen = print_conntrack(buffer + *len, hash->ctrack);
2065 -       if (*len + newlen > maxlen)
2066 +       if (seq_printf(s, "%-8s %u %lu ",
2067 +                     proto->name,
2068 +                     conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
2069 +                     timer_pending(&conntrack->timeout)
2070 +                     ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
2071 +               return 1;
2072 +
2073 +       proto->print_conntrack(buffer, conntrack);
2074 +       if (seq_puts(s, buffer))
2075 +               return 1;
2076 +  
2077 +       print_tuple(buffer, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
2078 +                   proto);
2079 +
2080 +       if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
2081 +               return 1;
2082 +
2083 +       if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
2084 +               if (seq_printf(s, "[UNREPLIED] "))
2085 +                       return 1;
2086 +
2087 +       print_tuple(buffer, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
2088 +                   proto);
2089 +       if (seq_puts(s, buffer))
2090 +               return 1;
2091 +
2092 +       if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
2093 +               return 1;
2094 +
2095 +       if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
2096 +               if (seq_printf(s, "[ASSURED] "))
2097 +                       return 1;
2098 +
2099 +       if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
2100                 return 1;
2101 -       else *len += newlen;
2102  
2103         return 0;
2104  }
2105  
2106 -static int
2107 -list_conntracks(char *buffer, char **start, off_t offset, int length)
2108 +
2109 +static int ct_seq_show(struct seq_file *s, void *v)
2110  {
2111 -       unsigned int i;
2112 -       unsigned int len = 0;
2113 -       off_t upto = 0;
2114 -       struct list_head *e;
2115 +       unsigned int *bucket = (unsigned int *) v;
2116  
2117 -       READ_LOCK(&ip_conntrack_lock);
2118 -       /* Traverse hash; print originals then reply. */
2119 -       for (i = 0; i < ip_conntrack_htable_size; i++) {
2120 -               if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
2121 -                             struct ip_conntrack_tuple_hash *,
2122 -                             buffer, offset, &upto, &len, length))
2123 -                       goto finished;
2124 +       if (LIST_FIND(&ip_conntrack_hash[*bucket], ct_seq_real_show,
2125 +                     struct ip_conntrack_tuple_hash *, s)) {
2126 +               /* buffer was filled and unable to print that tuple */
2127 +               return 1;
2128         }
2129 +       return 0;
2130 +}
2131 +       
2132 +static struct seq_operations ct_seq_ops = {
2133 +       .start = ct_seq_start,
2134 +       .next  = ct_seq_next,
2135 +       .stop  = ct_seq_stop,
2136 +       .show  = ct_seq_show
2137 +};
2138 +  
2139 +static int ct_open(struct inode *inode, struct file *file)
2140 +{
2141 +       return seq_open(file, &ct_seq_ops);
2142 +}
2143  
2144 -       /* Now iterate through expecteds. */
2145 +static struct file_operations ct_file_ops = {
2146 +       .owner   = THIS_MODULE,
2147 +       .open    = ct_open,
2148 +       .read    = seq_read,
2149 +       .llseek  = seq_lseek,
2150 +       .release = seq_release
2151 +};
2152 +  
2153 +/* expects */
2154 +static void *exp_seq_start(struct seq_file *s, loff_t *pos)
2155 +{
2156 +       struct list_head *e = &ip_conntrack_expect_list;
2157 +       loff_t i;
2158 +
2159 +       /* strange seq_file api calls stop even if we fail,
2160 +        * thus we need to grab lock since stop unlocks */
2161 +       READ_LOCK(&ip_conntrack_lock);
2162         READ_LOCK(&ip_conntrack_expect_tuple_lock);
2163 -       list_for_each(e, &ip_conntrack_expect_list) {
2164 -               unsigned int last_len;
2165 -               struct ip_conntrack_expect *expect
2166 -                       = (struct ip_conntrack_expect *)e;
2167 -               if (upto++ < offset) continue;
2168 -
2169 -               last_len = len;
2170 -               len += print_expect(buffer + len, expect);
2171 -               if (len > length) {
2172 -                       len = last_len;
2173 -                       goto finished_expects;
2174 -               }
2175 +
2176 +       if (list_empty(e))
2177 +               return NULL;
2178 +
2179 +       for (i = 0; i <= *pos; i++) {
2180 +               e = e->next;
2181 +               if (e == &ip_conntrack_expect_list)
2182 +                       return NULL;
2183         }
2184 +       return e;
2185 +}
2186 +
2187 +static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
2188 +{
2189 +       struct list_head *e = v;
2190 +
2191 +       e = e->next;
2192 +
2193 +       if (e == &ip_conntrack_expect_list)
2194 +               return NULL;
2195 +
2196 +       return e;
2197 +}
2198  
2199 - finished_expects:
2200 +static void exp_seq_stop(struct seq_file *s, void *v)
2201 +{
2202         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
2203 - finished:
2204         READ_UNLOCK(&ip_conntrack_lock);
2205 +}
2206  
2207 -       /* `start' hack - see fs/proc/generic.c line ~165 */
2208 -       *start = (char *)((unsigned int)upto - offset);
2209 -       return len;
2210 +static int exp_seq_show(struct seq_file *s, void *v)
2211 +{
2212 +       struct ip_conntrack_expect *expect = v;
2213 +       char buffer[IP_CT_PRINT_BUFLEN];
2214 +
2215 +       if (expect->expectant->helper->timeout)
2216 +               seq_printf(s, "%lu ", timer_pending(&expect->timeout)
2217 +                          ? (expect->timeout.expires - jiffies)/HZ : 0);
2218 +       else
2219 +               seq_printf(s, "- ");
2220 +
2221 +       seq_printf(s, "use=%u proto=%u ", atomic_read(&expect->use),
2222 +                  expect->tuple.dst.protonum);
2223 +
2224 +       print_tuple(buffer, &expect->tuple,
2225 +                   __ip_ct_find_proto(expect->tuple.dst.protonum));
2226 +       return seq_printf(s, "%s\n", buffer);
2227  }
2228  
2229 +static struct seq_operations exp_seq_ops = {
2230 +       .start = exp_seq_start,
2231 +       .next = exp_seq_next,
2232 +       .stop = exp_seq_stop,
2233 +       .show = exp_seq_show
2234 +};
2235 +
2236 +static int exp_open(struct inode *inode, struct file *file)
2237 +{
2238 +       return seq_open(file, &exp_seq_ops);
2239 +}
2240 +  
2241 +static struct file_operations exp_file_ops = {
2242 +       .owner   = THIS_MODULE,
2243 +       .open    = exp_open,
2244 +       .read    = seq_read,
2245 +       .llseek  = seq_lseek,
2246 +       .release = seq_release
2247 +};
2248 +
2249  static unsigned int ip_confirm(unsigned int hooknum,
2250                                struct sk_buff **pskb,
2251                                const struct net_device *in,
2252 @@ -334,6 +432,11 @@
2253  /* From ip_conntrack_proto_icmp.c */
2254  extern unsigned long ip_ct_generic_timeout;
2255  
2256 +/* Log invalid packets of a given protocol */
2257 +unsigned int ip_ct_log_invalid = 0;
2258 +static int log_invalid_proto_min = 0;
2259 +static int log_invalid_proto_max = 255;
2260 +
2261  static struct ctl_table_header *ip_ct_sysctl_header;
2262  
2263  static ctl_table ip_ct_sysctl_table[] = {
2264 @@ -449,6 +552,17 @@
2265                 .mode           = 0644,
2266                 .proc_handler   = &proc_dointvec_jiffies,
2267         },
2268 +       {
2269 +               .ctl_name       = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
2270 +               .procname       = "ip_conntrack_log_invalid",
2271 +               .data           = &ip_ct_log_invalid,
2272 +               .maxlen         = sizeof(unsigned int),
2273 +               .mode           = 0644,
2274 +               .proc_handler   = &proc_dointvec_minmax,
2275 +               .strategy       = &sysctl_intvec,
2276 +               .extra1         = &log_invalid_proto_min,
2277 +               .extra2         = &log_invalid_proto_max,
2278 +       },
2279         { .ctl_name = 0 }
2280  };
2281  
2282 @@ -494,7 +608,7 @@
2283  #endif
2284  static int init_or_cleanup(int init)
2285  {
2286 -       struct proc_dir_entry *proc;
2287 +       struct proc_dir_entry *proc, *proc_exp;
2288         int ret = 0;
2289  
2290         if (!init) goto cleanup;
2291 @@ -503,14 +617,18 @@
2292         if (ret < 0)
2293                 goto cleanup_nothing;
2294  
2295 -       proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
2296 +       proc = proc_net_create("ip_conntrack", 0440, NULL);
2297         if (!proc) goto cleanup_init;
2298 -       proc->owner = THIS_MODULE;
2299 +       proc->proc_fops = &ct_file_ops;
2300 +
2301 +       proc_exp = proc_net_create("ip_conntrack_expect", 0440, NULL);
2302 +       if (!proc_exp) goto cleanup_proc;
2303 +       proc_exp->proc_fops = &exp_file_ops;
2304  
2305         ret = nf_register_hook(&ip_conntrack_defrag_ops);
2306         if (ret < 0) {
2307                 printk("ip_conntrack: can't register pre-routing defrag hook.\n");
2308 -               goto cleanup_proc;
2309 +               goto cleanup_proc_exp;
2310         }
2311         ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
2312         if (ret < 0) {
2313 @@ -562,6 +680,8 @@
2314         nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
2315   cleanup_defragops:
2316         nf_unregister_hook(&ip_conntrack_defrag_ops);
2317 +cleanup_proc_exp:
2318 +       proc_net_remove("ip_conntrack_exp");
2319   cleanup_proc:
2320         proc_net_remove("ip_conntrack");
2321   cleanup_init:
2322 @@ -638,7 +758,7 @@
2323  EXPORT_SYMBOL(ip_conntrack_helper_register);
2324  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
2325  EXPORT_SYMBOL(ip_ct_selective_cleanup);
2326 -EXPORT_SYMBOL(ip_ct_refresh);
2327 +EXPORT_SYMBOL(ip_ct_refresh_acct);
2328  EXPORT_SYMBOL(ip_ct_find_proto);
2329  EXPORT_SYMBOL(__ip_ct_find_proto);
2330  EXPORT_SYMBOL(ip_ct_find_helper);
2331 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c
2332 --- linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c      2004-09-07 12:07:46.566628480 +0200
2333 +++ linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c  2004-09-07 12:32:47.925387256 +0200
2334 @@ -31,6 +31,7 @@
2335  
2336  #include <linux/netfilter_ipv4/ip_conntrack.h>
2337  #include <linux/netfilter_ipv4/ip_conntrack_core.h>
2338 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2339  #include <linux/netfilter_ipv4/ip_nat.h>
2340  #include <linux/netfilter_ipv4/ip_nat_core.h>
2341  #include <linux/netfilter_ipv4/listhelp.h>
2342 @@ -144,7 +145,8 @@
2343         switch ((*pskb)->nh.iph->protocol) {
2344         case IPPROTO_ICMP:
2345                 /* ICMP errors. */
2346 -               ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
2347 +               protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
2348 +               ct = (struct ip_conntrack *)(*pskb)->nfct->master;
2349                 if (ct) {
2350                         /* We only do SNAT in the compatibility layer.
2351                            So we can manipulate ICMP errors from
2352 @@ -165,7 +167,8 @@
2353         case IPPROTO_UDP:
2354                 IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
2355  
2356 -               if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
2357 +               if (!ip_ct_get_tuple((*pskb)->nh.iph, *pskb,
2358 +                                    (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
2359                         if (net_ratelimit())
2360                                 printk("ip_fw_compat_masq: Can't get tuple\n");
2361                         return NF_ACCEPT;
2362 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.7/net/ipv4/netfilter/ip_nat_core.c
2363 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_core.c    2004-09-07 12:07:46.565628632 +0200
2364 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_core.c        2004-09-07 12:32:56.183131888 +0200
2365 @@ -49,7 +49,6 @@
2366  static struct list_head *bysource;
2367  static struct list_head *byipsproto;
2368  LIST_HEAD(protos);
2369 -LIST_HEAD(helpers);
2370  
2371  extern struct ip_nat_protocol unknown_nat_protocol;
2372  
2373 @@ -498,13 +497,6 @@
2374         return ret;
2375  }
2376  
2377 -static inline int
2378 -helper_cmp(const struct ip_nat_helper *helper,
2379 -          const struct ip_conntrack_tuple *tuple)
2380 -{
2381 -       return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
2382 -}
2383 -
2384  /* Where to manip the reply packets (will be reverse manip). */
2385  static unsigned int opposite_hook[NF_IP_NUMHOOKS]
2386  = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
2387 @@ -643,8 +635,7 @@
2388  
2389         /* If there's a helper, assign it; based on new tuple. */
2390         if (!conntrack->master)
2391 -               info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
2392 -                                        &reply);
2393 +               info->helper = ip_nat_find_helper(&reply);
2394  
2395         /* It's done. */
2396         info->initialized |= (1 << HOOK2MANIP(hooknum));
2397 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.7/net/ipv4/netfilter/ip_nat_helper.c
2398 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_helper.c  2004-09-07 12:07:46.565628632 +0200
2399 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_helper.c      2004-09-07 12:32:56.184131736 +0200
2400 @@ -47,6 +47,7 @@
2401  #define DUMP_OFFSET(x)
2402  #endif
2403  
2404 +static LIST_HEAD(helpers);
2405  DECLARE_LOCK(ip_nat_seqofs_lock);
2406  
2407  /* Setup TCP sequence correction given this change at this sequence */
2408 @@ -419,6 +420,18 @@
2409         return ret;
2410  }
2411  
2412 +struct ip_nat_helper *
2413 +ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
2414 +{
2415 +       struct ip_nat_helper *h;
2416 +
2417 +       READ_LOCK(&ip_nat_lock);
2418 +       h = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple);
2419 +       READ_UNLOCK(&ip_nat_lock);
2420 +
2421 +       return h;
2422 +}
2423 +
2424  static int
2425  kill_helper(const struct ip_conntrack *i, void *helper)
2426  {
2427 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_queue.c linux-2.6.7/net/ipv4/netfilter/ip_queue.c
2428 --- linux-2.6.7.org/net/ipv4/netfilter/ip_queue.c       2004-09-07 12:07:46.566628480 +0200
2429 +++ linux-2.6.7/net/ipv4/netfilter/ip_queue.c   2004-09-07 12:33:00.821426760 +0200
2430 @@ -255,9 +255,10 @@
2431                                 entry->skb->dev->hard_header_parse(entry->skb,
2432                                                                    pmsg->hw_addr);
2433         }
2434 -       
2435 -       if (data_len)
2436 -               memcpy(pmsg->payload, entry->skb->data, data_len);
2437 +
2438 +       if (data_len) 
2439 +               if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len) != 0)
2440 +                       goto nlmsg_failure;
2441                 
2442         nlh->nlmsg_len = skb->tail - old_tail;
2443         return skb;
2444 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
2445 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      1970-01-01 01:00:00.000000000 +0100
2446 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  2004-09-07 12:33:07.424422952 +0200
2447 @@ -0,0 +1,89 @@
2448 +/**
2449 + * Strip all IP options in the IP packet header.
2450 + *
2451 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
2452 + * This software is distributed under GNU GPL v2, 1991
2453 + */
2454 +
2455 +#include <linux/module.h>
2456 +#include <linux/skbuff.h>
2457 +#include <net/ip.h>
2458 +#include <net/checksum.h>
2459 +
2460 +#include <linux/netfilter_ipv4/ip_tables.h>
2461 +
2462 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
2463 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
2464 +MODULE_LICENSE("GPL");
2465 +
2466 +static unsigned int
2467 +target(struct sk_buff **pskb,
2468 +       const struct net_device *in,
2469 +       const struct net_device *out,
2470 +       unsigned int hooknum,
2471 +       const void *targinfo,
2472 +       void *userinfo)
2473 +{
2474 +       struct iphdr *iph;
2475 +       struct sk_buff *skb;
2476 +       struct ip_options *opt;
2477 +       unsigned char *optiph;
2478 +       int l;
2479 +       
2480 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
2481 +               return NF_DROP;
2482
2483 +       skb = (*pskb);
2484 +       iph = (*pskb)->nh.iph;
2485 +       optiph = skb->nh.raw;
2486 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
2487 +
2488 +       /* if no options in packet then nothing to clear. */
2489 +       if (iph->ihl * 4 == sizeof(struct iphdr))
2490 +               return IPT_CONTINUE;
2491 +
2492 +       /* else clear all options */
2493 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
2494 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
2495 +       opt = &(IPCB(skb)->opt);
2496 +       opt->is_data = 0;
2497 +       opt->optlen = l;
2498 +
2499 +       skb->nfcache |= NFC_ALTERED;
2500 +
2501 +        return IPT_CONTINUE;
2502 +}
2503 +
2504 +static int
2505 +checkentry(const char *tablename,
2506 +          const struct ipt_entry *e,
2507 +           void *targinfo,
2508 +           unsigned int targinfosize,
2509 +           unsigned int hook_mask)
2510 +{
2511 +       if (strcmp(tablename, "mangle")) {
2512 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
2513 +               return 0;
2514 +       }
2515 +       /* nothing else to check because no parameters */
2516 +       return 1;
2517 +}
2518 +
2519 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
2520 +       .name = "IPV4OPTSSTRIP",
2521 +       .target = target,
2522 +       .checkentry = checkentry,
2523 +       .me = THIS_MODULE };
2524 +
2525 +static int __init init(void)
2526 +{
2527 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
2528 +}
2529 +
2530 +static void __exit fini(void)
2531 +{
2532 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
2533 +}
2534 +
2535 +module_init(init);
2536 +module_exit(fini);
2537 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_LOG.c linux-2.6.7/net/ipv4/netfilter/ipt_LOG.c
2538 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_LOG.c        2004-09-07 12:07:46.566628480 +0200
2539 +++ linux-2.6.7/net/ipv4/netfilter/ipt_LOG.c    2004-09-07 12:32:38.740783528 +0200
2540 @@ -76,7 +76,7 @@
2541                 printk("FRAG:%u ", ntohs(iph.frag_off) & IP_OFFSET);
2542  
2543         if ((info->logflags & IPT_LOG_IPOPT)
2544 -           && iph.ihl * 4 != sizeof(struct iphdr)) {
2545 +           && iph.ihl * 4 > sizeof(struct iphdr)) {
2546                 unsigned char opt[4 * 15 - sizeof(struct iphdr)];
2547                 unsigned int i, optsize;
2548  
2549 @@ -143,7 +143,7 @@
2550                 printk("URGP=%u ", ntohs(tcph.urg_ptr));
2551  
2552                 if ((info->logflags & IPT_LOG_TCPOPT)
2553 -                   && tcph.doff * 4 != sizeof(struct tcphdr)) {
2554 +                   && tcph.doff * 4 > sizeof(struct tcphdr)) {
2555                         unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
2556                         unsigned int i, optsize;
2557  
2558 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c
2559 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c        1970-01-01 01:00:00.000000000 +0100
2560 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c    2004-09-07 12:33:09.041177168 +0200
2561 @@ -0,0 +1,120 @@
2562 +/* TTL modification target for IP tables
2563 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
2564 + *
2565 + * Version: $Revision$
2566 + *
2567 + * This software is distributed under the terms of GNU GPL
2568 + */
2569 +
2570 +#include <linux/module.h>
2571 +#include <linux/skbuff.h>
2572 +#include <linux/ip.h>
2573 +#include <net/checksum.h>
2574 +
2575 +#include <linux/netfilter_ipv4/ip_tables.h>
2576 +#include <linux/netfilter_ipv4/ipt_TTL.h>
2577 +
2578 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
2579 +MODULE_DESCRIPTION("IP tables TTL modification module");
2580 +MODULE_LICENSE("GPL");
2581 +
2582 +static unsigned int 
2583 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 
2584 +               const struct net_device *out, unsigned int hooknum, 
2585 +               const void *targinfo, void *userinfo)
2586 +{
2587 +       struct iphdr *iph;
2588 +       const struct ipt_TTL_info *info = targinfo;
2589 +       u_int16_t diffs[2];
2590 +       int new_ttl;
2591 +
2592 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
2593 +               return NF_DROP;
2594 +
2595 +       iph = (*pskb)->nh.iph;
2596 +                        
2597 +       switch (info->mode) {
2598 +               case IPT_TTL_SET:
2599 +                       new_ttl = info->ttl;
2600 +                       break;
2601 +               case IPT_TTL_INC:
2602 +                       new_ttl = iph->ttl + info->ttl;
2603 +                       if (new_ttl > 255)
2604 +                               new_ttl = 255;
2605 +                       break;
2606 +               case IPT_TTL_DEC:
2607 +                       new_ttl = iph->ttl - info->ttl;
2608 +                       if (new_ttl < 0)
2609 +                               new_ttl = 0;
2610 +                       break;
2611 +               default:
2612 +                       new_ttl = iph->ttl;
2613 +                       break;
2614 +       }
2615 +
2616 +       if (new_ttl != iph->ttl) {
2617 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
2618 +               iph->ttl = new_ttl;
2619 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
2620 +               iph->check = csum_fold(csum_partial((char *)diffs,
2621 +                                                   sizeof(diffs),
2622 +                                                   iph->check^0xFFFF));
2623 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
2624 +       }
2625 +
2626 +       return IPT_CONTINUE;
2627 +}
2628 +
2629 +static int ipt_ttl_checkentry(const char *tablename,
2630 +               const struct ipt_entry *e,
2631 +               void *targinfo,
2632 +               unsigned int targinfosize,
2633 +               unsigned int hook_mask)
2634 +{
2635 +       struct ipt_TTL_info *info = targinfo;
2636 +
2637 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
2638 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
2639 +                               targinfosize,
2640 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
2641 +               return 0;       
2642 +       }       
2643 +
2644 +       if (strcmp(tablename, "mangle")) {
2645 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
2646 +               return 0;
2647 +       }
2648 +
2649 +       if (info->mode > IPT_TTL_MAXMODE) {
2650 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
2651 +                       info->mode);
2652 +               return 0;
2653 +       }
2654 +
2655 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
2656 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
2657 +               return 0;
2658 +       }
2659 +       
2660 +       return 1;
2661 +}
2662 +
2663 +static struct ipt_target ipt_TTL = { 
2664 +       .name = "TTL",
2665 +       .target = ipt_ttl_target, 
2666 +       .checkentry = ipt_ttl_checkentry, 
2667 +       .me = THIS_MODULE 
2668 +};
2669 +
2670 +static int __init init(void)
2671 +{
2672 +       return ipt_register_target(&ipt_TTL);
2673 +}
2674 +
2675 +static void __exit fini(void)
2676 +{
2677 +       ipt_unregister_target(&ipt_TTL);
2678 +}
2679 +
2680 +module_init(init);
2681 +module_exit(fini);
2682 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_connlimit.c
2683 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_connlimit.c  1970-01-01 01:00:00.000000000 +0100
2684 +++ linux-2.6.7/net/ipv4/netfilter/ipt_connlimit.c      2004-09-07 12:33:10.091017568 +0200
2685 @@ -0,0 +1,230 @@
2686 +/*
2687 + * netfilter module to limit the number of parallel tcp
2688 + * connections per IP address.
2689 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
2690 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
2691 + *             only ignore TIME_WAIT or gone connections
2692 + *
2693 + * based on ...
2694 + *
2695 + * Kernel module to match connection tracking information.
2696 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
2697 + */
2698 +#include <linux/module.h>
2699 +#include <linux/skbuff.h>
2700 +#include <linux/list.h>
2701 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2702 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2703 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
2704 +#include <linux/netfilter_ipv4/ip_tables.h>
2705 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
2706 +
2707 +#define DEBUG 0
2708 +
2709 +MODULE_LICENSE("GPL");
2710 +
2711 +/* we'll save the tuples of all connections we care about */
2712 +struct ipt_connlimit_conn
2713 +{
2714 +        struct list_head list;
2715 +       struct ip_conntrack_tuple tuple;
2716 +};
2717 +
2718 +struct ipt_connlimit_data {
2719 +       spinlock_t lock;
2720 +       struct list_head iphash[256];
2721 +};
2722 +
2723 +static int ipt_iphash(u_int32_t addr)
2724 +{
2725 +       int hash;
2726 +
2727 +       hash  =  addr        & 0xff;
2728 +       hash ^= (addr >>  8) & 0xff;
2729 +       hash ^= (addr >> 16) & 0xff;
2730 +       hash ^= (addr >> 24) & 0xff;
2731 +       return hash;
2732 +}
2733 +
2734 +static int count_them(struct ipt_connlimit_data *data,
2735 +                     u_int32_t addr, u_int32_t mask,
2736 +                     struct ip_conntrack *ct)
2737 +{
2738 +#if DEBUG
2739 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
2740 +                                    "fin_wait", "time_wait", "close", "close_wait",
2741 +                                    "last_ack", "listen" };
2742 +#endif
2743 +       int addit = 1, matches = 0;
2744 +       struct ip_conntrack_tuple tuple;
2745 +       struct ip_conntrack_tuple_hash *found;
2746 +       struct ipt_connlimit_conn *conn;
2747 +       struct list_head *hash,*lh;
2748 +
2749 +       spin_lock(&data->lock);
2750 +       tuple = ct->tuplehash[0].tuple;
2751 +       hash = &data->iphash[ipt_iphash(addr & mask)];
2752 +
2753 +       /* check the saved connections */
2754 +       for (lh = hash->next; lh != hash; lh = lh->next) {
2755 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
2756 +               found = ip_conntrack_find_get(&conn->tuple,ct);
2757 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
2758 +                   found != NULL &&
2759 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
2760 +                       /* Just to be sure we have it only once in the list.
2761 +                          We should'nt see tuples twice unless someone hooks this
2762 +                          into a table without "-p tcp --syn" */
2763 +                       addit = 0;
2764 +               }
2765 +#if DEBUG
2766 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
2767 +                      ipt_iphash(addr & mask),
2768 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
2769 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
2770 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
2771 +#endif
2772 +               if (NULL == found) {
2773 +                       /* this one is gone */
2774 +                       lh = lh->prev;
2775 +                       list_del(lh->next);
2776 +                       kfree(conn);
2777 +                       continue;
2778 +               }
2779 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
2780 +                       /* we don't care about connections which are
2781 +                          closed already -> ditch it */
2782 +                       lh = lh->prev;
2783 +                       list_del(lh->next);
2784 +                       kfree(conn);
2785 +                       nf_conntrack_put(&found->ctrack->infos[0]);
2786 +                       continue;
2787 +               }
2788 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
2789 +                       /* same source IP address -> be counted! */
2790 +                       matches++;
2791 +               }
2792 +               nf_conntrack_put(&found->ctrack->infos[0]);
2793 +       }
2794 +       if (addit) {
2795 +               /* save the new connection in our list */
2796 +#if DEBUG
2797 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
2798 +                      ipt_iphash(addr & mask),
2799 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
2800 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
2801 +#endif
2802 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
2803 +               if (NULL == conn)
2804 +                       return -1;
2805 +               memset(conn,0,sizeof(*conn));
2806 +               INIT_LIST_HEAD(&conn->list);
2807 +               conn->tuple = tuple;
2808 +               list_add(&conn->list,hash);
2809 +               matches++;
2810 +       }
2811 +       spin_unlock(&data->lock);
2812 +       return matches;
2813 +}
2814 +
2815 +static int
2816 +match(const struct sk_buff *skb,
2817 +      const struct net_device *in,
2818 +      const struct net_device *out,
2819 +      const void *matchinfo,
2820 +      int offset,
2821 +      int *hotdrop)
2822 +{
2823 +       const struct ipt_connlimit_info *info = matchinfo;
2824 +       int connections, match;
2825 +       struct ip_conntrack *ct;
2826 +       enum ip_conntrack_info ctinfo;
2827 +
2828 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2829 +       if (NULL == ct) {
2830 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
2831 +               *hotdrop = 1;
2832 +               return 0;
2833 +       }
2834 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
2835 +       if (-1 == connections) {
2836 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
2837 +               *hotdrop = 1; /* let's free some memory :-) */
2838 +               return 0;
2839 +       }
2840 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
2841 +#if DEBUG
2842 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
2843 +              "connections=%d limit=%d match=%s\n",
2844 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
2845 +              connections, info->limit, match ? "yes" : "no");
2846 +#endif
2847 +
2848 +       return match;
2849 +}
2850 +
2851 +static int check(const char *tablename,
2852 +                const struct ipt_ip *ip,
2853 +                void *matchinfo,
2854 +                unsigned int matchsize,
2855 +                unsigned int hook_mask)
2856 +{
2857 +       struct ipt_connlimit_info *info = matchinfo;
2858 +       int i;
2859 +
2860 +       /* verify size */
2861 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
2862 +               return 0;
2863 +
2864 +       /* refuse anything but tcp */
2865 +       if (ip->proto != IPPROTO_TCP)
2866 +               return 0;
2867 +
2868 +       /* init private data */
2869 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
2870 +       spin_lock_init(&(info->data->lock));
2871 +       for (i = 0; i < 256; i++)
2872 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
2873 +       
2874 +       return 1;
2875 +}
2876 +
2877 +static void destroy(void *matchinfo, unsigned int matchinfosize)
2878 +{
2879 +       struct ipt_connlimit_info *info = matchinfo;
2880 +       struct ipt_connlimit_conn *conn;
2881 +       struct list_head *hash;
2882 +       int i;
2883 +
2884 +       /* cleanup */
2885 +       for (i = 0; i < 256; i++) {
2886 +               hash = &(info->data->iphash[i]);
2887 +               while (hash != hash->next) {
2888 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
2889 +                       list_del(hash->next);
2890 +                       kfree(conn);
2891 +               }
2892 +       }
2893 +       kfree(info->data);
2894 +}
2895 +
2896 +static struct ipt_match connlimit_match = { 
2897 +       .name = "connlimit",
2898 +       .match = &match,
2899 +       .checkentry = &check,
2900 +       .destroy = &destroy,
2901 +       .me = THIS_MODULE
2902 +};
2903 +
2904 +static int __init init(void)
2905 +{
2906 +       return ipt_register_match(&connlimit_match);
2907 +}
2908 +
2909 +static void __exit fini(void)
2910 +{
2911 +       ipt_unregister_match(&connlimit_match);
2912 +}
2913 +
2914 +module_init(init);
2915 +module_exit(fini);
2916 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c
2917 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c   1970-01-01 01:00:00.000000000 +0100
2918 +++ linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c       2004-09-07 12:33:11.098864352 +0200
2919 @@ -0,0 +1,690 @@
2920 +/* iptables match extension to limit the number of packets per second
2921 + * seperately for each destination.
2922 + *
2923 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2924 + *
2925 + * $Id$
2926 + *
2927 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2928 + *
2929 + * based on ipt_limit.c by:
2930 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
2931 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
2932 + * Rusty Russell       <rusty@rustcorp.com.au>
2933 + *
2934 + * The general idea is to create a hash table for every dstip and have a
2935 + * seperate limit counter per tuple.  This way you can do something like 'limit
2936 + * the number of syn packets for each of my internal addresses.
2937 + *
2938 + * Ideally this would just be implemented as a general 'hash' match, which would
2939 + * allow us to attach any iptables target to it's hash buckets.  But this is
2940 + * not possible in the current iptables architecture.  As always, pkttables for
2941 + * 2.7.x will help ;)
2942 + */
2943 +#include <linux/module.h>
2944 +#include <linux/skbuff.h>
2945 +#include <linux/spinlock.h>
2946 +#include <linux/random.h>
2947 +#include <linux/jhash.h>
2948 +#include <linux/slab.h>
2949 +#include <linux/vmalloc.h>
2950 +#include <linux/tcp.h>
2951 +#include <linux/udp.h>
2952 +#include <linux/proc_fs.h>
2953 +#include <linux/seq_file.h>
2954 +
2955 +#define ASSERT_READ_LOCK(x) 
2956 +#define ASSERT_WRITE_LOCK(x) 
2957 +#include <linux/netfilter_ipv4/lockhelp.h>
2958 +#include <linux/netfilter_ipv4/listhelp.h>
2959 +
2960 +#include <linux/netfilter_ipv4/ip_tables.h>
2961 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2962 +
2963 +/* FIXME: this is just for IP_NF_ASSERRT */
2964 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2965 +
2966 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2967 +
2968 +MODULE_LICENSE("GPL");
2969 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2970 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2971 +
2972 +/* need to declare this at the top */
2973 +static struct proc_dir_entry *dstlimit_procdir;
2974 +static struct file_operations dl_file_ops;
2975 +
2976 +/* hash table crap */
2977 +
2978 +struct dsthash_dst {
2979 +       u_int32_t src_ip;
2980 +       u_int32_t dst_ip;
2981 +       u_int16_t port;
2982 +};
2983 +
2984 +struct dsthash_ent {
2985 +       /* static / read-only parts in the beginning */
2986 +       struct list_head list;
2987 +       struct dsthash_dst dst;
2988 +
2989 +       /* modified structure members in the end */
2990 +       unsigned long expires;          /* precalculated expiry time */
2991 +       struct {
2992 +               unsigned long prev;     /* last modification */
2993 +               u_int32_t credit;
2994 +               u_int32_t credit_cap, cost;
2995 +       } rateinfo;
2996 +};
2997 +
2998 +struct ipt_dstlimit_htable {
2999 +       struct list_head list;          /* global list of all htables */
3000 +       atomic_t use;
3001 +
3002 +       struct dstlimit_cfg cfg;        /* config */
3003 +
3004 +       /* used internally */
3005 +       spinlock_t lock;                /* lock for list_head */
3006 +       u_int32_t rnd;                  /* random seed for hash */
3007 +       struct timer_list timer;        /* timer for gc */
3008 +       atomic_t count;                 /* number entries in table */
3009 +
3010 +       /* seq_file stuff */
3011 +       struct proc_dir_entry *pde;
3012 +
3013 +       struct list_head hash[0];       /* hashtable itself */
3014 +};
3015 +
3016 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
3017 +static LIST_HEAD(dstlimit_htables);
3018 +static kmem_cache_t *dstlimit_cachep;
3019 +
3020 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
3021 +{
3022 +       return (ent->dst.dst_ip == b->dst_ip 
3023 +               && ent->dst.port == b->port
3024 +               && ent->dst.src_ip == b->src_ip);
3025 +}
3026 +
3027 +static inline u_int32_t
3028 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
3029 +{
3030 +       return (jhash_3words(dst->dst_ip, dst->port, 
3031 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
3032 +}
3033 +
3034 +static inline struct dsthash_ent *
3035 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
3036 +{
3037 +       struct dsthash_ent *ent;
3038 +       u_int32_t hash = hash_dst(ht, dst);
3039 +       MUST_BE_LOCKED(&ht->lock);
3040 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
3041 +       return ent;
3042 +}
3043 +
3044 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
3045 +static struct dsthash_ent *
3046 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
3047 +{
3048 +       struct dsthash_ent *ent;
3049 +
3050 +       /* initialize hash with random val at the time we allocate
3051 +        * the first hashtable entry */
3052 +       if (!ht->rnd)
3053 +               get_random_bytes(&ht->rnd, 4);
3054 +
3055 +       if (ht->cfg.max &&
3056 +           atomic_read(&ht->count) >= ht->cfg.max) {
3057 +               /* FIXME: do something. question is what.. */
3058 +               if (net_ratelimit())
3059 +                       printk(KERN_WARNING 
3060 +                               "ipt_dstlimit: max count of %u reached\n", 
3061 +                               ht->cfg.max);
3062 +               return NULL;
3063 +       }
3064 +
3065 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
3066 +       if (!ent) {
3067 +               if (net_ratelimit())
3068 +                       printk(KERN_ERR 
3069 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
3070 +               return NULL;
3071 +       }
3072 +
3073 +       atomic_inc(&ht->count);
3074 +
3075 +       ent->dst.dst_ip = dst->dst_ip;
3076 +       ent->dst.port = dst->port;
3077 +       ent->dst.src_ip = dst->src_ip;
3078 +
3079 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
3080 +
3081 +       return ent;
3082 +}
3083 +
3084 +static inline void 
3085 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
3086 +{
3087 +       MUST_BE_LOCKED(&ht->lock);
3088 +
3089 +       list_del(&ent->list);
3090 +       kmem_cache_free(dstlimit_cachep, ent);
3091 +       atomic_dec(&ht->count);
3092 +}
3093 +static void htable_gc(unsigned long htlong);
3094 +
3095 +static int htable_create(struct ipt_dstlimit_info *minfo)
3096 +{
3097 +       int i;
3098 +       unsigned int size;
3099 +       struct ipt_dstlimit_htable *hinfo;
3100 +
3101 +       if (minfo->cfg.size)
3102 +               size = minfo->cfg.size;
3103 +       else {
3104 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
3105 +                        / sizeof(struct list_head));
3106 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
3107 +                       size = 8192;
3108 +               if (size < 16)
3109 +                       size = 16;
3110 +       }
3111 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
3112 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
3113 +                       + (sizeof(struct list_head) * size));
3114 +       if (!hinfo) {
3115 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
3116 +               return -1;
3117 +       }
3118 +       minfo->hinfo = hinfo;
3119 +
3120 +       /* copy match config into hashtable config */
3121 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
3122 +       hinfo->cfg.size = size;
3123 +       if (!hinfo->cfg.max)
3124 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
3125 +       else if (hinfo->cfg.max < hinfo->cfg.size)
3126 +               hinfo->cfg.max = hinfo->cfg.size;
3127 +
3128 +       for (i = 0; i < hinfo->cfg.size; i++)
3129 +               INIT_LIST_HEAD(&hinfo->hash[i]);
3130 +
3131 +       atomic_set(&hinfo->count, 0);
3132 +       atomic_set(&hinfo->use, 1);
3133 +       hinfo->rnd = 0;
3134 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
3135 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
3136 +       if (!hinfo->pde) {
3137 +               vfree(hinfo);
3138 +               return -1;
3139 +       }
3140 +       hinfo->pde->proc_fops = &dl_file_ops;
3141 +       hinfo->pde->data = hinfo;
3142 +
3143 +       init_timer(&hinfo->timer);
3144 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
3145 +       hinfo->timer.data = (unsigned long )hinfo;
3146 +       hinfo->timer.function = htable_gc;
3147 +       add_timer(&hinfo->timer);
3148 +
3149 +       WRITE_LOCK(&dstlimit_lock);
3150 +       list_add(&hinfo->list, &dstlimit_htables);
3151 +       WRITE_UNLOCK(&dstlimit_lock);
3152 +
3153 +       return 0;
3154 +}
3155 +
3156 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
3157 +{
3158 +       return 1;
3159 +}
3160 +
3161 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
3162 +{
3163 +       return (jiffies >= he->expires);
3164 +}
3165 +
3166 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
3167 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
3168 +                                             struct dsthash_ent *he))
3169 +{
3170 +       int i;
3171 +
3172 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
3173 +
3174 +       /* lock hash table and iterate over it */
3175 +       LOCK_BH(&ht->lock);
3176 +       for (i = 0; i < ht->cfg.size; i++) {
3177 +               struct dsthash_ent *dh, *n;
3178 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
3179 +                       if ((*select)(ht, dh))
3180 +                               __dsthash_free(ht, dh);
3181 +               }
3182 +       }
3183 +       UNLOCK_BH(&ht->lock);
3184 +}
3185 +
3186 +/* hash table garbage collector, run by timer */
3187 +static void htable_gc(unsigned long htlong)
3188 +{
3189 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
3190 +
3191 +       htable_selective_cleanup(ht, select_gc);
3192 +
3193 +       /* re-add the timer accordingly */
3194 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
3195 +       add_timer(&ht->timer);
3196 +}
3197 +
3198 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
3199 +{
3200 +       /* remove timer, if it is pending */
3201 +       if (timer_pending(&hinfo->timer))
3202 +               del_timer(&hinfo->timer);
3203 +
3204 +       /* remove proc entry */
3205 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
3206 +
3207 +       htable_selective_cleanup(hinfo, select_all);
3208 +       vfree(hinfo);
3209 +}
3210 +
3211 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
3212 +{
3213 +       struct ipt_dstlimit_htable *hinfo;
3214 +
3215 +       READ_LOCK(&dstlimit_lock);
3216 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
3217 +               if (!strcmp(name, hinfo->pde->name)) {
3218 +                       atomic_inc(&hinfo->use);
3219 +                       READ_UNLOCK(&dstlimit_lock);
3220 +                       return hinfo;
3221 +               }
3222 +       }
3223 +       READ_UNLOCK(&dstlimit_lock);
3224 +
3225 +       return NULL;
3226 +}
3227 +
3228 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
3229 +{
3230 +       if (atomic_dec_and_test(&hinfo->use)) {
3231 +               WRITE_LOCK(&dstlimit_lock);
3232 +               list_del(&hinfo->list);
3233 +               WRITE_UNLOCK(&dstlimit_lock);
3234 +               htable_destroy(hinfo);
3235 +       }
3236 +}
3237 +
3238 +
3239 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
3240 + * see net/sched/sch_tbf.c in the linux source tree
3241 + */
3242 +
3243 +/* Rusty: This is my (non-mathematically-inclined) understanding of
3244 +   this algorithm.  The `average rate' in jiffies becomes your initial
3245 +   amount of credit `credit' and the most credit you can ever have
3246 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
3247 +   test, `cost'.
3248 +
3249 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
3250 +   If you get credit balance more than this, the extra credit is
3251 +   discarded.  Every time the match passes, you lose `cost' credits;
3252 +   if you don't have that many, the test fails.
3253 +
3254 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
3255 +
3256 +   To get the maximum range, we multiply by this factor (ie. you get N
3257 +   credits per jiffy).  We want to allow a rate as low as 1 per day
3258 +   (slowest userspace tool allows), which means
3259 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
3260 +*/
3261 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
3262 +
3263 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
3264 + * us the power of 2 below the theoretical max, so GCC simply does a
3265 + * shift. */
3266 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
3267 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
3268 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
3269 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
3270 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
3271 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
3272 +
3273 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
3274 +
3275 +/* Precision saver. */
3276 +static inline u_int32_t
3277 +user2credits(u_int32_t user)
3278 +{
3279 +       /* If multiplying would overflow... */
3280 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
3281 +               /* Divide first. */
3282 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
3283 +
3284 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
3285 +}
3286 +
3287 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
3288 +{
3289 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
3290 +                                       * CREDITS_PER_JIFFY;
3291 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
3292 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
3293 +}
3294 +
3295 +static int
3296 +dstlimit_match(const struct sk_buff *skb,
3297 +               const struct net_device *in,
3298 +               const struct net_device *out,
3299 +               const void *matchinfo,
3300 +               int offset,
3301 +               int *hotdrop)
3302 +{
3303 +       struct ipt_dstlimit_info *r = 
3304 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
3305 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
3306 +       unsigned long now = jiffies;
3307 +       struct dsthash_ent *dh;
3308 +       struct dsthash_dst dst;
3309 +
3310 +       memset(&dst, 0, sizeof(dst));
3311 +
3312 +       /* dest ip is always in hash */
3313 +       dst.dst_ip = skb->nh.iph->daddr;
3314 +
3315 +       /* source ip only if respective hashmode, otherwise set to
3316 +        * zero */
3317 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
3318 +               dst.src_ip = skb->nh.iph->saddr;
3319 +
3320 +       /* dest port only if respective mode */
3321 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
3322 +               u16 ports[2];
3323 +
3324 +               /* Must not be a fragment. */
3325 +               if (offset)
3326 +                       return 0;
3327 +
3328 +               /* Must be big enough to read ports (both UDP and TCP have
3329 +                  them at the start). */
3330 +               if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
3331 +                       /* We've been asked to examine this packet, and we
3332 +                          can't.  Hence, no choice but to drop. */
3333 +                       *hotdrop = 1;
3334 +                       return 0;
3335 +               }
3336 +
3337 +               switch (skb->nh.iph->protocol) {
3338 +                       struct tcphdr *th;
3339 +                       struct udphdr *uh;
3340 +               case IPPROTO_TCP:
3341 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
3342 +                       dst.port = th->dest;
3343 +                       break;
3344 +               case IPPROTO_UDP:
3345 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
3346 +                       dst.port = uh->dest;
3347 +                       break;
3348 +               default:
3349 +                       break;
3350 +               }
3351 +       } 
3352 +
3353 +       LOCK_BH(&hinfo->lock);
3354 +       dh = __dsthash_find(hinfo, &dst);
3355 +       if (!dh) {
3356 +               dh = __dsthash_alloc_init(hinfo, &dst);
3357 +
3358 +               if (!dh) {
3359 +                       /* enomem... don't match == DROP */
3360 +                       if (net_ratelimit())
3361 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
3362 +                       UNLOCK_BH(&hinfo->lock);
3363 +                       return 0;
3364 +               }
3365 +
3366 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
3367 +
3368 +               dh->rateinfo.prev = jiffies;
3369 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
3370 +                                                       hinfo->cfg.burst);
3371 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
3372 +                                                       hinfo->cfg.burst);
3373 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
3374 +
3375 +               UNLOCK_BH(&hinfo->lock);
3376 +               return 1;
3377 +       }
3378 +
3379 +       /* update expiration timeout */
3380 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
3381 +
3382 +       rateinfo_recalc(dh, now);
3383 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
3384 +               /* We're underlimit. */
3385 +               dh->rateinfo.credit -= dh->rateinfo.cost;
3386 +               UNLOCK_BH(&hinfo->lock);
3387 +               return 1;
3388 +       }
3389 +
3390 +               UNLOCK_BH(&hinfo->lock);
3391 +
3392 +       /* default case: we're overlimit, thus don't match */
3393 +       return 0;
3394 +}
3395 +
3396 +static int
3397 +dstlimit_checkentry(const char *tablename,
3398 +                    const struct ipt_ip *ip,
3399 +                    void *matchinfo,
3400 +                    unsigned int matchsize,
3401 +                    unsigned int hook_mask)
3402 +{
3403 +       struct ipt_dstlimit_info *r = matchinfo;
3404 +
3405 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
3406 +               return 0;
3407 +
3408 +       /* Check for overflow. */
3409 +       if (r->cfg.burst == 0
3410 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
3411 +                                       user2credits(r->cfg.avg)) {
3412 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
3413 +                      r->cfg.avg, r->cfg.burst);
3414 +               return 0;
3415 +       }
3416 +
3417 +       if (r->cfg.mode == 0 
3418 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
3419 +                         |IPT_DSTLIMIT_HASH_DIP
3420 +                         |IPT_DSTLIMIT_HASH_SIP))
3421 +               return 0;
3422 +
3423 +       if (!r->cfg.gc_interval)
3424 +               return 0;
3425 +       
3426 +       if (!r->cfg.expire)
3427 +               return 0;
3428 +
3429 +       r->hinfo = htable_find_get(r->name);
3430 +       if (!r->hinfo && (htable_create(r) != 0)) {
3431 +               return 0;
3432 +       }
3433 +
3434 +       /* Ugly hack: For SMP, we only want to use one set */
3435 +       r->u.master = r;
3436 +
3437 +       return 1;
3438 +}
3439 +
3440 +static void
3441 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
3442 +{
3443 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
3444 +
3445 +       htable_put(r->hinfo);
3446 +}
3447 +
3448 +static struct ipt_match ipt_dstlimit = { 
3449 +       .list = { .prev = NULL, .next = NULL }, 
3450 +       .name = "dstlimit", 
3451 +       .match = dstlimit_match, 
3452 +       .checkentry = dstlimit_checkentry, 
3453 +       .destroy = dstlimit_destroy,
3454 +       .me = THIS_MODULE 
3455 +};
3456 +
3457 +/* PROC stuff */
3458 +
3459 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
3460 +{
3461 +       struct proc_dir_entry *pde = s->private;
3462 +       struct ipt_dstlimit_htable *htable = pde->data;
3463 +       unsigned int *bucket;
3464 +
3465 +       LOCK_BH(&htable->lock);
3466 +       if (*pos >= htable->cfg.size)
3467 +               return NULL;
3468 +
3469 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
3470 +       if (!bucket)
3471 +               return ERR_PTR(-ENOMEM);
3472 +
3473 +       *bucket = *pos;
3474 +       return bucket;
3475 +}
3476 +
3477 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
3478 +{
3479 +       struct proc_dir_entry *pde = s->private;
3480 +       struct ipt_dstlimit_htable *htable = pde->data;
3481 +       unsigned int *bucket = (unsigned int *)v;
3482 +
3483 +       *pos = ++(*bucket);
3484 +       if (*pos >= htable->cfg.size) {
3485 +               kfree(v);
3486 +               return NULL;
3487 +       }
3488 +       return bucket;
3489 +}
3490 +
3491 +static void dl_seq_stop(struct seq_file *s, void *v)
3492 +{
3493 +       struct proc_dir_entry *pde = s->private;
3494 +       struct ipt_dstlimit_htable *htable = pde->data;
3495 +       unsigned int *bucket = (unsigned int *)v;
3496 +
3497 +       kfree(bucket);
3498 +
3499 +       UNLOCK_BH(&htable->lock);
3500 +}
3501 +
3502 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
3503 +{
3504 +       /* recalculate to show accurate numbers */
3505 +       rateinfo_recalc(ent, jiffies);
3506 +
3507 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
3508 +                       (ent->expires - jiffies)/HZ,
3509 +                       NIPQUAD(ent->dst.src_ip),
3510 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
3511 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
3512 +                       ent->rateinfo.cost);
3513 +}
3514 +
3515 +static int dl_seq_show(struct seq_file *s, void *v)
3516 +{
3517 +       struct proc_dir_entry *pde = s->private;
3518 +       struct ipt_dstlimit_htable *htable = pde->data;
3519 +       unsigned int *bucket = (unsigned int *)v;
3520 +
3521 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
3522 +                     struct dsthash_ent *, s)) {
3523 +               /* buffer was filled and unable to print that tuple */
3524 +               return 1;
3525 +       }
3526 +       return 0;
3527 +}
3528 +
3529 +static struct seq_operations dl_seq_ops = {
3530 +       .start = dl_seq_start,
3531 +       .next  = dl_seq_next,
3532 +       .stop  = dl_seq_stop,
3533 +       .show  = dl_seq_show
3534 +};
3535 +
3536 +static int dl_proc_open(struct inode *inode, struct file *file)
3537 +{
3538 +       int ret = seq_open(file, &dl_seq_ops);
3539 +
3540 +       if (!ret) {
3541 +               struct seq_file *sf = file->private_data;
3542 +               sf->private = PDE(inode);
3543 +       }
3544 +       return ret;
3545 +}
3546 +
3547 +static struct file_operations dl_file_ops = {
3548 +       .owner   = THIS_MODULE,
3549 +       .open    = dl_proc_open,
3550 +       .read    = seq_read,
3551 +       .llseek  = seq_lseek,
3552 +       .release = seq_release
3553 +};
3554 +
3555 +static int init_or_fini(int fini)
3556 +{
3557 +       int ret = 0;
3558 +
3559 +       if (fini)
3560 +               goto cleanup;
3561 +
3562 +       if (ipt_register_match(&ipt_dstlimit)) {
3563 +               ret = -EINVAL;
3564 +               goto cleanup_nothing;
3565 +       }
3566 +
3567 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
3568 +        * quite small ? */
3569 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
3570 +                                           sizeof(struct dsthash_ent), 0,
3571 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
3572 +       if (!dstlimit_cachep) {
3573 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
3574 +               ret = -ENOMEM;
3575 +               goto cleanup_unreg_match;
3576 +       }
3577 +
3578 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
3579 +       if (!dstlimit_procdir) {
3580 +               printk(KERN_ERR "Unable to create proc dir entry\n");
3581 +               ret = -ENOMEM;
3582 +               goto cleanup_free_slab;
3583 +       }
3584 +
3585 +       return ret;
3586 +
3587 +cleanup:
3588 +       remove_proc_entry("ipt_dstlimit", proc_net);
3589 +cleanup_free_slab:
3590 +       kmem_cache_destroy(dstlimit_cachep);
3591 +cleanup_unreg_match:
3592 +       ipt_unregister_match(&ipt_dstlimit);
3593 +cleanup_nothing:
3594 +       return ret;
3595 +       
3596 +}
3597 +
3598 +static int __init init(void)
3599 +{
3600 +       return init_or_fini(0);
3601 +}
3602 +
3603 +static void __exit fini(void)
3604 +{
3605 +       init_or_fini(1);
3606 +}
3607 +
3608 +module_init(init);
3609 +module_exit(fini);
3610 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c
3611 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c      1970-01-01 01:00:00.000000000 +0100
3612 +++ linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c  2004-09-07 12:33:12.080715088 +0200
3613 @@ -0,0 +1,185 @@
3614 +/*
3615 + *  This module implements a simple TSK FLC 
3616 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
3617 + * to limit , in an adaptive and flexible way , the packet rate crossing 
3618 + * a given stream . It serves as an initial and very simple (but effective)
3619 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
3620 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
3621 + * into our code in a precise , adaptive and efficient manner. 
3622 + *  The goal is very similar to that of "limit" match , but using techniques of
3623 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
3624 + * avoiding over and undershoots - and stuff like that .
3625 + *
3626 + *
3627 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
3628 + * 2002-08-17  : Changed to eliminate floating point operations .
3629 + * 2002-08-23  : Coding style changes .
3630 +*/
3631 +
3632 +#include <linux/module.h>
3633 +#include <linux/skbuff.h>
3634 +#include <linux/ip.h>
3635 +#include <linux/random.h>
3636 +#include <net/tcp.h>
3637 +#include <linux/spinlock.h>
3638 +#include <linux/netfilter_ipv4/ip_tables.h>
3639 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
3640 +
3641 +/*
3642 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
3643 + Expressed in percentage
3644 +*/
3645 +
3646 +#define PAR_LOW                1/100
3647 +#define PAR_HIGH       1
3648 +
3649 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
3650 +
3651 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
3652 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
3653 +MODULE_LICENSE("GPL");
3654 +
3655 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3656 +{
3657 +       if (tx >= maxi)
3658 +               return 100;
3659 +
3660 +       if (tx <= mini)
3661 +               return 0;
3662 +
3663 +       return ( (100*(tx-mini)) / (maxi-mini) );
3664 +}
3665 +
3666 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3667 +{
3668 +       if (tx <= mini)
3669 +               return 100;
3670 +
3671 +       if (tx >= maxi)
3672 +               return 0;
3673 +
3674 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
3675 +}
3676 +
3677 +static int
3678 +ipt_fuzzy_match(const struct sk_buff *pskb,
3679 +              const struct net_device *in,
3680 +              const struct net_device *out,
3681 +              const void *matchinfo,
3682 +              int offset,
3683 +              int *hotdrop)
3684 +{
3685 +       /* From userspace */
3686 +       
3687 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
3688 +
3689 +       u_int8_t random_number;
3690 +       unsigned long amount;
3691 +       u_int8_t howhigh, howlow;
3692 +       
3693 +
3694 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
3695 +
3696 +       info->bytes_total += pskb->len;
3697 +       info->packets_total++;
3698 +
3699 +       info->present_time = jiffies;
3700 +       
3701 +       if (info->present_time >= info->previous_time)
3702 +               amount = info->present_time - info->previous_time;
3703 +       else { 
3704 +               /* There was a transition : I choose to re-sample 
3705 +                  and keep the old acceptance rate...
3706 +               */
3707 +
3708 +               amount = 0;
3709 +               info->previous_time = info->present_time;
3710 +               info->bytes_total = info->packets_total = 0;
3711 +       };
3712 +       
3713 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
3714 +       {
3715 +
3716 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
3717 +                                       / amount );
3718 +
3719 +               info->previous_time = info->present_time;
3720 +               info->bytes_total = info->packets_total = 0;
3721 +
3722 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
3723 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
3724 +
3725 +               info->acceptance_rate = (u_int8_t) \
3726 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
3727 +
3728 +               /* In fact , the above defuzzification would require a denominator
3729 +                  proportional to (howhigh+howlow) but , in this particular case ,
3730 +                  that expression is constant .
3731 +                  An imediate consequence is that it isn't necessary to call 
3732 +                  both mf_high and mf_low - but to keep things understandable ,
3733 +                  I did so .  */ 
3734 +
3735 +       }
3736 +       
3737 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
3738 +
3739 +
3740 +       if ( info->acceptance_rate < 100 )
3741 +       {                
3742 +               get_random_bytes((void *)(&random_number), 1);
3743 +
3744 +               /*  If within the acceptance , it can pass => don't match */
3745 +               if (random_number <= (255 * info->acceptance_rate) / 100)
3746 +                       return 0;
3747 +               else
3748 +                       return 1; /* It can't pass ( It matches ) */
3749 +       } ;
3750 +
3751 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
3752 +       
3753 +}
3754 +
3755 +static int
3756 +ipt_fuzzy_checkentry(const char *tablename,
3757 +                  const struct ipt_ip *e,
3758 +                  void *matchinfo,
3759 +                  unsigned int matchsize,
3760 +                  unsigned int hook_mask)
3761 +{
3762 +       
3763 +       const struct ipt_fuzzy_info *info = matchinfo;
3764 +
3765 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
3766 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
3767 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
3768 +               return 0;
3769 +       }
3770 +
3771 +       if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
3772 +           || (info->minimum_rate >= info->maximum_rate )) {
3773 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
3774 +               return 0;
3775 +       }
3776 +
3777 +       return 1;
3778 +}
3779 +
3780 +static struct ipt_match ipt_fuzzy_reg = { 
3781 +       .name = "fuzzy",
3782 +       .match = ipt_fuzzy_match,
3783 +       .checkentry = ipt_fuzzy_checkentry,
3784 +       .me = THIS_MODULE
3785 +};
3786 +
3787 +static int __init init(void)
3788 +{
3789 +       return ipt_register_match(&ipt_fuzzy_reg);
3790 +}
3791 +
3792 +static void __exit fini(void)
3793 +{
3794 +       ipt_unregister_match(&ipt_fuzzy_reg);
3795 +}
3796 +
3797 +module_init(init);
3798 +module_exit(fini);
3799 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c
3800 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c        1970-01-01 01:00:00.000000000 +0100
3801 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c    2004-09-07 12:33:15.334220480 +0200
3802 @@ -0,0 +1,172 @@
3803 +/*
3804 +  This is a module which is used to match ipv4 options.
3805 +  This file is distributed under the terms of the GNU General Public
3806 +  License (GPL). Copies of the GPL can be obtained from:
3807 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
3808 +
3809 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
3810 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
3811 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
3812 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
3813 +  19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
3814 +*/
3815 +
3816 +#include <linux/module.h>
3817 +#include <linux/skbuff.h>
3818 +#include <net/ip.h>
3819 +
3820 +#include <linux/netfilter_ipv4/ip_tables.h>
3821 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
3822 +
3823 +MODULE_LICENSE("GPL");
3824 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3825 +
3826 +static int
3827 +match(const struct sk_buff *skb,
3828 +      const struct net_device *in,
3829 +      const struct net_device *out,
3830 +      const void *matchinfo,
3831 +      int offset,
3832 +      int *hotdrop)
3833 +{
3834 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3835 +       const struct iphdr *iph = skb->nh.iph;
3836 +       const struct ip_options *opt;
3837 +
3838 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
3839 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
3840 +
3841 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
3842 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3843 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3844 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3845 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3846 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
3847 +                       return 0;
3848 +               return 1;
3849 +       }
3850 +       else {
3851 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
3852 +                       /* there are options, and we don't need to care which one */
3853 +                       return 1;
3854 +               else {
3855 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
3856 +                               /* there are options but we don't want any ! */
3857 +                               return 0;
3858 +               }
3859 +       }
3860 +
3861 +       opt = &(IPCB(skb)->opt);
3862 +
3863 +       /* source routing */
3864 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
3865 +               if (!((opt->srr) & (opt->is_strictroute)))
3866 +                       return 0;
3867 +       }
3868 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
3869 +               if (!((opt->srr) & (!opt->is_strictroute)))
3870 +                       return 0;
3871 +       }
3872 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
3873 +               if (opt->srr)
3874 +                       return 0;
3875 +       }
3876 +       /* record route */
3877 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
3878 +               if (!opt->rr)
3879 +                       return 0;
3880 +       }
3881 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
3882 +               if (opt->rr)
3883 +                       return 0;
3884 +       }
3885 +       /* timestamp */
3886 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
3887 +               if (!opt->ts)
3888 +                       return 0;
3889 +       }
3890 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3891 +               if (opt->ts)
3892 +                       return 0;
3893 +       }
3894 +       /* router-alert option  */
3895 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3896 +               if (!opt->router_alert)
3897 +                       return 0;
3898 +       }
3899 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3900 +               if (opt->router_alert)
3901 +                       return 0;
3902 +       }
3903 +
3904 +       /* we match ! */
3905 +       return 1;
3906 +}
3907 +
3908 +static int
3909 +checkentry(const char *tablename,
3910 +          const struct ipt_ip *ip,
3911 +          void *matchinfo,
3912 +          unsigned int matchsize,
3913 +          unsigned int hook_mask)
3914 +{
3915 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3916 +       /* Check the size */
3917 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
3918 +               return 0;
3919 +       /* Now check the coherence of the data ... */
3920 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
3921 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
3922 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
3923 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
3924 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
3925 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
3926 +               return 0; /* opposites */
3927 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
3928 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3929 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3930 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3931 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3932 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
3933 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
3934 +               return 0; /* opposites */
3935 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
3936 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
3937 +               return 0; /* cannot match in the same time loose and strict source routing */
3938 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3939 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
3940 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
3941 +               return 0; /* opposites */
3942 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
3943 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
3944 +               return 0; /* opposites */
3945 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
3946 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
3947 +               return 0; /* opposites */
3948 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
3949 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
3950 +               return 0; /* opposites */
3951 +
3952 +       /* everything looks ok. */
3953 +       return 1;
3954 +}
3955 +
3956 +static struct ipt_match ipv4options_match = { 
3957 +       .name = "ipv4options",
3958 +       .match = match,
3959 +       .checkentry = checkentry,
3960 +       .me = THIS_MODULE
3961 +};
3962 +
3963 +static int __init init(void)
3964 +{
3965 +       return ipt_register_match(&ipv4options_match);
3966 +}
3967 +
3968 +static void __exit fini(void)
3969 +{
3970 +       ipt_unregister_match(&ipv4options_match);
3971 +}
3972 +
3973 +module_init(init);
3974 +module_exit(fini);
3975 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.7/net/ipv4/netfilter/ipt_mport.c
3976 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c      1970-01-01 01:00:00.000000000 +0100
3977 +++ linux-2.6.7/net/ipv4/netfilter/ipt_mport.c  2004-09-07 12:33:16.384060880 +0200
3978 @@ -0,0 +1,116 @@
3979 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
3980 +   the same place so we can treat them as equal. */
3981 +#include <linux/module.h>
3982 +#include <linux/types.h>
3983 +#include <linux/udp.h>
3984 +#include <linux/skbuff.h>
3985 +
3986 +#include <linux/netfilter_ipv4/ipt_mport.h>
3987 +#include <linux/netfilter_ipv4/ip_tables.h>
3988 +
3989 +MODULE_LICENSE("GPL");
3990 +
3991 +#if 0
3992 +#define duprintf(format, args...) printk(format , ## args)
3993 +#else
3994 +#define duprintf(format, args...)
3995 +#endif
3996 +
3997 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3998 +static inline int
3999 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
4000 +{
4001 +       unsigned int i;
4002 +        unsigned int m;
4003 +        u_int16_t pflags = minfo->pflags;
4004 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
4005 +                u_int16_t s, e;
4006 +
4007 +                if (pflags & m
4008 +                    && minfo->ports[i] == 65535)
4009 +                        return 0;
4010 +
4011 +                s = minfo->ports[i];
4012 +
4013 +                if (pflags & m) {
4014 +                        e = minfo->ports[++i];
4015 +                        m <<= 1;
4016 +                } else
4017 +                        e = s;
4018 +
4019 +                if (minfo->flags & IPT_MPORT_SOURCE
4020 +                    && src >= s && src <= e)
4021 +                        return 1;
4022 +
4023 +               if (minfo->flags & IPT_MPORT_DESTINATION
4024 +                   && dst >= s && dst <= e)
4025 +                       return 1;
4026 +       }
4027 +
4028 +       return 0;
4029 +}
4030 +
4031 +static int
4032 +match(const struct sk_buff *skb,
4033 +      const struct net_device *in,
4034 +      const struct net_device *out,
4035 +      const void *matchinfo,
4036 +      int offset,
4037 +      int *hotdrop)
4038 +{
4039 +       u16 ports[2];
4040 +       const struct ipt_mport *minfo = matchinfo;
4041 +
4042 +       if (offset)
4043 +               return 0;
4044 +
4045 +       /* Must be big enough to read ports (both UDP and TCP have
4046 +           them at the start). */
4047 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
4048 +               /* We've been asked to examine this packet, and we
4049 +                  can't.  Hence, no choice but to drop. */
4050 +                       duprintf("ipt_multiport:"
4051 +                                " Dropping evil offset=0 tinygram.\n");
4052 +                       *hotdrop = 1;
4053 +                       return 0;
4054 +       }
4055 +
4056 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
4057 +}
4058 +
4059 +/* Called when user tries to insert an entry of this type. */
4060 +static int
4061 +checkentry(const char *tablename,
4062 +          const struct ipt_ip *ip,
4063 +          void *matchinfo,
4064 +          unsigned int matchsize,
4065 +          unsigned int hook_mask)
4066 +{
4067 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
4068 +               return 0;
4069 +
4070 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
4071 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
4072 +               && !(ip->invflags & IPT_INV_PROTO)
4073 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
4074 +}
4075 +
4076 +static struct ipt_match mport_match = { 
4077 +       .name = "mport",
4078 +       .match = &match,
4079 +       .checkentry = &checkentry,
4080 +       .me = THIS_MODULE
4081 +};
4082 +
4083 +static int __init init(void)
4084 +{
4085 +       return ipt_register_match(&mport_match);
4086 +}
4087 +
4088 +static void __exit fini(void)
4089 +{
4090 +       ipt_unregister_match(&mport_match);
4091 +}
4092 +
4093 +module_init(init);
4094 +module_exit(fini);
4095 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.7/net/ipv4/netfilter/ipt_nth.c
4096 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c        1970-01-01 01:00:00.000000000 +0100
4097 +++ linux-2.6.7/net/ipv4/netfilter/ipt_nth.c    2004-09-07 12:33:17.547883952 +0200
4098 @@ -0,0 +1,166 @@
4099 +/*
4100 +  This is a module which is used for match support for every Nth packet
4101 +  This file is distributed under the terms of the GNU General Public
4102 +  License (GPL). Copies of the GPL can be obtained from:
4103 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
4104 +
4105 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
4106 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
4107 +        * added support for multiple counters
4108 +        * added support for matching on individual packets
4109 +          in the counter cycle
4110 +  2004-02-19 Harald Welte <laforge@netfilter.org>
4111 +       * port to 2.6.x
4112 +
4113 +*/
4114 +
4115 +#include <linux/module.h>
4116 +#include <linux/skbuff.h>
4117 +#include <linux/ip.h>
4118 +#include <net/tcp.h>
4119 +#include <linux/spinlock.h>
4120 +#include <linux/netfilter_ipv4/ip_tables.h>
4121 +#include <linux/netfilter_ipv4/ipt_nth.h>
4122 +
4123 +MODULE_LICENSE("GPL");
4124 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
4125 +
4126 +/*
4127 + * State information.
4128 + */
4129 +struct state {
4130 +       spinlock_t lock;
4131 +       u_int16_t number;
4132 +};
4133 +
4134 +static struct state states[IPT_NTH_NUM_COUNTERS];
4135 +
4136 +static int
4137 +ipt_nth_match(const struct sk_buff *pskb,
4138 +             const struct net_device *in,
4139 +             const struct net_device *out,
4140 +             const void *matchinfo,
4141 +             int offset,
4142 +             int *hotdrop)
4143 +{
4144 +       /* Parameters from userspace */
4145 +       const struct ipt_nth_info *info = matchinfo;
4146 +        unsigned counter = info->counter;
4147 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
4148 +       {
4149 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
4150 +               return 0;
4151 +        };
4152 +
4153 +        spin_lock(&states[counter].lock);
4154 +
4155 +        /* Are we matching every nth packet?*/
4156 +        if (info->packet == 0xFF)
4157 +        {
4158 +               /* We're matching every nth packet and only every nth packet*/
4159 +               /* Do we match or invert match? */
4160 +               if (info->not == 0)
4161 +               {
4162 +                       if (states[counter].number == 0)
4163 +                       {
4164 +                               ++states[counter].number;
4165 +                               goto match;
4166 +                       }
4167 +                       if (states[counter].number >= info->every)
4168 +                               states[counter].number = 0; /* reset the counter */
4169 +                       else
4170 +                               ++states[counter].number;
4171 +                       goto dontmatch;
4172 +               }
4173 +               else
4174 +               {
4175 +                       if (states[counter].number == 0)
4176 +                       {
4177 +                               ++states[counter].number;
4178 +                               goto dontmatch;
4179 +                       }
4180 +                       if (states[counter].number >= info->every)
4181 +                               states[counter].number = 0;
4182 +                       else
4183 +                               ++states[counter].number;
4184 +                       goto match;
4185 +               }
4186 +        }
4187 +        else
4188 +        {
4189 +               /* We're using the --packet, so there must be a rule for every value */
4190 +               if (states[counter].number == info->packet)
4191 +               {
4192 +                       /* only increment the counter when a match happens */
4193 +                       if (states[counter].number >= info->every)
4194 +                               states[counter].number = 0; /* reset the counter */
4195 +                       else
4196 +                               ++states[counter].number;
4197 +                       goto match;
4198 +               }
4199 +               else
4200 +                       goto dontmatch;
4201 +       }
4202 +
4203 + dontmatch:
4204 +       /* don't match */
4205 +       spin_unlock(&states[counter].lock);
4206 +       return 0;
4207 +
4208 + match:
4209 +       spin_unlock(&states[counter].lock);
4210 +       return 1;
4211 +}
4212 +
4213 +static int
4214 +ipt_nth_checkentry(const char *tablename,
4215 +                  const struct ipt_ip *e,
4216 +                  void *matchinfo,
4217 +                  unsigned int matchsize,
4218 +                  unsigned int hook_mask)
4219 +{
4220 +       /* Parameters from userspace */
4221 +       const struct ipt_nth_info *info = matchinfo;
4222 +        unsigned counter = info->counter;
4223 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
4224 +       {
4225 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
4226 +                       return 0;
4227 +               };
4228 +
4229 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
4230 +               printk("nth: matchsize %u != %u\n", matchsize,
4231 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
4232 +               return 0;
4233 +       }
4234 +
4235 +       states[counter].number = info->startat;
4236 +
4237 +       return 1;
4238 +}
4239 +
4240 +static struct ipt_match ipt_nth_reg = { 
4241 +       .name = "nth",
4242 +       .match = ipt_nth_match,
4243 +       .checkentry = ipt_nth_checkentry,
4244 +       .me = THIS_MODULE
4245 +};
4246 +
4247 +static int __init init(void)
4248 +{
4249 +       unsigned counter;
4250 +
4251 +       memset(&states, 0, sizeof(states));
4252 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
4253 +               spin_lock_init(&(states[counter].lock));
4254 +
4255 +       return ipt_register_match(&ipt_nth_reg);
4256 +}
4257 +
4258 +static void __exit fini(void)
4259 +{
4260 +       ipt_unregister_match(&ipt_nth_reg);
4261 +}
4262 +
4263 +module_init(init);
4264 +module_exit(fini);
4265 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.7/net/ipv4/netfilter/ipt_osf.c
4266 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c        1970-01-01 01:00:00.000000000 +0100
4267 +++ linux-2.6.7/net/ipv4/netfilter/ipt_osf.c    2004-09-07 12:33:18.674712648 +0200
4268 @@ -0,0 +1,873 @@
4269 +/*
4270 + * ipt_osf.c
4271 + *
4272 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
4273 + *
4274 + *
4275 + * This program is free software; you can redistribute it and/or modify
4276 + * it under the terms of the GNU General Public License as published by
4277 + * the Free Software Foundation; either version 2 of the License, or
4278 + * (at your option) any later version.
4279 + *
4280 + * This program is distributed in the hope that it will be useful,
4281 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4282 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4283 + * GNU General Public License for more details.
4284 + *
4285 + * You should have received a copy of the GNU General Public License
4286 + * along with this program; if not, write to the Free Software
4287 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4288 + */
4289 +
4290 +/*
4291 + * OS fingerprint matching module.
4292 + * It simply compares various parameters from SYN packet with
4293 + * some hardcoded ones.
4294 + *
4295 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
4296 + * for his p0f.
4297 + */
4298 +
4299 +#include <linux/config.h>
4300 +#include <linux/kernel.h>
4301 +#include <linux/types.h>
4302 +#include <linux/string.h>
4303 +#include <linux/smp.h>
4304 +#include <linux/module.h>
4305 +#include <linux/skbuff.h>
4306 +#include <linux/file.h>
4307 +#include <linux/ip.h>
4308 +#include <linux/proc_fs.h>
4309 +#include <linux/fs.h>
4310 +#include <linux/slab.h>
4311 +#include <linux/spinlock.h>
4312 +#include <linux/ctype.h>
4313 +#include <linux/list.h>
4314 +#include <linux/if.h>
4315 +
4316 +#include <net/sock.h>
4317 +#include <net/ip.h>
4318 +
4319 +#include <linux/netfilter_ipv4/ip_tables.h>
4320 +
4321 +#include <linux/netfilter_ipv4/ipt_osf.h>
4322 +
4323 +#define OSF_DEBUG
4324 +
4325 +#ifdef OSF_DEBUG
4326 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
4327 +#define loga(x...)             printk(x)
4328 +#else
4329 +#define log(x...)              do {} while(0)
4330 +#define loga(x...)             do {} while(0)
4331 +#endif
4332 +
4333 +#define FMATCH_WRONG           0
4334 +#define FMATCH_OK              1
4335 +#define FMATCH_OPT_WRONG       2
4336 +
4337 +#define OPTDEL                 ','
4338 +#define OSFPDEL                ':'
4339 +#define MAXOPTSTRLEN           128
4340 +#define OSFFLUSH               "FLUSH"
4341 +
4342 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
4343 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
4344 +static struct list_head        finger_list;    
4345 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
4346 +                     const void *, int, 
4347 +                     int *);
4348 +static int checkentry(const char *, const struct ipt_ip *, void *,
4349 +                          unsigned int, unsigned int);
4350 +
4351 +static unsigned long seq, ipt_osf_groups = 1;
4352 +static struct sock *nts;
4353 +
4354 +static struct ipt_match osf_match = 
4355 +{ 
4356 +       { NULL, NULL }, 
4357 +       "osf", 
4358 +       &match, 
4359 +       &checkentry, 
4360 +       NULL, 
4361 +       THIS_MODULE 
4362 +};
4363 +
4364 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
4365 +{
4366 +       unsigned int size;
4367 +       struct sk_buff *skb;
4368 +       struct ipt_osf_nlmsg *data;
4369 +       struct nlmsghdr *nlh;
4370 +
4371 +       size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
4372 +
4373 +       skb = alloc_skb(size, GFP_ATOMIC);
4374 +       if (!skb)
4375 +       {
4376 +               log("skb_alloc() failed.\n");
4377 +               return;
4378 +       }
4379 +       
4380 +       nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
4381 +       
4382 +       data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
4383 +
4384 +       memcpy(&data->f, f, sizeof(struct osf_finger));
4385 +       memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
4386 +       memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
4387 +
4388 +       NETLINK_CB(skb).dst_groups = ipt_osf_groups;
4389 +       netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
4390 +
4391 +nlmsg_failure:
4392 +       return;
4393 +}
4394 +
4395 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
4396 +{
4397 +       struct iphdr *ip = skb->nh.iph;
4398 +
4399 +       if (flags & IPT_OSF_SMART)
4400 +       {
4401 +               struct in_device *in_dev = in_dev_get(skb->dev);
4402 +
4403 +               for_ifa(in_dev)
4404 +               {
4405 +                       if (inet_ifa_match(ip->saddr, ifa))
4406 +                       {
4407 +                               in_dev_put(in_dev);
4408 +                               return (ip->ttl == f_ttl);
4409 +                       }
4410 +               }
4411 +               endfor_ifa(in_dev);
4412 +               
4413 +               in_dev_put(in_dev);
4414 +               return (ip->ttl <= f_ttl);
4415 +       }
4416 +       else
4417 +               return (ip->ttl == f_ttl);
4418 +}
4419 +
4420 +static int
4421 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
4422 +      const void *matchinfo, int offset,
4423 +      int *hotdrop)
4424 +{
4425 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
4426 +       struct iphdr *ip = skb->nh.iph;
4427 +       struct tcphdr *tcp;
4428 +       int fmatch = FMATCH_WRONG, fcount = 0;
4429 +       unsigned long totlen, optsize = 0, window;
4430 +       unsigned char df, *optp = NULL, *_optp = NULL;
4431 +       char check_WSS = 0;
4432 +       struct list_head *ent;
4433 +       struct osf_finger *f;
4434 +
4435 +       if (!ip || !info)
4436 +               return 0;
4437 +                               
4438 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
4439 +
4440 +       if (!tcp->syn)
4441 +               return 0;
4442 +       
4443 +       totlen = ntohs(ip->tot_len);
4444 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
4445 +       window = ntohs(tcp->window);
4446 +       
4447 +       if (tcp->doff*4 > sizeof(struct tcphdr))
4448 +       {
4449 +               _optp = optp = (char *)(tcp+1);
4450 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
4451 +       }
4452 +
4453 +       /* Actually we can create hash/table of all genres and search
4454 +        * only in appropriate part, but here is initial variant,
4455 +        * so will use slow path.
4456 +        */
4457 +       read_lock(&osf_lock);
4458 +       list_for_each(ent, &finger_list)
4459 +       {
4460 +               f = list_entry(ent, struct osf_finger, flist);
4461 +       
4462 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
4463 +                       continue;
4464 +
4465 +               optp = _optp;
4466 +               fmatch = FMATCH_WRONG;
4467 +
4468 +               if (totlen == f->ss && df == f->df && 
4469 +                       smart_dec(skb, info->flags, f->ttl))
4470 +               {
4471 +                       unsigned long foptsize;
4472 +                       int optnum;
4473 +                       unsigned short mss = 0;
4474 +
4475 +                       check_WSS = 0;
4476 +
4477 +                       switch (f->wss.wc)
4478 +                       {
4479 +                               case 0:   check_WSS = 0; break;
4480 +                               case 'S': check_WSS = 1; break;
4481 +                               case 'T': check_WSS = 2; break;
4482 +                               case '%': check_WSS = 3; break;
4483 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
4484 +                                                        f->wss.wc, f->genre, f->details);
4485 +                                        check_WSS = 4;
4486 +                                        break;
4487 +                       }
4488 +                       if (check_WSS == 4)
4489 +                               continue;
4490 +
4491 +                       /* Check options */
4492 +
4493 +                       foptsize = 0;
4494 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
4495 +                               foptsize += f->opt[optnum].length;
4496 +
4497 +                               
4498 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
4499 +                               continue;
4500 +
4501 +                       if (!optp)
4502 +                       {
4503 +                               fmatch = FMATCH_OK;
4504 +                               loga("\tYEP : matching without options.\n");
4505 +                               if ((info->flags & IPT_OSF_LOG) && 
4506 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
4507 +                                       break;
4508 +                               else
4509 +                                       continue;
4510 +                       }
4511 +                       
4512 +
4513 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
4514 +                       {
4515 +                               if (f->opt[optnum].kind == (*optp)) 
4516 +                               {
4517 +                                       unsigned char len = f->opt[optnum].length;
4518 +                                       unsigned char *optend = optp + len;
4519 +                                       int loop_cont = 0;
4520 +
4521 +                                       fmatch = FMATCH_OK;
4522 +
4523 +
4524 +                                       switch (*optp)
4525 +                                       {
4526 +                                               case OSFOPT_MSS:
4527 +                                                       mss = ntohs(*(unsigned short *)(optp+2));
4528 +                                                       break;
4529 +                                               case OSFOPT_TS:
4530 +                                                       loop_cont = 1;
4531 +                                                       break;
4532 +                                       }
4533 +                                       
4534 +                                       if (loop_cont)
4535 +                                       {
4536 +                                               optp = optend;
4537 +                                               continue;
4538 +                                       }
4539 +                                       
4540 +                                       if (len != 1)
4541 +                                       {
4542 +                                               /* Skip kind and length fields*/
4543 +                                               optp += 2; 
4544 +
4545 +                                               if (f->opt[optnum].wc.val != 0)
4546 +                                               {
4547 +                                                       unsigned long tmp = 0;
4548 +                                                       
4549 +                                                       /* Hmmm... It looks a bit ugly. :) */
4550 +                                                       memcpy(&tmp, optp, 
4551 +                                                               (len > sizeof(unsigned long)?
4552 +                                                                       sizeof(unsigned long):len));
4553 +                                                       /* 2 + 2: optlen(2 bytes) + 
4554 +                                                        *      kind(1 byte) + length(1 byte) */
4555 +                                                       if (len == 4) 
4556 +                                                               tmp = ntohs(tmp);
4557 +                                                       else
4558 +                                                               tmp = ntohl(tmp);
4559 +
4560 +                                                       if (f->opt[optnum].wc.wc == '%')
4561 +                                                       {
4562 +                                                               if ((tmp % f->opt[optnum].wc.val) != 0)
4563 +                                                                       fmatch = FMATCH_OPT_WRONG;
4564 +                                                       }
4565 +                                                       else if (tmp != f->opt[optnum].wc.val)
4566 +                                                               fmatch = FMATCH_OPT_WRONG;
4567 +                                               }
4568 +                                       }
4569 +
4570 +                                       optp = optend;
4571 +                               }
4572 +                               else
4573 +                                       fmatch = FMATCH_OPT_WRONG;
4574 +
4575 +                               if (fmatch != FMATCH_OK)
4576 +                                       break;
4577 +                       }
4578 +
4579 +                       if (fmatch != FMATCH_OPT_WRONG)
4580 +                       {
4581 +                               fmatch = FMATCH_WRONG;
4582 +
4583 +                               switch (check_WSS)
4584 +                               {
4585 +                                       case 0:
4586 +                                               if (f->wss.val == 0 || window == f->wss.val)
4587 +                                                       fmatch = FMATCH_OK;
4588 +                                               break;
4589 +                                       case 1: /* MSS */
4590 +/* Lurked in OpenBSD */
4591 +#define SMART_MSS      1460
4592 +                                               if (window == f->wss.val*mss || 
4593 +                                                       window == f->wss.val*SMART_MSS)
4594 +                                                       fmatch = FMATCH_OK;
4595 +                                               break;
4596 +                                       case 2: /* MTU */
4597 +                                               if (window == f->wss.val*(mss+40) ||
4598 +                                                       window == f->wss.val*(SMART_MSS+40))
4599 +                                                       fmatch = FMATCH_OK;
4600 +                                               break;
4601 +                                       case 3: /* MOD */
4602 +                                               if ((window % f->wss.val) == 0)
4603 +                                                       fmatch = FMATCH_OK;
4604 +                                               break;
4605 +                               }
4606 +                       }
4607 +                                       
4608 +
4609 +                       if (fmatch == FMATCH_OK)
4610 +                       {
4611 +                               fcount++;
4612 +                               log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n", 
4613 +                                       f->genre, f->version,
4614 +                                       f->subtype, f->details,
4615 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
4616 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest),
4617 +                                       f->ttl - ip->ttl);
4618 +                               if (info->flags & IPT_OSF_NETLINK)
4619 +                               {
4620 +                                       spin_lock_bh(&ipt_osf_netlink_lock);
4621 +                                       ipt_osf_nlsend(f, skb);
4622 +                                       spin_unlock_bh(&ipt_osf_netlink_lock);
4623 +                               }
4624 +                               if ((info->flags & IPT_OSF_LOG) && 
4625 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
4626 +                                       break;
4627 +                       }
4628 +               }
4629 +       }
4630 +       if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
4631 +       {
4632 +               unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
4633 +               unsigned int i, optsize;
4634 +               struct osf_finger fg;
4635 +
4636 +               memset(&fg, 0, sizeof(fg));
4637 +
4638 +               if ((info->flags & IPT_OSF_LOG))
4639 +                       log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
4640 +               if (optp)
4641 +               {
4642 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
4643 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
4644 +                                         opt, optsize) < 0)
4645 +                       {
4646 +                               if (info->flags & IPT_OSF_LOG)
4647 +                                       loga("TRUNCATED");
4648 +                               if (info->flags & IPT_OSF_NETLINK)
4649 +                                       strcpy(fg.details, "TRUNCATED");
4650 +                       }
4651 +                       else
4652 +                       {
4653 +                               for (i = 0; i < optsize; i++)
4654 +                               {
4655 +                                       if (info->flags & IPT_OSF_LOG)
4656 +                                               loga("%02X", opt[i]);
4657 +                               }
4658 +                               if (info->flags & IPT_OSF_NETLINK)
4659 +                                       memcpy(fg.details, opt, MAXDETLEN);
4660 +                       }
4661 +               }
4662 +               if ((info->flags & IPT_OSF_LOG))
4663 +                       loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
4664 +                               NIPQUAD(ip->saddr), ntohs(tcp->source),
4665 +                               NIPQUAD(ip->daddr), ntohs(tcp->dest));
4666 +               
4667 +               if (info->flags & IPT_OSF_NETLINK)
4668 +               {
4669 +                       fg.wss.val      = window;
4670 +                       fg.ttl          = ip->ttl;
4671 +                       fg.df           = df;
4672 +                       fg.ss           = totlen;
4673 +                       strncpy(fg.genre, "Unknown", MAXGENRELEN);
4674 +
4675 +                       spin_lock_bh(&ipt_osf_netlink_lock);
4676 +                       ipt_osf_nlsend(&fg, skb);
4677 +                       spin_unlock_bh(&ipt_osf_netlink_lock);
4678 +               }
4679 +       }
4680 +
4681 +       read_unlock(&osf_lock);
4682 +       
4683 +       if (fcount)
4684 +               fmatch = FMATCH_OK;
4685 +
4686 +       return (fmatch == FMATCH_OK)?1:0;
4687 +}
4688 +
4689 +static int
4690 +checkentry(const char *tablename,
4691 +           const struct ipt_ip *ip,
4692 +           void *matchinfo,
4693 +           unsigned int matchsize,
4694 +           unsigned int hook_mask)
4695 +{
4696 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
4697 +               return 0;
4698 +       if (ip->proto != IPPROTO_TCP)
4699 +              return 0;
4700 +
4701 +       return 1;
4702 +}
4703 +
4704 +static char * osf_strchr(char *ptr, char c)
4705 +{
4706 +       char *tmp;
4707 +
4708 +       tmp = strchr(ptr, c);
4709 +
4710 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
4711 +               tmp++;
4712 +
4713 +       return tmp;
4714 +}
4715 +
4716 +static struct osf_finger * finger_alloc(void)
4717 +{
4718 +       struct osf_finger *f;
4719 +
4720 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
4721 +       if (f)
4722 +               memset(f, 0, sizeof(struct osf_finger));
4723 +       
4724 +       return f;
4725 +}
4726 +
4727 +static void finger_free(struct osf_finger *f)
4728 +{
4729 +       memset(f, 0, sizeof(struct osf_finger));
4730 +       kfree(f);
4731 +}
4732 +
4733 +
4734 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
4735 +{
4736 +       int i, op;
4737 +       char *ptr, wc;
4738 +       unsigned long val;
4739 +
4740 +       ptr = &obuf[0];
4741 +       i = 0;
4742 +       while (ptr != NULL && i < olen)
4743 +       {
4744 +               val = 0;
4745 +               op = 0;
4746 +               wc = 0;
4747 +               switch (obuf[i])
4748 +               {
4749 +                       case 'N': 
4750 +                               op = OSFOPT_NOP;
4751 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
4752 +                               if (ptr)
4753 +                               {
4754 +                                       *ptr = '\0';
4755 +                                       ptr++;
4756 +                                       i += (int)(ptr-&obuf[i]);
4757 +
4758 +                               }
4759 +                               else
4760 +                                       i++;
4761 +                               break;
4762 +                       case 'S': 
4763 +                               op = OSFOPT_SACKP;
4764 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
4765 +                               if (ptr)
4766 +                               {
4767 +                                       *ptr = '\0';
4768 +                                       ptr++;
4769 +                                       i += (int)(ptr-&obuf[i]);
4770 +
4771 +                               }
4772 +                               else
4773 +                                       i++;
4774 +                               break;
4775 +                       case 'T': 
4776 +                               op = OSFOPT_TS;
4777 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
4778 +                               if (ptr)
4779 +                               {
4780 +                                       *ptr = '\0';
4781 +                                       ptr++;
4782 +                                       i += (int)(ptr-&obuf[i]);
4783 +
4784 +                               }
4785 +                               else
4786 +                                       i++;
4787 +                               break;
4788 +                       case 'W': 
4789 +                               op = OSFOPT_WSO;
4790 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
4791 +                               if (ptr)
4792 +                               {
4793 +                                       switch (obuf[i+1])
4794 +                                       {
4795 +                                               case '%':       wc = '%'; break;
4796 +                                               case 'S':       wc = 'S'; break;
4797 +                                               case 'T':       wc = 'T'; break;
4798 +                                               default:        wc = 0; break;
4799 +                                       }
4800 +                                       
4801 +                                       *ptr = '\0';
4802 +                                       ptr++;
4803 +                                       if (wc)
4804 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
4805 +                                       else
4806 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
4807 +                                       i += (int)(ptr-&obuf[i]);
4808 +
4809 +                               }
4810 +                               else
4811 +                                       i++;
4812 +                               break;
4813 +                       case 'M': 
4814 +                               op = OSFOPT_MSS;
4815 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
4816 +                               if (ptr)
4817 +                               {
4818 +                                       if (obuf[i+1] == '%')
4819 +                                               wc = '%';
4820 +                                       *ptr = '\0';
4821 +                                       ptr++;
4822 +                                       if (wc)
4823 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
4824 +                                       else
4825 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
4826 +                                       i += (int)(ptr-&obuf[i]);
4827 +
4828 +                               }
4829 +                               else
4830 +                                       i++;
4831 +                               break;
4832 +                       case 'E': 
4833 +                               op = OSFOPT_EOL;
4834 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
4835 +                               if (ptr)
4836 +                               {
4837 +                                       *ptr = '\0';
4838 +                                       ptr++;
4839 +                                       i += (int)(ptr-&obuf[i]);
4840 +
4841 +                               }
4842 +                               else
4843 +                                       i++;
4844 +                               break;
4845 +                       default:
4846 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
4847 +                               if (ptr)
4848 +                               {
4849 +                                       ptr++;
4850 +                                       i += (int)(ptr-&obuf[i]);
4851 +
4852 +                               }
4853 +                               else
4854 +                                       i++;
4855 +                               break;
4856 +               }
4857 +
4858 +               opt[*optnum].kind       = IANA_opts[op].kind;
4859 +               opt[*optnum].length     = IANA_opts[op].length;
4860 +               opt[*optnum].wc.wc      = wc;
4861 +               opt[*optnum].wc.val     = val;
4862 +
4863 +               (*optnum)++;
4864 +       }
4865 +}
4866 +
4867 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
4868 +{
4869 +       struct list_head *ent;
4870 +       struct osf_finger *f = NULL;
4871 +       int i, __count, err;
4872 +       
4873 +       *eof = 1;
4874 +       __count = count;
4875 +       count = 0;
4876 +
4877 +       read_lock_bh(&osf_lock);
4878 +       list_for_each(ent, &finger_list)
4879 +       {
4880 +               f = list_entry(ent, struct osf_finger, flist);
4881 +
4882 +               log("%s [%s]", f->genre, f->details);
4883 +               
4884 +               err = snprintf(buf+count, __count-count, "%s - %s[%s] : %s", 
4885 +                                       f->genre, f->version,
4886 +                                       f->subtype, f->details);
4887 +               if (err == 0 || __count <= count + err)
4888 +                       break;
4889 +               else
4890 +                       count += err;
4891 +               if (f->opt_num)
4892 +               {
4893 +                       loga(" OPT: ");
4894 +                       //count += sprintf(buf+count, " OPT: ");
4895 +                       for (i=0; i<f->opt_num; ++i)
4896 +                       {
4897 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
4898 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
4899 +                               loga("%d.%c%lu; ", 
4900 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
4901 +                       }
4902 +               }
4903 +               loga("\n");
4904 +               err = snprintf(buf+count, __count-count, "\n");
4905 +               if (err == 0 || __count <= count + err)
4906 +                       break;
4907 +               else
4908 +                       count += err;
4909 +       }
4910 +       read_unlock_bh(&osf_lock);
4911 +
4912 +       return count;
4913 +}
4914 +
4915 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
4916 +{
4917 +       int cnt;
4918 +       unsigned long i;
4919 +       char obuf[MAXOPTSTRLEN];
4920 +       struct osf_finger *finger;
4921 +       struct list_head *ent, *n;
4922 +
4923 +       char *pbeg, *pend;
4924 +
4925 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
4926 +       {
4927 +               int i = 0;
4928 +               write_lock_bh(&osf_lock);
4929 +               list_for_each_safe(ent, n, &finger_list)
4930 +               {
4931 +                       i++;
4932 +                       finger = list_entry(ent, struct osf_finger, flist);
4933 +                       list_del(&finger->flist);
4934 +                       finger_free(finger);
4935 +               }
4936 +               write_unlock_bh(&osf_lock);
4937 +       
4938 +               log("Flushed %d entries.\n", i);
4939 +               
4940 +               return count;
4941 +       }
4942 +
4943 +       
4944 +       cnt = 0;
4945 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
4946 +               if (buffer[i] == ':')
4947 +                       cnt++;
4948 +
4949 +       if (cnt != 8 || i != count)
4950 +       {
4951 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
4952 +                       cnt, i, count);
4953 +               return count;
4954 +       }
4955 +
4956 +       memset(obuf, 0, sizeof(obuf));
4957 +       
4958 +       finger = finger_alloc();
4959 +       if (!finger)
4960 +       {
4961 +               log("Failed to allocate new fingerprint entry.\n");
4962 +               return -ENOMEM;
4963 +       }
4964 +
4965 +       pbeg = (char *)buffer;
4966 +       pend = osf_strchr(pbeg, OSFPDEL);
4967 +       if (pend)
4968 +       {
4969 +               *pend = '\0';
4970 +               if (pbeg[0] == 'S')
4971 +               {
4972 +                       finger->wss.wc = 'S';
4973 +                       if (pbeg[1] == '%')
4974 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4975 +                       else if (pbeg[1] == '*')
4976 +                               finger->wss.val = 0;
4977 +                       else 
4978 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4979 +               }
4980 +               else if (pbeg[0] == 'T')
4981 +               {
4982 +                       finger->wss.wc = 'T';
4983 +                       if (pbeg[1] == '%')
4984 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4985 +                       else if (pbeg[1] == '*')
4986 +                               finger->wss.val = 0;
4987 +                       else 
4988 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4989 +               }
4990 +               else if (pbeg[0] == '%')
4991 +               {
4992 +                       finger->wss.wc = '%';
4993 +                       finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4994 +               }
4995 +               else if (isdigit(pbeg[0]))
4996 +               {
4997 +                       finger->wss.wc = 0;
4998 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
4999 +               }
5000 +
5001 +               pbeg = pend+1;
5002 +       }
5003 +       pend = osf_strchr(pbeg, OSFPDEL);
5004 +       if (pend)
5005 +       {
5006 +               *pend = '\0';
5007 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
5008 +               pbeg = pend+1;
5009 +       }
5010 +       pend = osf_strchr(pbeg, OSFPDEL);
5011 +       if (pend)
5012 +       {
5013 +               *pend = '\0';
5014 +               finger->df = simple_strtoul(pbeg, NULL, 10);
5015 +               pbeg = pend+1;
5016 +       }
5017 +       pend = osf_strchr(pbeg, OSFPDEL);
5018 +       if (pend)
5019 +       {
5020 +               *pend = '\0';
5021 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
5022 +               pbeg = pend+1;
5023 +       }
5024 +
5025 +       pend = osf_strchr(pbeg, OSFPDEL);
5026 +       if (pend)
5027 +       {
5028 +               *pend = '\0';
5029 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
5030 +               pbeg = pend+1;
5031 +       }
5032 +
5033 +       pend = osf_strchr(pbeg, OSFPDEL);
5034 +       if (pend)
5035 +       {
5036 +               *pend = '\0';
5037 +               if (pbeg[0] == '@' || pbeg[0] == '*')
5038 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
5039 +               else
5040 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
5041 +               pbeg = pend+1;
5042 +       }
5043 +       
5044 +       pend = osf_strchr(pbeg, OSFPDEL);
5045 +       if (pend)
5046 +       {
5047 +               *pend = '\0';
5048 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
5049 +               pbeg = pend+1;
5050 +       }
5051 +       
5052 +       pend = osf_strchr(pbeg, OSFPDEL);
5053 +       if (pend)
5054 +       {
5055 +               *pend = '\0';
5056 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
5057 +               pbeg = pend+1;
5058 +       }
5059 +
5060 +       cnt = snprintf(finger->details, 
5061 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
5062 +                       "%s", pbeg);
5063 +       
5064 +       log("%s - %s[%s] : %s\n", 
5065 +               finger->genre, finger->version,
5066 +               finger->subtype, finger->details);
5067 +       
5068 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
5069 +       
5070 +
5071 +       write_lock_bh(&osf_lock);
5072 +       list_add_tail(&finger->flist, &finger_list);
5073 +       write_unlock_bh(&osf_lock);
5074 +
5075 +       return count;
5076 +}
5077 +
5078 +static int __init osf_init(void)
5079 +{
5080 +       int err;
5081 +       struct proc_dir_entry *p;
5082 +
5083 +       log("Startng OS fingerprint matching module.\n");
5084 +
5085 +       INIT_LIST_HEAD(&finger_list);
5086 +       
5087 +       err = ipt_register_match(&osf_match);
5088 +       if (err)
5089 +       {
5090 +               log("Failed to register OS fingerprint matching module.\n");
5091 +               return -ENXIO;
5092 +       }
5093 +
5094 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
5095 +       if (!p)
5096 +       {
5097 +               ipt_unregister_match(&osf_match);
5098 +               return -ENXIO;
5099 +       }
5100 +
5101 +       p->write_proc = osf_proc_write;
5102 +       p->read_proc  = osf_proc_read;
5103 +       
5104 +       nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
5105 +       if (!nts)
5106 +       {
5107 +               log("netlink_kernel_create() failed\n");
5108 +               remove_proc_entry("sys/net/ipv4/osf", NULL);
5109 +               ipt_unregister_match(&osf_match);
5110 +               return -ENOMEM;
5111 +       }
5112 +
5113 +       return 0;
5114 +}
5115 +
5116 +static void __exit osf_fini(void)
5117 +{
5118 +       struct list_head *ent, *n;
5119 +       struct osf_finger *f;
5120 +       
5121 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
5122 +       ipt_unregister_match(&osf_match);
5123 +       if (nts && nts->sk_socket)
5124 +               sock_release(nts->sk_socket);
5125 +
5126 +       list_for_each_safe(ent, n, &finger_list)
5127 +       {
5128 +               f = list_entry(ent, struct osf_finger, flist);
5129 +               list_del(&f->flist);
5130 +               finger_free(f);
5131 +       }
5132 +       
5133 +       log("OS fingerprint matching module finished.\n");
5134 +}
5135 +
5136 +module_init(osf_init);
5137 +module_exit(osf_fini);
5138 +
5139 +MODULE_LICENSE("GPL");
5140 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
5141 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
5142 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.7/net/ipv4/netfilter/ipt_psd.c
5143 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c        1970-01-01 01:00:00.000000000 +0100
5144 +++ linux-2.6.7/net/ipv4/netfilter/ipt_psd.c    2004-09-07 12:33:19.724553048 +0200
5145 @@ -0,0 +1,358 @@
5146 +/*
5147 +  This is a module which is used for PSD (portscan detection)
5148 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
5149 +  and LOG target module.
5150 +
5151 +  Copyright (C) 2000,2001 astaro AG
5152 +
5153 +  This file is distributed under the terms of the GNU General Public
5154 +  License (GPL). Copies of the GPL can be obtained from:
5155 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
5156 +
5157 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
5158 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
5159 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
5160 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
5161 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
5162 +  2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
5163 +*/
5164 +
5165 +#include <linux/module.h>
5166 +#include <linux/skbuff.h>
5167 +#include <linux/ip.h>
5168 +#include <net/tcp.h>
5169 +#include <linux/spinlock.h>
5170 +#include <linux/netfilter_ipv4/ip_tables.h>
5171 +#include <linux/netfilter_ipv4/ipt_psd.h>
5172 +
5173 +#if 0
5174 +#define DEBUGP printk
5175 +#else
5176 +#define DEBUGP(format, args...)
5177 +#endif
5178 +
5179 +MODULE_LICENSE("GPL");
5180 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
5181 +
5182 +#define HF_DADDR_CHANGING   0x01
5183 +#define HF_SPORT_CHANGING   0x02
5184 +#define HF_TOS_CHANGING            0x04
5185 +#define HF_TTL_CHANGING            0x08
5186 +
5187 +/*
5188 + * Information we keep per each target port
5189 + */
5190 +struct port {
5191 +       u_int16_t number;      /* port number */
5192 +       u_int8_t proto;        /* protocol number */
5193 +       u_int8_t and_flags;    /* tcp ANDed flags */
5194 +       u_int8_t or_flags;     /* tcp ORed flags */
5195 +};
5196 +
5197 +/*
5198 + * Information we keep per each source address.
5199 + */
5200 +struct host {
5201 +       struct host *next;              /* Next entry with the same hash */
5202 +       clock_t timestamp;              /* Last update time */
5203 +       struct in_addr src_addr;        /* Source address */
5204 +       struct in_addr dest_addr;       /* Destination address */
5205 +       unsigned short src_port;        /* Source port */
5206 +       int count;                      /* Number of ports in the list */
5207 +       int weight;                     /* Total weight of ports in the list */
5208 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
5209 +       unsigned char tos;              /* TOS */
5210 +       unsigned char ttl;              /* TTL */
5211 +       unsigned char flags;            /* HF_ flags bitmask */
5212 +};
5213 +
5214 +/*
5215 + * State information.
5216 + */
5217 +static struct {
5218 +       spinlock_t lock;
5219 +       struct host list[LIST_SIZE];    /* List of source addresses */
5220 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
5221 +       int index;                      /* Oldest entry to be replaced */
5222 +} state;
5223 +
5224 +/*
5225 + * Convert an IP address into a hash table index.
5226 + */
5227 +static inline int hashfunc(struct in_addr addr)
5228 +{
5229 +       unsigned int value;
5230 +       int hash;
5231 +
5232 +       value = addr.s_addr;
5233 +       hash = 0;
5234 +       do {
5235 +               hash ^= value;
5236 +       } while ((value >>= HASH_LOG));
5237 +
5238 +       return hash & (HASH_SIZE - 1);
5239 +}
5240 +
5241 +static int
5242 +ipt_psd_match(const struct sk_buff *pskb,
5243 +             const struct net_device *in,
5244 +             const struct net_device *out,
5245 +             const void *matchinfo,
5246 +             int offset,
5247 +             int *hotdrop)
5248 +{
5249 +       struct iphdr *ip_hdr;
5250 +       struct tcphdr *tcp_hdr;
5251 +       struct in_addr addr;
5252 +       u_int16_t src_port,dest_port;
5253 +       u_int8_t tcp_flags, proto;
5254 +       clock_t now;
5255 +       struct host *curr, *last, **head;
5256 +       int hash, index, count;
5257 +
5258 +       /* Parameters from userspace */
5259 +       const struct ipt_psd_info *psdinfo = matchinfo;
5260 +
5261 +       /* IP header */
5262 +       ip_hdr = pskb->nh.iph;
5263 +
5264 +       /* Sanity check */
5265 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
5266 +               DEBUGP("PSD: sanity check failed\n");
5267 +               return 0;
5268 +       }
5269 +
5270 +       /* TCP or UDP ? */
5271 +       proto = ip_hdr->protocol;
5272 +
5273 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
5274 +               DEBUGP("PSD: protocol not supported\n");
5275 +               return 0;
5276 +       }
5277 +
5278 +       /* Get the source address, source & destination ports, and TCP flags */
5279 +
5280 +       addr.s_addr = ip_hdr->saddr;
5281 +
5282 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
5283 +
5284 +       /* Yep, it´s dirty */
5285 +       src_port = tcp_hdr->source;
5286 +       dest_port = tcp_hdr->dest;
5287 +
5288 +       if (proto == IPPROTO_TCP) {
5289 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
5290 +       }
5291 +       else {
5292 +               tcp_flags = 0x00;
5293 +       }
5294 +
5295 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
5296 +        * them spoof us. [DHCP needs this feature - HW] */
5297 +       if (!addr.s_addr) {
5298 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
5299 +               return 0;
5300 +       }
5301 +
5302 +       /* Use jiffies here not to depend on someone setting the time while we're
5303 +        * running; we need to be careful with possible return value overflows. */
5304 +       now = jiffies;
5305 +
5306 +       spin_lock(&state.lock);
5307 +
5308 +       /* Do we know this source address already? */
5309 +       count = 0;
5310 +       last = NULL;
5311 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
5312 +               do {
5313 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
5314 +                       count++;
5315 +                       if (curr->next) last = curr;
5316 +               } while ((curr = curr->next));
5317 +
5318 +       if (curr) {
5319 +
5320 +               /* We know this address, and the entry isn't too old. Update it. */
5321 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
5322 +                   time_after_eq(now, curr->timestamp)) {
5323 +
5324 +                       /* Just update the appropriate list entry if we've seen this port already */
5325 +                       for (index = 0; index < curr->count; index++) {
5326 +                               if (curr->ports[index].number == dest_port) {
5327 +                                       curr->ports[index].proto = proto;
5328 +                                       curr->ports[index].and_flags &= tcp_flags;
5329 +                                       curr->ports[index].or_flags |= tcp_flags;
5330 +                                       goto out_no_match;
5331 +                               }
5332 +                       }
5333 +
5334 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
5335 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
5336 +                               goto out_no_match;
5337 +
5338 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
5339 +                       curr->timestamp = now;
5340 +
5341 +                       /* Logged this scan already? Then drop the packet. */
5342 +                       if (curr->weight >= psdinfo->weight_threshold)
5343 +                               goto out_match;
5344 +
5345 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
5346 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
5347 +                               curr->flags |= HF_DADDR_CHANGING;
5348 +                       if (curr->src_port != src_port)
5349 +                               curr->flags |= HF_SPORT_CHANGING;
5350 +                       if (curr->tos != ip_hdr->tos)
5351 +                               curr->flags |= HF_TOS_CHANGING;
5352 +                       if (curr->ttl != ip_hdr->ttl)
5353 +                               curr->flags |= HF_TTL_CHANGING;
5354 +
5355 +                       /* Update the total weight */
5356 +                       curr->weight += (ntohs(dest_port) < 1024) ?
5357 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
5358 +
5359 +                       /* Got enough destination ports to decide that this is a scan? */
5360 +                       /* Then log it and drop the packet. */
5361 +                       if (curr->weight >= psdinfo->weight_threshold)
5362 +                               goto out_match;
5363 +
5364 +                       /* Remember the new port */
5365 +                       if (curr->count < SCAN_MAX_COUNT) {
5366 +                               curr->ports[curr->count].number = dest_port;
5367 +                               curr->ports[curr->count].proto = proto;
5368 +                               curr->ports[curr->count].and_flags = tcp_flags;
5369 +                               curr->ports[curr->count].or_flags = tcp_flags;
5370 +                               curr->count++;
5371 +                       }
5372 +
5373 +                       goto out_no_match;
5374 +               }
5375 +
5376 +               /* We know this address, but the entry is outdated. Mark it unused, and
5377 +                * remove from the hash table. We'll allocate a new entry instead since
5378 +                * this one might get re-used too soon. */
5379 +               curr->src_addr.s_addr = 0;
5380 +               if (last)
5381 +                       last->next = last->next->next;
5382 +               else if (*head)
5383 +                       *head = (*head)->next;
5384 +               last = NULL;
5385 +       }
5386 +
5387 +       /* We don't need an ACK from a new source address */
5388 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
5389 +               goto out_no_match;
5390 +
5391 +       /* Got too many source addresses with the same hash value? Then remove the
5392 +        * oldest one from the hash table, so that they can't take too much of our
5393 +        * CPU time even with carefully chosen spoofed IP addresses. */
5394 +       if (count >= HASH_MAX && last) last->next = NULL;
5395 +
5396 +       /* We're going to re-use the oldest list entry, so remove it from the hash
5397 +        * table first (if it is really already in use, and isn't removed from the
5398 +        * hash table already because of the HASH_MAX check above). */
5399 +
5400 +       /* First, find it */
5401 +       if (state.list[state.index].src_addr.s_addr)
5402 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
5403 +       else
5404 +               head = &last;
5405 +       last = NULL;
5406 +       if ((curr = *head))
5407 +       do {
5408 +               if (curr == &state.list[state.index]) break;
5409 +               last = curr;
5410 +       } while ((curr = curr->next));
5411 +
5412 +       /* Then, remove it */
5413 +       if (curr) {
5414 +               if (last)
5415 +                       last->next = last->next->next;
5416 +               else if (*head)
5417 +                       *head = (*head)->next;
5418 +       }
5419 +
5420 +       /* Get our list entry */
5421 +       curr = &state.list[state.index++];
5422 +       if (state.index >= LIST_SIZE) state.index = 0;
5423 +
5424 +       /* Link it into the hash table */
5425 +       head = &state.hash[hash];
5426 +       curr->next = *head;
5427 +       *head = curr;
5428 +
5429 +       /* And fill in the fields */
5430 +       curr->timestamp = now;
5431 +       curr->src_addr = addr;
5432 +       curr->dest_addr.s_addr = ip_hdr->daddr;
5433 +       curr->src_port = src_port;
5434 +       curr->count = 1;
5435 +       curr->weight = (ntohs(dest_port) < 1024) ?
5436 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
5437 +       curr->ports[0].number = dest_port;
5438 +       curr->ports[0].proto = proto;
5439 +       curr->ports[0].and_flags = tcp_flags;
5440 +       curr->ports[0].or_flags = tcp_flags;
5441 +       curr->tos = ip_hdr->tos;
5442 +       curr->ttl = ip_hdr->ttl;
5443 +
5444 +out_no_match:
5445 +       spin_unlock(&state.lock);
5446 +       return 0;
5447 +
5448 +out_match:
5449 +       spin_unlock(&state.lock);
5450 +       return 1;
5451 +}
5452 +
5453 +static int ipt_psd_checkentry(const char *tablename,
5454 +                             const struct ipt_ip *e,
5455 +                             void *matchinfo,
5456 +                             unsigned int matchsize,
5457 +                             unsigned int hook_mask)
5458 +{
5459 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
5460 +
5461 +       /* we accept TCP only */
5462 +/*     if (e->ip.proto != IPPROTO_TCP) { */
5463 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
5464 +/*             return 0; */
5465 +/*     } */
5466 +
5467 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
5468 +               DEBUGP("PSD: matchsize %u != %u\n",
5469 +                      matchsize,
5470 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
5471 +               return 0;
5472 +       }
5473 +
5474 +       return 1;
5475 +}
5476 +
5477 +static struct ipt_match ipt_psd_reg = {
5478 +       .name = "psd",
5479 +       .match = ipt_psd_match,
5480 +       .checkentry = ipt_psd_checkentry,
5481 +       .me = THIS_MODULE };
5482 +
5483 +static int __init init(void)
5484 +{
5485 +       if (ipt_register_match(&ipt_psd_reg))
5486 +               return -EINVAL;
5487 +
5488 +       memset(&state, 0, sizeof(state));
5489 +
5490 +       spin_lock_init(&(state.lock));
5491 +
5492 +       printk("netfilter PSD loaded - (c) astaro AG\n");
5493 +       return 0;
5494 +}
5495 +
5496 +static void __exit fini(void)
5497 +{
5498 +       ipt_unregister_match(&ipt_psd_reg);
5499 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
5500 +}
5501 +
5502 +module_init(init);
5503 +module_exit(fini);
5504 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.7/net/ipv4/netfilter/ipt_quota.c
5505 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c      1970-01-01 01:00:00.000000000 +0100
5506 +++ linux-2.6.7/net/ipv4/netfilter/ipt_quota.c  2004-09-07 12:33:20.690406216 +0200
5507 @@ -0,0 +1,91 @@
5508 +/* 
5509 + * netfilter module to enforce network quotas
5510 + *
5511 + * Sam Johnston <samj@samj.net>
5512 + */
5513 +#include <linux/module.h>
5514 +#include <linux/skbuff.h>
5515 +#include <linux/spinlock.h>
5516 +#include <linux/interrupt.h>
5517 +
5518 +#include <linux/netfilter_ipv4/ip_tables.h>
5519 +#include <linux/netfilter_ipv4/ipt_quota.h>
5520 +
5521 +MODULE_LICENSE("GPL");
5522 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
5523 +
5524 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
5525 +
5526 +static int
5527 +match(const struct sk_buff *skb,
5528 +      const struct net_device *in,
5529 +      const struct net_device *out,
5530 +      const void *matchinfo,
5531 +      int offset, int *hotdrop)
5532 +{
5533 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
5534 +       unsigned int datalen;
5535 +
5536 +       if (skb->len < sizeof(struct iphdr))
5537 +               return NF_ACCEPT;
5538 +       
5539 +       datalen = skb->len - skb->nh.iph->ihl*4;
5540 +
5541 +        spin_lock_bh(&quota_lock);
5542 +
5543 +        if (q->quota >= datalen) {
5544 +                /* we can afford this one */
5545 +                q->quota -= datalen;
5546 +                spin_unlock_bh(&quota_lock);
5547 +
5548 +#ifdef DEBUG_IPT_QUOTA
5549 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
5550 +#endif
5551 +                return 1;
5552 +        }
5553 +
5554 +        /* so we do not allow even small packets from now on */
5555 +        q->quota = 0;
5556 +
5557 +#ifdef DEBUG_IPT_QUOTA
5558 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
5559 +#endif
5560 +
5561 +        spin_unlock_bh(&quota_lock);
5562 +        return 0;
5563 +}
5564 +
5565 +static int
5566 +checkentry(const char *tablename,
5567 +           const struct ipt_ip *ip,
5568 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
5569 +{
5570 +        /* TODO: spinlocks? sanity checks? */
5571 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
5572 +                return 0;
5573 +
5574 +        return 1;
5575 +}
5576 +
5577 +static struct ipt_match quota_match = {
5578 +       .name = "quota",
5579 +       .match = match,
5580 +       .checkentry = checkentry,
5581 +       .me = THIS_MODULE
5582 +};
5583 +
5584 +static int __init
5585 +init(void)
5586 +{
5587 +        return ipt_register_match(&quota_match);
5588 +}
5589 +
5590 +static void __exit
5591 +fini(void)
5592 +{
5593 +        ipt_unregister_match(&quota_match);
5594 +}
5595 +
5596 +module_init(init);
5597 +module_exit(fini);
5598 +
5599 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c
5600 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c       1970-01-01 01:00:00.000000000 +0100
5601 +++ linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c   2004-09-07 12:33:05.390732120 +0200
5602 @@ -0,0 +1,201 @@
5603 +#include <linux/module.h>
5604 +#include <linux/skbuff.h>
5605 +#include <net/ip.h>
5606 +#include <linux/sctp.h>
5607 +
5608 +#include <linux/netfilter_ipv4/ip_tables.h>
5609 +#include <linux/netfilter_ipv4/ipt_sctp.h>
5610 +
5611 +#ifdef DEBUG_SCTP
5612 +#define duprintf(format, args...) printk(format , ## args)
5613 +#else
5614 +#define duprintf(format, args...)
5615 +#endif
5616 +
5617 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
5618 +                                             || (!!((invflag) & (option)) ^ (cond)))
5619 +
5620 +static int
5621 +match_flags(const struct ipt_sctp_flag_info *flag_info,
5622 +           const int flag_count,
5623 +           u_int8_t chunktype,
5624 +           u_int8_t chunkflags)
5625 +{
5626 +       int i;
5627 +
5628 +       for (i = 0; i < flag_count; i++) {
5629 +               if (flag_info[i].chunktype == chunktype) {
5630 +                       return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
5631 +               }
5632 +       }
5633 +
5634 +       return 1;
5635 +}
5636 +
5637 +static int
5638 +match_packet(const struct sk_buff *skb,
5639 +            const u_int32_t *chunkmap,
5640 +            int chunk_match_type,
5641 +            const struct ipt_sctp_flag_info *flag_info,
5642 +            const int flag_count,
5643 +            int *hotdrop)
5644 +{
5645 +       int offset;
5646 +       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
5647 +       sctp_chunkhdr_t sch;
5648 +
5649 +#ifdef DEBUG_SCTP
5650 +       int i = 0;
5651 +#endif
5652 +
5653 +       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
5654 +               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
5655 +       }
5656 +
5657 +       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
5658 +       do {
5659 +               if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
5660 +                       duprintf("Dropping invalid SCTP packet.\n");
5661 +                       *hotdrop = 1;
5662 +                       return 0;
5663 +               }
5664 +
5665 +               duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
5666 +                               ++i, offset, sch.type, htons(sch.length), sch.flags);
5667 +
5668 +               offset += (htons(sch.length) + 3) & ~3;
5669 +
5670 +               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
5671 +
5672 +               if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
5673 +                       switch (chunk_match_type) {
5674 +                       case SCTP_CHUNK_MATCH_ANY:
5675 +                               if (match_flags(flag_info, flag_count, 
5676 +                                       sch.type, sch.flags)) {
5677 +                                       return 1;
5678 +                               }
5679 +                               break;
5680 +
5681 +                       case SCTP_CHUNK_MATCH_ALL:
5682 +                               if (match_flags(flag_info, flag_count, 
5683 +                                       sch.type, sch.flags)) {
5684 +                                       SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
5685 +                               }
5686 +                               break;
5687 +
5688 +                       case SCTP_CHUNK_MATCH_ONLY:
5689 +                               if (!match_flags(flag_info, flag_count, 
5690 +                                       sch.type, sch.flags)) {
5691 +                                       return 0;
5692 +                               }
5693 +                               break;
5694 +                       }
5695 +               } else {
5696 +                       switch (chunk_match_type) {
5697 +                       case SCTP_CHUNK_MATCH_ONLY:
5698 +                               return 0;
5699 +                       }
5700 +               }
5701 +       } while (offset < skb->len);
5702 +
5703 +       switch (chunk_match_type) {
5704 +       case SCTP_CHUNK_MATCH_ALL:
5705 +               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
5706 +       case SCTP_CHUNK_MATCH_ANY:
5707 +               return 0;
5708 +       case SCTP_CHUNK_MATCH_ONLY:
5709 +               return 1;
5710 +       }
5711 +
5712 +       /* This will never be reached, but required to stop compiler whine */
5713 +       return 0;
5714 +}
5715 +
5716 +static int
5717 +match(const struct sk_buff *skb,
5718 +      const struct net_device *in,
5719 +      const struct net_device *out,
5720 +      const void *matchinfo,
5721 +      int offset,
5722 +      int *hotdrop)
5723 +{
5724 +       const struct ipt_sctp_info *info;
5725 +       sctp_sctphdr_t sh;
5726 +
5727 +       info = (const struct ipt_sctp_info *)matchinfo;
5728 +
5729 +       if (offset) {
5730 +               duprintf("Dropping non-first fragment.. FIXME\n");
5731 +               return 0;
5732 +       }
5733 +       
5734 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
5735 +               duprintf("Dropping evil TCP offset=0 tinygram.\n");
5736 +               *hotdrop = 1;
5737 +               return 0;
5738 +               }
5739 +       duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
5740 +
5741 +       return  SCCHECK(((ntohs(sh.source) >= info->spts[0]) 
5742 +                       && (ntohs(sh.source) <= info->spts[1])), 
5743 +                       IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
5744 +               && SCCHECK(((ntohs(sh.dest) >= info->dpts[0]) 
5745 +                       && (ntohs(sh.dest) <= info->dpts[1])), 
5746 +                       IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
5747 +               && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
5748 +                                       info->flag_info, info->flag_count, 
5749 +                                       hotdrop),
5750 +                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
5751 +}
5752 +
5753 +static int
5754 +checkentry(const char *tablename,
5755 +          const struct ipt_ip *ip,
5756 +          void *matchinfo,
5757 +          unsigned int matchsize,
5758 +          unsigned int hook_mask)
5759 +{
5760 +       const struct ipt_sctp_info *info;
5761 +
5762 +       info = (const struct ipt_sctp_info *)matchinfo;
5763 +
5764 +       return ip->proto == IPPROTO_SCTP
5765 +               && !(ip->invflags & IPT_INV_PROTO)
5766 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
5767 +               && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
5768 +               && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
5769 +               && !(info->invflags & ~info->flags)
5770 +               && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
5771 +                       (info->chunk_match_type &
5772 +                               (SCTP_CHUNK_MATCH_ALL 
5773 +                               | SCTP_CHUNK_MATCH_ANY
5774 +                               | SCTP_CHUNK_MATCH_ONLY)));
5775 +}
5776 +
5777 +static struct ipt_match sctp_match = 
5778 +{ 
5779 +       .list = { NULL, NULL},
5780 +       .name = "sctp",
5781 +       .match = &match,
5782 +       .checkentry = &checkentry,
5783 +       .destroy = NULL,
5784 +       .me = THIS_MODULE
5785 +};
5786 +
5787 +static int __init init(void)
5788 +{
5789 +       return ipt_register_match(&sctp_match);
5790 +}
5791 +
5792 +static void __exit fini(void)
5793 +{
5794 +       ipt_unregister_match(&sctp_match);
5795 +}
5796 +
5797 +module_init(init);
5798 +module_exit(fini);
5799 +
5800 +MODULE_LICENSE("GPL");
5801 +MODULE_AUTHOR("Kiran Kumar Immidi");
5802 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
5803 +
5804 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c linux-2.6.7/net/ipv4/netfilter/ipt_time.c
5805 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c       1970-01-01 01:00:00.000000000 +0100
5806 +++ linux-2.6.7/net/ipv4/netfilter/ipt_time.c   2004-09-07 12:33:22.072196152 +0200
5807 @@ -0,0 +1,189 @@
5808 +/*
5809 +  This is a module which is used for time matching
5810 +  It is using some modified code from dietlibc (localtime() function)
5811 +  that you can find at http://www.fefe.de/dietlibc/
5812 +  This file is distributed under the terms of the GNU General Public
5813 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
5814 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
5815 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
5816 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
5817 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
5818 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
5819 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
5820 +  2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
5821 +*/
5822 +
5823 +#include <linux/module.h>
5824 +#include <linux/skbuff.h>
5825 +#include <linux/netfilter_ipv4/ip_tables.h>
5826 +#include <linux/netfilter_ipv4/ipt_time.h>
5827 +#include <linux/time.h>
5828 +
5829 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5830 +MODULE_DESCRIPTION("Match arrival timestamp/date");
5831 +MODULE_LICENSE("GPL");
5832 +
5833 +struct tm
5834 +{
5835 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
5836 +       int tm_min;                   /* Minutes.     [0-59] */
5837 +       int tm_hour;                  /* Hours.       [0-23] */
5838 +       int tm_mday;                  /* Day.         [1-31] */
5839 +       int tm_mon;                   /* Month.       [0-11] */
5840 +       int tm_year;                  /* Year - 1900.  */
5841 +       int tm_wday;                  /* Day of week. [0-6] */
5842 +       int tm_yday;                  /* Days in year.[0-365] */
5843 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
5844 +
5845 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
5846 +       const char *tm_zone;          /* we don't care, we count from GMT */
5847 +};
5848 +
5849 +void
5850 +localtime(const time_t *timepr, struct tm *r);
5851 +
5852 +static int
5853 +match(const struct sk_buff *skb,
5854 +      const struct net_device *in,
5855 +      const struct net_device *out,
5856 +      const void *matchinfo,
5857 +      int offset,
5858 +      const void *hdr,
5859 +      u_int16_t datalen,
5860 +      int *hotdrop)
5861 +{
5862 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
5863 +       struct tm currenttime;                          /* time human readable */
5864 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
5865 +       u_int16_t packet_time;
5866 +       struct timeval kerneltimeval;
5867 +       time_t packet_local_time;
5868 +
5869 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
5870 +       if (info->kerneltime)
5871 +       {
5872 +               do_gettimeofday(&kerneltimeval);
5873 +               packet_local_time = kerneltimeval.tv_sec;
5874 +       }
5875 +       else
5876 +               packet_local_time = skb->stamp.tv_sec;
5877 +
5878 +       /* First we make sure we are in the date start-stop boundaries */
5879 +       if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
5880 +               return 0; /* We are outside the date boundaries */
5881 +
5882 +       /* Transform the timestamp of the packet, in a human readable form */
5883 +       localtime(&packet_local_time, &currenttime);
5884 +
5885 +       /* check if we match this timestamp, we start by the days... */
5886 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
5887 +               return 0; /* the day doesn't match */
5888 +
5889 +       /* ... check the time now */
5890 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
5891 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
5892 +               return 0;
5893 +
5894 +       /* here we match ! */
5895 +       return 1;
5896 +}
5897 +
5898 +static int
5899 +checkentry(const char *tablename,
5900 +           const struct ipt_ip *ip,
5901 +           void *matchinfo,
5902 +           unsigned int matchsize,
5903 +           unsigned int hook_mask)
5904 +{
5905 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
5906 +
5907 +       /* First, check that we are in the correct hooks */
5908 +       if (hook_mask
5909 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
5910 +       {
5911 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
5912 +               return 0;
5913 +       }
5914 +       /* we use the kerneltime if we are in forward or output */
5915 +       info->kerneltime = 1;
5916 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
5917 +               /* we use the skb time */
5918 +               info->kerneltime = 0;
5919 +
5920 +       /* Check the size */
5921 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
5922 +               return 0;
5923 +       /* Now check the coherence of the data ... */
5924 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
5925 +           (info->time_stop  > 1439))
5926 +       {
5927 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
5928 +               return 0;
5929 +       }
5930 +
5931 +       return 1;
5932 +}
5933 +
5934 +static struct ipt_match time_match
5935 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
5936 +
5937 +static int __init init(void)
5938 +{
5939 +       printk("ipt_time loading\n");
5940 +       return ipt_register_match(&time_match);
5941 +}
5942 +
5943 +static void __exit fini(void)
5944 +{
5945 +       ipt_unregister_match(&time_match);
5946 +       printk("ipt_time unloaded\n");
5947 +}
5948 +
5949 +module_init(init);
5950 +module_exit(fini);
5951 +
5952 +
5953 +/* The part below is borowed and modified from dietlibc */
5954 +
5955 +/* seconds per day */
5956 +#define SPD 24*60*60
5957 +
5958 +void
5959 +localtime(const time_t *timepr, struct tm *r) {
5960 +       time_t i;
5961 +       time_t timep;
5962 +       extern struct timezone sys_tz;
5963 +       const unsigned int __spm[12] =
5964 +               { 0,
5965 +                 (31),
5966 +                 (31+28),
5967 +                 (31+28+31),
5968 +                 (31+28+31+30),
5969 +                 (31+28+31+30+31),
5970 +                 (31+28+31+30+31+30),
5971 +                 (31+28+31+30+31+30+31),
5972 +                 (31+28+31+30+31+30+31+31),
5973 +                 (31+28+31+30+31+30+31+31+30),
5974 +                 (31+28+31+30+31+30+31+31+30+31),
5975 +                 (31+28+31+30+31+30+31+31+30+31+30),
5976 +               };
5977 +       register time_t work;
5978 +
5979 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
5980 +       work=timep%(SPD);
5981 +       r->tm_sec=work%60; work/=60;
5982 +       r->tm_min=work%60; r->tm_hour=work/60;
5983 +       work=timep/(SPD);
5984 +       r->tm_wday=(4+work)%7;
5985 +       for (i=1970; ; ++i) {
5986 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
5987 +               if (work>k)
5988 +                       work-=k;
5989 +               else
5990 +                       break;
5991 +       }
5992 +       r->tm_year=i-1900;
5993 +       for (i=11; i && __spm[i]>work; --i) ;
5994 +       r->tm_mon=i;
5995 +       r->tm_mday=work-__spm[i]+1;
5996 +}
5997 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.7/net/ipv4/netfilter/ipt_u32.c
5998 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c        1970-01-01 01:00:00.000000000 +0100
5999 +++ linux-2.6.7/net/ipv4/netfilter/ipt_u32.c    2004-09-07 12:38:33.377870496 +0200
6000 @@ -0,0 +1,211 @@
6001 +/* Kernel module to match u32 packet content. */
6002 +
6003 +/* 
6004 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
6005 +have specified values.  The specification of what to extract is general 
6006 +enough to find data at given offsets from tcp headers or payloads.
6007 +
6008 + --u32 tests
6009 + The argument amounts to a program in a small language described below.
6010 + tests := location = value |  tests && location = value
6011 + value := range | value , range
6012 + range := number | number : number
6013 +  a single number, n, is interpreted the same as n:n
6014 +  n:m is interpreted as the range of numbers >=n and <=m
6015 + location := number | location operator number
6016 + operator := & | << | >> | @
6017 +
6018 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
6019 + membership operator and the value syntax describes a set.  The @ operator
6020 + is what allows moving to the next header and is described further below.
6021 +
6022 + *** Until I can find out how to avoid it, there are some artificial limits
6023 + on the size of the tests:
6024 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
6025 + - no more than 10 ranges (and 9 commas) per value
6026 + - no more than 10 numbers (and 9 operators) per location
6027 +
6028 + To describe the meaning of location, imagine the following machine that
6029 + interprets it.  There are three registers:
6030 +  A is of type char*, initially the address of the IP header
6031 +  B and C are unsigned 32 bit integers, initially zero
6032 +
6033 +  The instructions are:
6034 +   number      B = number;
6035 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
6036 +   &number     C = C&number
6037 +   <<number    C = C<<number
6038 +   >>number    C = C>>number
6039 +   @number     A = A+C; then do the instruction number
6040 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
6041 +  Otherwise the result of the computation is the final value of C.
6042 +
6043 + Whitespace is allowed but not required in the tests.
6044 + However the characters that do occur there are likely to require
6045 + shell quoting, so it's a good idea to enclose the arguments in quotes.
6046 +
6047 +Example:
6048 + match IP packets with total length >= 256
6049 + The IP header contains a total length field in bytes 2-3.
6050 + --u32 "0&0xFFFF=0x100:0xFFFF" 
6051 + read bytes 0-3
6052 + AND that with FFFF (giving bytes 2-3),
6053 + and test whether that's in the range [0x100:0xFFFF]
6054 +
6055 +Example: (more realistic, hence more complicated)
6056 + match icmp packets with icmp type 0
6057 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
6058 + --u32 "6&0xFF=1 && ...
6059 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
6060 + Next test that it's not a fragment.
6061 +  (If so it might be part of such a packet but we can't always tell.)
6062 +  n.b. This test is generally needed if you want to match anything
6063 +  beyond the IP header.
6064 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
6065 + packet (not a fragment).  Alternatively, you can allow first fragments
6066 + by only testing the last 5 bits of byte 6.
6067 + ... 4&0x3FFF=0 && ...
6068 + Last test: the first byte past the IP header (the type) is 0
6069 + This is where we have to use the @syntax.  The length of the IP header
6070 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
6071 + IP header itself.
6072 + ... 0>>22&0x3C@0>>24=0"
6073 + The first 0 means read bytes 0-3,
6074 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
6075 +   the first byte, so only 22 bits is four times that plus a few more bits.
6076 + &3C then eliminates the two extra bits on the right and the first four 
6077 + bits of the first byte.
6078 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
6079 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
6080 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
6081 + @ means to use this number as a new offset into the packet, and read
6082 + four bytes starting from there.  This is the first 4 bytes of the icmp
6083 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
6084 + the value 24 to the right to throw out all but the first byte and compare
6085 + the result with 0.
6086 +
6087 +Example: 
6088 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
6089 + First we test that the packet is a tcp packet (similar to icmp).
6090 + --u32 "6&0xFF=6 && ...
6091 + Next, test that it's not a fragment (same as above).
6092 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
6093 + 0>>22&3C as above computes the number of bytes in the IP header.
6094 + @ makes this the new offset into the packet, which is the start of the
6095 + tcp header.  The length of the tcp header (again in 32 bit words) is
6096 + the left half of byte 12 of the tcp header.  The 12>>26&3C
6097 + computes this length in bytes (similar to the IP header before).
6098 + @ makes this the new offset, which is the start of the tcp payload.
6099 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
6100 + result is any of 1, 2, 5 or 8
6101 +*/
6102 +
6103 +#include <linux/module.h>
6104 +#include <linux/skbuff.h>
6105 +
6106 +#include <linux/netfilter_ipv4/ipt_u32.h>
6107 +#include <linux/netfilter_ipv4/ip_tables.h>
6108 +
6109 +/* #include <asm-i386/timex.h> for timing */
6110 +
6111 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
6112 +MODULE_DESCRIPTION("IP tables u32 matching module");
6113 +MODULE_LICENSE("GPL");
6114 +
6115 +static int
6116 +match(const struct sk_buff *skb,
6117 +      const struct net_device *in,
6118 +      const struct net_device *out,
6119 +      const void *matchinfo,
6120 +      int offset,
6121 +      const void *hdr,
6122 +      u_int16_t datalen,
6123 +      int *hotdrop)
6124 +{
6125 +       const struct ipt_u32 *data = matchinfo;
6126 +       int testind, i;
6127 +       unsigned char* origbase = (char*)skb->nh.iph;
6128 +       unsigned char* base = origbase;
6129 +       unsigned char* head = skb->head;
6130 +       unsigned char* end = skb->end;
6131 +       int nnums, nvals;
6132 +       u_int32_t pos, val;
6133 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
6134 +          cycles1 = get_cycles(); */
6135 +
6136 +       for (testind=0; testind < data->ntests; testind++) {
6137 +               base = origbase; /* reset for each test */
6138 +               pos = data->tests[testind].location[0].number;
6139 +               if (base+pos+3 > end || base+pos < head) 
6140 +                       return 0;
6141 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
6142 +                       (base[pos+2]<<8) + base[pos+3];
6143 +               nnums = data->tests[testind].nnums;
6144 +               for (i=1; i < nnums; i++) {
6145 +                       u_int32_t number = data->tests[testind].location[i].number;
6146 +                       switch (data->tests[testind].location[i].nextop) {
6147 +                       case IPT_U32_AND: 
6148 +                               val = val & number; 
6149 +                               break;
6150 +                       case IPT_U32_LEFTSH: 
6151 +                               val = val << number;
6152 +                               break;
6153 +                       case IPT_U32_RIGHTSH: 
6154 +                               val = val >> number; 
6155 +                               break;
6156 +                       case IPT_U32_AT:
6157 +                               base = base + val;
6158 +                               pos = number;
6159 +                               if (base+pos+3 > end || base+pos < head) 
6160 +                                       return 0;
6161 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
6162 +                                       (base[pos+2]<<8) + base[pos+3];
6163 +                               break;
6164 +                       }
6165 +               }
6166 +               nvals = data->tests[testind].nvalues;
6167 +               for (i=0; i < nvals; i++) {
6168 +                       if ((data->tests[testind].value[i].min <= val) &&
6169 +                           (val <= data->tests[testind].value[i].max)) {
6170 +                               break;
6171 +                       }
6172 +               }
6173 +               if (i >= data->tests[testind].nvalues) {
6174 +                       /* cycles2 = get_cycles(); 
6175 +                          printk("failed %d in %d cycles\n", testind, 
6176 +                                 cycles2-cycles1); */
6177 +                       return 0;
6178 +               }
6179 +       }
6180 +       /* cycles2 = get_cycles();
6181 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
6182 +       return 1;
6183 +}
6184 +
6185 +static int
6186 +checkentry(const char *tablename,
6187 +           const struct ipt_ip *ip,
6188 +           void *matchinfo,
6189 +           unsigned int matchsize,
6190 +           unsigned int hook_mask)
6191 +{
6192 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
6193 +               return 0;
6194 +       return 1;
6195 +}
6196 +
6197 +static struct ipt_match u32_match
6198 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
6199 +
6200 +static int __init init(void)
6201 +{
6202 +       return ipt_register_match(&u32_match);
6203 +}
6204 +
6205 +static void __exit fini(void)
6206 +{
6207 +       ipt_unregister_match(&u32_match);
6208 +}
6209 +
6210 +module_init(init);
6211 +module_exit(fini);
6212 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Kconfig linux-2.6.7/net/ipv6/netfilter/Kconfig
6213 --- linux-2.6.7.org/net/ipv6/netfilter/Kconfig  2004-09-07 12:07:46.626619360 +0200
6214 +++ linux-2.6.7/net/ipv6/netfilter/Kconfig      2004-09-07 12:33:17.553883040 +0200
6215 @@ -230,5 +230,60 @@
6216           <file:Documentation/modules.txt>.  If unsure, say `N'.
6217           help
6218  
6219 +config IP6_NF_TARGET_HL
6220 +       tristate  'HL target support'
6221 +       depends on IP6_NF_MANGLE
6222 +       help
6223 +         This option adds a `HL' target, which allows you to modify the value of
6224 +         IPv6 Hop Limit field.
6225 +       
6226 +         If you want to compile it as a module, say M here and read
6227 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
6228 +
6229 +config IP6_NF_TARGET_REJECT
6230 +       tristate  'REJECT target support'
6231 +       depends on IP6_NF_FILTER
6232 +       help
6233 +         The REJECT target allows a filtering rule to specify that an ICMPv6
6234 +         error should be issued in response to an incoming packet, rather
6235 +         than silently being dropped.
6236 +       
6237 +         If you want to compile it as a module, say M here and read
6238 +         Documentation/modules.txt.  If unsure, say `N'.
6239 +
6240 +config IP6_NF_MATCH_FUZZY
6241 +       tristate  'Fuzzy match support'
6242 +       depends on IP6_NF_FILTER
6243 +       help
6244 +         This option adds a `fuzzy' match, which allows you to match
6245 +         packets according to a fuzzy logic based law.
6246 +       
6247 +         If you want to compile it as a module, say M here and read
6248 +         Documentation/modules.txt.  If unsure, say `N'.
6249 +
6250 +config IP6_NF_MATCH_NTH
6251 +       tristate  'Nth match support'
6252 +       depends on IP6_NF_IPTABLES
6253 +       help
6254 +         This option adds a `Nth' match, which allow you to make
6255 +         rules that match every Nth packet.  By default there are 
6256 +         16 different counters.
6257 +       
6258 +         [options]
6259 +          --every     Nth              Match every Nth packet
6260 +         [--counter]  num              Use counter 0-15 (default:0)
6261 +         [--start]    num              Initialize the counter at the number 'num'
6262 +                                       instead of 0. Must be between 0 and Nth-1
6263 +         [--packet]   num              Match on 'num' packet. Must be between 0
6264 +                                       and Nth-1.
6265 +       
6266 +                                       If --packet is used for a counter than
6267 +                                       there must be Nth number of --packet
6268 +                                       rules, covering all values between 0 and
6269 +                                       Nth-1 inclusively.
6270 +        
6271 +         If you want to compile it as a module, say M here and read
6272 +         Documentation/modules.txt.  If unsure, say `N'.
6273 +
6274  endmenu
6275  
6276 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Makefile linux-2.6.7/net/ipv6/netfilter/Makefile
6277 --- linux-2.6.7.org/net/ipv6/netfilter/Makefile 2004-09-07 12:07:46.626619360 +0200
6278 +++ linux-2.6.7/net/ipv6/netfilter/Makefile     2004-09-07 12:33:17.554882888 +0200
6279 @@ -8,6 +8,7 @@
6280  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
6281  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
6282  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
6283 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
6284  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
6285  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
6286  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
6287 @@ -21,5 +22,8 @@
6288  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
6289  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
6290  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
6291 +
6292 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
6293 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
6294  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
6295  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
6296 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c
6297 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c        1970-01-01 01:00:00.000000000 +0100
6298 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c    2004-09-07 12:33:06.517560816 +0200
6299 @@ -0,0 +1,105 @@
6300 +/* 
6301 + * Hop Limit modification target for ip6tables
6302 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
6303 + * Based on HW's TTL module
6304 + *
6305 + * This software is distributed under the terms of GNU GPL
6306 + */
6307 +
6308 +#include <linux/module.h>
6309 +#include <linux/skbuff.h>
6310 +#include <linux/ip.h>
6311 +
6312 +#include <linux/netfilter_ipv6/ip6_tables.h>
6313 +#include <linux/netfilter_ipv6/ip6t_HL.h>
6314 +
6315 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
6316 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
6317 +MODULE_LICENSE("GPL");
6318 +
6319 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
6320 +               const struct net_device *in, const struct net_device *out,
6321 +               const void *targinfo, void *userinfo)
6322 +{
6323 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
6324 +       const struct ip6t_HL_info *info = targinfo;
6325 +       u_int16_t diffs[2];
6326 +       int new_hl;
6327 +                        
6328 +       switch (info->mode) {
6329 +               case IP6T_HL_SET:
6330 +                       new_hl = info->hop_limit;
6331 +                       break;
6332 +               case IP6T_HL_INC:
6333 +                       new_hl = ip6h->hop_limit + info->hop_limit;
6334 +                       if (new_hl > 255)
6335 +                               new_hl = 255;
6336 +                       break;
6337 +               case IP6T_HL_DEC:
6338 +                       new_hl = ip6h->hop_limit - info->hop_limit;
6339 +                       if (new_hl < 0)
6340 +                               new_hl = 0;
6341 +                       break;
6342 +               default:
6343 +                       new_hl = ip6h->hop_limit;
6344 +                       break;
6345 +       }
6346 +
6347 +       if (new_hl != ip6h->hop_limit) {
6348 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
6349 +               ip6h->hop_limit = new_hl;
6350 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
6351 +       }
6352 +
6353 +       return IP6T_CONTINUE;
6354 +}
6355 +
6356 +static int ip6t_hl_checkentry(const char *tablename,
6357 +               const struct ip6t_entry *e,
6358 +               void *targinfo,
6359 +               unsigned int targinfosize,
6360 +               unsigned int hook_mask)
6361 +{
6362 +       struct ip6t_HL_info *info = targinfo;
6363 +
6364 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
6365 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
6366 +                               targinfosize,
6367 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
6368 +               return 0;       
6369 +       }       
6370 +
6371 +       if (strcmp(tablename, "mangle")) {
6372 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6373 +               return 0;
6374 +       }
6375 +
6376 +       if (info->mode > IP6T_HL_MAXMODE) {
6377 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
6378 +                       info->mode);
6379 +               return 0;
6380 +       }
6381 +
6382 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
6383 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
6384 +               return 0;
6385 +       }
6386 +       
6387 +       return 1;
6388 +}
6389 +
6390 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
6391 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
6392 +
6393 +static int __init init(void)
6394 +{
6395 +       return ip6t_register_target(&ip6t_HL);
6396 +}
6397 +
6398 +static void __exit fini(void)
6399 +{
6400 +       ip6t_unregister_target(&ip6t_HL);
6401 +}
6402 +
6403 +module_init(init);
6404 +module_exit(fini);
6405 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c
6406 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c    1970-01-01 01:00:00.000000000 +0100
6407 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c        2004-09-07 12:33:08.255296640 +0200
6408 @@ -0,0 +1,458 @@
6409 +/*
6410 + * IP6 tables REJECT target module
6411 + * Linux INET6 implementation
6412 + *
6413 + * Copyright (C)2003 USAGI/WIDE Project
6414 + *
6415 + * Authors:
6416 + *     Yasuyuki Kozakai        <yasuyuki.kozakai@toshiba.co.jp>
6417 + *
6418 + * Based on net/ipv4/netfilter/ipt_REJECT.c
6419 + *
6420 + * This program is free software; you can redistribute it and/or
6421 + * modify it under the terms of the GNU General Public License
6422 + * as published by the Free Software Foundation; either version
6423 + * 2 of the License, or (at your option) any later version.
6424 + */
6425 +
6426 +#include <linux/config.h>
6427 +#include <linux/module.h>
6428 +#include <linux/skbuff.h>
6429 +#include <linux/icmpv6.h>
6430 +#include <net/ipv6.h>
6431 +#include <net/tcp.h>
6432 +#include <net/icmp.h>
6433 +#include <net/ip6_fib.h>
6434 +#include <net/ip6_route.h>
6435 +#include <net/flow.h>
6436 +#include <linux/netfilter_ipv6/ip6_tables.h>
6437 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
6438 +
6439 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
6440 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
6441 +MODULE_LICENSE("GPL");
6442 +
6443 +#if 0
6444 +#define DEBUGP printk
6445 +#else
6446 +#define DEBUGP(format, args...)
6447 +#endif
6448 +
6449 +#if 0
6450 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
6451 +{
6452 +       void (*attach)(struct sk_buff *, struct nf_ct_info *);
6453 +       if (nfct && (attach = ip6_ct_attach) != NULL) {
6454 +               mb();
6455 +               attach(new_skb, nfct);
6456 +       }
6457 +}
6458 +#endif
6459 +
6460 +static int maybe_reroute(struct sk_buff *skb)
6461 +{
6462 +       if (skb->nfcache & NFC_ALTERED){
6463 +               if (ip6_route_me_harder(skb) != 0){
6464 +                       kfree_skb(skb);
6465 +                       return -EINVAL;
6466 +               }
6467 +       }
6468 +
6469 +       return dst_output(skb);
6470 +}
6471 +
6472 +/* Send RST reply */
6473 +static void send_reset(struct sk_buff *oldskb)
6474 +{
6475 +       struct sk_buff *nskb;
6476 +       struct tcphdr otcph, *tcph;
6477 +       unsigned int otcplen, tcphoff, hh_len;
6478 +       int needs_ack;
6479 +       struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
6480 +       struct dst_entry *dst = NULL;
6481 +       u8 proto;
6482 +       struct flowi fl;
6483 +       proto = oip6h->nexthdr;
6484 +       int err;
6485 +
6486 +       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
6487 +           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
6488 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6489 +               return;
6490 +       }
6491 +
6492 +       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
6493 +                                  &proto, oldskb->len - ((u8*)(oip6h+1)
6494 +                                                         - oldskb->data));
6495 +
6496 +       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
6497 +               DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
6498 +               return;
6499 +       }
6500 +
6501 +       otcplen = oldskb->len - tcphoff;
6502 +
6503 +       /* IP header checks: fragment, too short. */
6504 +       if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
6505 +               DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
6506 +                       proto, otcplen);
6507 +               return;
6508 +       }
6509 +
6510 +       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
6511 +               if (net_ratelimit())
6512 +                       printk("ip6t_REJECT: Can't copy tcp header\n");
6513 +               return;
6514 +       }
6515 +
6516 +       /* No RST for RST. */
6517 +       if (otcph.rst) {
6518 +               DEBUGP("ip6t_REJECT: RST is set\n");
6519 +               return;
6520 +       }
6521 +
6522 +       /* Check checksum. */
6523 +       if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
6524 +                           skb_checksum(oldskb, tcphoff, otcplen, 0))) {
6525 +               DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
6526 +               return;
6527 +       }
6528 +
6529 +       memset(&fl, 0, sizeof(fl));
6530 +       fl.proto = IPPROTO_TCP;
6531 +       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
6532 +       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
6533 +       fl.fl_ip_sport = otcph.dest;
6534 +       fl.fl_ip_dport = otcph.source;
6535 +       err = ip6_dst_lookup(NULL, &dst, &fl);
6536 +       if (err) {
6537 +               if (net_ratelimit())
6538 +                       printk("ip6t_REJECT: can't find dst. err = %d\n", err);
6539 +               return;
6540 +       }
6541 +
6542 +       hh_len = (dst->dev->hard_header_len + 15)&~15;
6543 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
6544 +                        + sizeof(struct tcphdr) + dst->trailer_len,
6545 +                        GFP_ATOMIC);
6546 +
6547 +       if (!nskb) {
6548 +               if (net_ratelimit())
6549 +                       printk("ip6t_REJECT: Can't alloc skb\n");
6550 +               dst_release(dst);
6551 +               return;
6552 +       }
6553 +
6554 +       nskb->dst = dst;
6555 +       dst_hold(dst);
6556 +
6557 +       skb_reserve(nskb, hh_len + dst->header_len);
6558 +
6559 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6560 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
6561 +       ip6h->version = 6;
6562 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6563 +       ip6h->nexthdr = IPPROTO_TCP;
6564 +       ip6h->payload_len = htons(sizeof(struct tcphdr));
6565 +       ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
6566 +       ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
6567 +
6568 +       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
6569 +       /* Truncate to length (no data) */
6570 +       tcph->doff = sizeof(struct tcphdr)/4;
6571 +       tcph->source = otcph.dest;
6572 +       tcph->dest = otcph.source;
6573 +
6574 +       if (otcph.ack) {
6575 +               needs_ack = 0;
6576 +               tcph->seq = otcph.ack_seq;
6577 +               tcph->ack_seq = 0;
6578 +       } else {
6579 +               needs_ack = 1;
6580 +               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
6581 +                                     + otcplen - (otcph.doff<<2));
6582 +               tcph->seq = 0;
6583 +       }
6584 +
6585 +       /* Reset flags */
6586 +       ((u_int8_t *)tcph)[13] = 0;
6587 +       tcph->rst = 1;
6588 +       tcph->ack = needs_ack;
6589 +       tcph->window = 0;
6590 +       tcph->urg_ptr = 0;
6591 +       tcph->check = 0;
6592 +
6593 +       /* Adjust TCP checksum */
6594 +       tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
6595 +                                     &nskb->nh.ipv6h->daddr,
6596 +                                     sizeof(struct tcphdr), IPPROTO_TCP,
6597 +                                     csum_partial((char *)tcph,
6598 +                                                  sizeof(struct tcphdr), 0));
6599 +
6600 +#if 0
6601 +       connection_attach(nskb, oldskb->nfct);
6602 +#endif
6603 +
6604 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6605 +               maybe_reroute);
6606 +
6607 +       dst_release(dst);
6608 +}
6609 +
6610 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
6611 +{
6612 +       struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
6613 +       struct icmp6hdr *icmp6h;
6614 +       struct dst_entry *dst = NULL;
6615 +       struct rt6_info *rt;
6616 +       int tmo;
6617 +       __u32 csum;
6618 +       unsigned int len, datalen, hh_len;
6619 +       int saddr_type, daddr_type;
6620 +       unsigned int ptr, ip6off;
6621 +       u8 proto;
6622 +       struct flowi fl;
6623 +       struct sk_buff *nskb;
6624 +       char *data;
6625 +
6626 +       saddr_type = ipv6_addr_type(&hdr->saddr);
6627 +       daddr_type = ipv6_addr_type(&hdr->daddr);
6628 +
6629 +       if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
6630 +           (!(daddr_type & IPV6_ADDR_UNICAST))) {
6631 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6632 +               return;
6633 +       }
6634 +
6635 +       ip6off = skb_in->nh.raw - skb_in->data;
6636 +       proto = hdr->nexthdr;
6637 +       ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
6638 +                              skb_in->len - ip6off);
6639 +
6640 +       if ((ptr < 0) || (ptr > skb_in->len)) {
6641 +               ptr = ip6off + sizeof(struct ipv6hdr);
6642 +               proto = hdr->nexthdr;
6643 +       } else if (proto == IPPROTO_ICMPV6) {
6644 +                u8 type;
6645 +
6646 +                if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
6647 +                                                     icmp6_type), &type, 1)) {
6648 +                       DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
6649 +                       return;
6650 +               }
6651 +
6652 +               if (!(type & ICMPV6_INFOMSG_MASK)) {
6653 +                       DEBUGP("ip6t_REJECT: no reply to icmp error\n");
6654 +                       return;
6655 +               }
6656 +        } else if (proto == IPPROTO_UDP) {
6657 +               int plen = skb_in->len - (ptr - ip6off);
6658 +               uint16_t check;
6659 +
6660 +               if (plen < sizeof(struct udphdr)) {
6661 +                       DEBUGP("ip6t_REJECT: too short\n");
6662 +                       return;
6663 +               }
6664 +
6665 +               if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
6666 +                                 &check, 2)) {
6667 +                       if (net_ratelimit())
6668 +                               printk("ip6t_REJECT: can't get copy from skb");
6669 +                       return;
6670 +               }
6671 +
6672 +               if (check &&
6673 +                   csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
6674 +                                   IPPROTO_UDP,
6675 +                                   skb_checksum(skb_in, ptr, plen, 0))) {
6676 +                       DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
6677 +                       return;
6678 +               }
6679 +       }
6680 +
6681 +       memset(&fl, 0, sizeof(fl));
6682 +       fl.proto = IPPROTO_ICMPV6;
6683 +       ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
6684 +       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
6685 +       fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
6686 +       fl.fl_icmp_code = code;
6687 +
6688 +       if (ip6_dst_lookup(NULL, &dst, &fl)) {
6689 +               return;
6690 +       }
6691 +
6692 +       rt = (struct rt6_info *)dst;
6693 +       tmo = 1*HZ;
6694 +
6695 +       if (rt->rt6i_dst.plen < 128)
6696 +               tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
6697 +
6698 +       if (!xrlim_allow(dst, tmo)) {
6699 +               if (net_ratelimit())
6700 +                       printk("ip6t_REJECT: rate limitted\n");
6701 +               goto dst_release_out;
6702 +       }
6703 +
6704 +       len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
6705 +
6706 +       if (len > dst_pmtu(dst))
6707 +               len = dst_pmtu(dst);
6708 +       if (len > IPV6_MIN_MTU)
6709 +               len = IPV6_MIN_MTU;
6710 +
6711 +       datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
6712 +       hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
6713 +
6714 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
6715 +                        GFP_ATOMIC);
6716 +
6717 +       if (!nskb) {
6718 +               if (net_ratelimit())
6719 +                       printk("ip6t_REJECT: can't alloc skb\n");
6720 +               goto dst_release_out;
6721 +       }
6722 +
6723 +       nskb->priority = 0;
6724 +       nskb->dst = dst;
6725 +       dst_hold(dst);
6726 +
6727 +       skb_reserve(nskb, hh_len + dst->header_len);
6728 +
6729 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6730 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
6731 +       ip6h->version = 6;
6732 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6733 +       ip6h->nexthdr = IPPROTO_ICMPV6;
6734 +       ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
6735 +       ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
6736 +       ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
6737 +
6738 +       icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
6739 +       icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
6740 +       icmp6h->icmp6_code = code;
6741 +       icmp6h->icmp6_cksum = 0;
6742 +
6743 +       data = skb_put(nskb, datalen);
6744 +
6745 +       csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
6746 +       csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
6747 +       icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
6748 +                                            datalen + sizeof(struct icmp6hdr),
6749 +                                            IPPROTO_ICMPV6, csum);
6750 +
6751 +#if 0
6752 +       connection_attach(nskb, skb_in->nfct);
6753 +#endif
6754 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6755 +               maybe_reroute);
6756 +
6757 +dst_release_out:
6758 +       dst_release(dst);
6759 +}
6760 +
6761 +static unsigned int reject6_target(struct sk_buff **pskb,
6762 +                          unsigned int hooknum,
6763 +                          const struct net_device *in,
6764 +                          const struct net_device *out,
6765 +                          const void *targinfo,
6766 +                          void *userinfo)
6767 +{
6768 +       const struct ip6t_reject_info *reject = targinfo;
6769 +
6770 +       DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
6771 +       /* WARNING: This code causes reentry within ip6tables.
6772 +          This means that the ip6tables jump stack is now crap.  We
6773 +          must return an absolute verdict. --RR */
6774 +       switch (reject->with) {
6775 +       case IP6T_ICMP6_NO_ROUTE:
6776 +               send_unreach(*pskb, ICMPV6_NOROUTE);
6777 +               break;
6778 +       case IP6T_ICMP6_ADM_PROHIBITED:
6779 +               send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
6780 +               break;
6781 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
6782 +               send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
6783 +               break;
6784 +       case IP6T_ICMP6_ADDR_UNREACH:
6785 +               send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
6786 +               break;
6787 +       case IP6T_ICMP6_PORT_UNREACH:
6788 +               send_unreach(*pskb, ICMPV6_PORT_UNREACH);
6789 +               break;
6790 +       case IP6T_ICMP6_ECHOREPLY:
6791 +               /* Do nothing */
6792 +               break;
6793 +       case IP6T_TCP_RESET:
6794 +               send_reset(*pskb);
6795 +               break;
6796 +       default:
6797 +               if (net_ratelimit())
6798 +                       printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
6799 +               break;
6800 +       }
6801 +
6802 +       return NF_DROP;
6803 +}
6804 +
6805 +static int check(const char *tablename,
6806 +                const struct ip6t_entry *e,
6807 +                void *targinfo,
6808 +                unsigned int targinfosize,
6809 +                unsigned int hook_mask)
6810 +{
6811 +       const struct ip6t_reject_info *rejinfo = targinfo;
6812 +
6813 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
6814 +               DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
6815 +               return 0;
6816 +       }
6817 +
6818 +       /* Only allow these for packet filtering. */
6819 +       if (strcmp(tablename, "filter") != 0) {
6820 +               DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
6821 +               return 0;
6822 +       }
6823 +
6824 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
6825 +                          | (1 << NF_IP6_FORWARD)
6826 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
6827 +               DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
6828 +               return 0;
6829 +       }
6830 +
6831 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
6832 +               printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
6833 +               return 0;
6834 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
6835 +               /* Must specify that it's a TCP packet */
6836 +               if (e->ipv6.proto != IPPROTO_TCP
6837 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
6838 +                       DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
6839 +                       return 0;
6840 +               }
6841 +       }
6842 +
6843 +       return 1;
6844 +}
6845 +
6846 +static struct ip6t_target ip6t_reject_reg = {
6847 +       .name           = "REJECT",
6848 +       .target         = reject6_target,
6849 +       .checkentry     = check,
6850 +       .me             = THIS_MODULE
6851 +};
6852 +
6853 +static int __init init(void)
6854 +{
6855 +       if (ip6t_register_target(&ip6t_reject_reg))
6856 +               return -EINVAL;
6857 +       return 0;
6858 +}
6859 +
6860 +static void __exit fini(void)
6861 +{
6862 +       ip6t_unregister_target(&ip6t_reject_reg);
6863 +}
6864 +
6865 +module_init(init);
6866 +module_exit(fini);
6867 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c
6868 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c     1970-01-01 01:00:00.000000000 +0100
6869 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c 2004-09-07 12:33:12.081714936 +0200
6870 @@ -0,0 +1,189 @@
6871 +/*
6872 + * This module implements a simple TSK FLC
6873 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
6874 + * to limit , in an adaptive and flexible way , the packet rate crossing
6875 + * a given stream . It serves as an initial and very simple (but effective)
6876 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
6877 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
6878 + * into our code in a precise , adaptive and efficient manner.
6879 + *  The goal is very similar to that of "limit" match , but using techniques of
6880 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
6881 + * avoiding over and undershoots - and stuff like that .
6882 + *
6883 + *
6884 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
6885 + * 2002-08-17  : Changed to eliminate floating point operations .
6886 + * 2002-08-23  : Coding style changes .
6887 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
6888 + */
6889 +
6890 +#include <linux/module.h>
6891 +#include <linux/skbuff.h>
6892 +#include <linux/ipv6.h>
6893 +#include <linux/random.h>
6894 +#include <net/tcp.h>
6895 +#include <linux/spinlock.h>
6896 +#include <linux/netfilter_ipv6/ip6_tables.h>
6897 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
6898 +
6899 +/*
6900 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
6901 + Expressed in percentage
6902 +*/
6903 +
6904 +#define PAR_LOW                1/100
6905 +#define PAR_HIGH       1
6906 +
6907 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
6908 +
6909 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
6910 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
6911 +MODULE_LICENSE("GPL");
6912 +
6913 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6914 +{
6915 +       if (tx >= maxi) return 100;
6916 +
6917 +       if (tx <= mini) return 0;
6918 +
6919 +       return ((100 * (tx-mini)) / (maxi-mini));
6920 +}
6921 +
6922 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6923 +{
6924 +       if (tx <= mini) return 100;
6925 +
6926 +       if (tx >= maxi) return 0;
6927 +
6928 +       return ((100 * (maxi - tx)) / (maxi - mini));
6929 +
6930 +}
6931 +
6932 +static int
6933 +ip6t_fuzzy_match(const struct sk_buff *pskb,
6934 +              const struct net_device *in,
6935 +              const struct net_device *out,
6936 +              const void *matchinfo,
6937 +              int offset,
6938 +              const void *hdr,
6939 +              u_int16_t datalen,
6940 +              int *hotdrop)
6941 +{
6942 +       /* From userspace */
6943 +
6944 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
6945 +
6946 +       u_int8_t random_number;
6947 +       unsigned long amount;
6948 +       u_int8_t howhigh, howlow;
6949 +
6950 +
6951 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
6952 +
6953 +       info->bytes_total += pskb->len;
6954 +       info->packets_total++;
6955 +
6956 +       info->present_time = jiffies;
6957 +
6958 +       if (info->present_time >= info->previous_time)
6959 +               amount = info->present_time - info->previous_time;
6960 +       else {
6961 +               /* There was a transition : I choose to re-sample
6962 +                  and keep the old acceptance rate...
6963 +               */
6964 +
6965 +               amount = 0;
6966 +               info->previous_time = info->present_time;
6967 +               info->bytes_total = info->packets_total = 0;
6968 +            };
6969 +
6970 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
6971 +
6972 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
6973 +                                       / amount);
6974 +
6975 +               info->previous_time = info->present_time;
6976 +               info->bytes_total = info->packets_total = 0;
6977 +
6978 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
6979 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
6980 +
6981 +               info->acceptance_rate = (u_int8_t) \
6982 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
6983 +
6984 +       /* In fact, the above defuzzification would require a denominator
6985 +        * proportional to (howhigh+howlow) but, in this particular case,
6986 +        * that expression is constant.
6987 +        * An imediate consequence is that it is not necessary to call
6988 +        * both mf_high and mf_low - but to keep things understandable,
6989 +        * I did so.
6990 +        */
6991 +
6992 +       }
6993 +
6994 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
6995 +
6996 +
6997 +       if (info->acceptance_rate < 100)
6998 +       {
6999 +               get_random_bytes((void *)(&random_number), 1);
7000 +
7001 +               /*  If within the acceptance , it can pass => don't match */
7002 +               if (random_number <= (255 * info->acceptance_rate) / 100)
7003 +                       return 0;
7004 +               else
7005 +                       return 1; /* It can't pass (It matches) */
7006 +       };
7007 +
7008 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
7009 +
7010 +}
7011 +
7012 +static int
7013 +ip6t_fuzzy_checkentry(const char *tablename,
7014 +                  const struct ip6t_ip6 *ip,
7015 +                  void *matchinfo,
7016 +                  unsigned int matchsize,
7017 +                  unsigned int hook_mask)
7018 +{
7019 +
7020 +       const struct ip6t_fuzzy_info *info = matchinfo;
7021 +
7022 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
7023 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
7024 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
7025 +               return 0;
7026 +       }
7027 +
7028 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
7029 +        || (info->minimum_rate >= info->maximum_rate)) {
7030 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
7031 +               return 0;
7032 +       }
7033 +
7034 +       return 1;
7035 +}
7036 +
7037 +static struct ip6t_match ip6t_fuzzy_reg = {
7038 +       {NULL, NULL},
7039 +       "fuzzy",
7040 +       ip6t_fuzzy_match,
7041 +       ip6t_fuzzy_checkentry,
7042 +       NULL,
7043 +       THIS_MODULE };
7044 +
7045 +static int __init init(void)
7046 +{
7047 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
7048 +               return -EINVAL;
7049 +
7050 +       return 0;
7051 +}
7052 +
7053 +static void __exit fini(void)
7054 +{
7055 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
7056 +}
7057 +
7058 +module_init(init);
7059 +module_exit(fini);
7060 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c
7061 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c       1970-01-01 01:00:00.000000000 +0100
7062 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c   2004-09-07 12:33:17.548883800 +0200
7063 @@ -0,0 +1,173 @@
7064 +/*
7065 +  This is a module which is used for match support for every Nth packet
7066 +  This file is distributed under the terms of the GNU General Public
7067 +  License (GPL). Copies of the GPL can be obtained from:
7068 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
7069 +
7070 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
7071 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
7072 +        * added support for multiple counters
7073 +        * added support for matching on individual packets
7074 +          in the counter cycle
7075 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
7076 +
7077 +*/
7078 +
7079 +#include <linux/module.h>
7080 +#include <linux/skbuff.h>
7081 +#include <linux/ip.h>
7082 +#include <net/tcp.h>
7083 +#include <linux/spinlock.h>
7084 +#include <linux/netfilter_ipv6/ip6_tables.h>
7085 +#include <linux/netfilter_ipv6/ip6t_nth.h>
7086 +
7087 +MODULE_LICENSE("GPL");
7088 +
7089 +/*
7090 + * State information.
7091 + */
7092 +struct state {
7093 +       spinlock_t lock;
7094 +       u_int16_t number;
7095 +};
7096 +
7097 +static struct state states[IP6T_NTH_NUM_COUNTERS];
7098 +
7099 +static int
7100 +ip6t_nth_match(const struct sk_buff *pskb,
7101 +             const struct net_device *in,
7102 +             const struct net_device *out,
7103 +             const void *matchinfo,
7104 +             int offset,
7105 +             const void *hdr,
7106 +             u_int16_t datalen,
7107 +             int *hotdrop)
7108 +{
7109 +       /* Parameters from userspace */
7110 +       const struct ip6t_nth_info *info = matchinfo;
7111 +        unsigned counter = info->counter;
7112 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
7113 +       {
7114 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
7115 +               return 0;
7116 +        };
7117 +
7118 +        spin_lock(&states[counter].lock);
7119 +
7120 +        /* Are we matching every nth packet?*/
7121 +        if (info->packet == 0xFF)
7122 +        {
7123 +               /* We're matching every nth packet and only every nth packet*/
7124 +               /* Do we match or invert match? */
7125 +               if (info->not == 0)
7126 +               {
7127 +                       if (states[counter].number == 0)
7128 +                       {
7129 +                               ++states[counter].number;
7130 +                               goto match;
7131 +                       }
7132 +                       if (states[counter].number >= info->every)
7133 +                               states[counter].number = 0; /* reset the counter */
7134 +                       else
7135 +                               ++states[counter].number;
7136 +                       goto dontmatch;
7137 +               }
7138 +               else
7139 +               {
7140 +                       if (states[counter].number == 0)
7141 +                       {
7142 +                               ++states[counter].number;
7143 +                               goto dontmatch;
7144 +                       }
7145 +                       if (states[counter].number >= info->every)
7146 +                               states[counter].number = 0;
7147 +                       else
7148 +                               ++states[counter].number;
7149 +                       goto match;
7150 +               }
7151 +        }
7152 +        else
7153 +        {
7154 +               /* We're using the --packet, so there must be a rule for every value */
7155 +               if (states[counter].number == info->packet)
7156 +               {
7157 +                       /* only increment the counter when a match happens */
7158 +                       if (states[counter].number >= info->every)
7159 +                               states[counter].number = 0; /* reset the counter */
7160 +                       else
7161 +                               ++states[counter].number;
7162 +                       goto match;
7163 +               }
7164 +               else
7165 +                       goto dontmatch;
7166 +       }
7167 +
7168 + dontmatch:
7169 +       /* don't match */
7170 +       spin_unlock(&states[counter].lock);
7171 +       return 0;
7172 +
7173 + match:
7174 +       spin_unlock(&states[counter].lock);
7175 +       return 1;
7176 +}
7177 +
7178 +static int
7179 +ip6t_nth_checkentry(const char *tablename,
7180 +                  const struct ip6t_ip6 *e,
7181 +                  void *matchinfo,
7182 +                  unsigned int matchsize,
7183 +                  unsigned int hook_mask)
7184 +{
7185 +       /* Parameters from userspace */
7186 +       const struct ip6t_nth_info *info = matchinfo;
7187 +        unsigned counter = info->counter;
7188 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
7189 +       {
7190 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
7191 +                       return 0;
7192 +               };
7193 +
7194 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
7195 +               printk("nth: matchsize %u != %u\n", matchsize,
7196 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
7197 +               return 0;
7198 +       }
7199 +
7200 +       states[counter].number = info->startat;
7201 +
7202 +       return 1;
7203 +}
7204 +
7205 +static struct ip6t_match ip6t_nth_reg = { 
7206 +       {NULL, NULL},
7207 +       "nth",
7208 +       ip6t_nth_match,
7209 +       ip6t_nth_checkentry,
7210 +       NULL,
7211 +       THIS_MODULE };
7212 +
7213 +static int __init init(void)
7214 +{
7215 +       unsigned counter;
7216 +        memset(&states, 0, sizeof(states));
7217 +       if (ip6t_register_match(&ip6t_nth_reg))
7218 +               return -EINVAL;
7219 +
7220 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
7221 +       {
7222 +               spin_lock_init(&(states[counter].lock));
7223 +        };
7224 +
7225 +       printk("ip6t_nth match loaded\n");
7226 +       return 0;
7227 +}
7228 +
7229 +static void __exit fini(void)
7230 +{
7231 +       ip6t_unregister_match(&ip6t_nth_reg);
7232 +       printk("ip6t_nth match unloaded\n");
7233 +}
7234 +
7235 +module_init(init);
7236 +module_exit(fini);
This page took 1.05234 seconds and 3 git commands to generate.