1 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h
2 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h 2004-04-29 09:49:29.000000000 +0200
8 +/***************************************************************************/
9 +/* This program is free software; you can redistribute it and/or modify */
10 +/* it under the terms of the GNU General Public License as published by */
11 +/* the Free Software Foundation; either version 2 of the License, or */
12 +/* (at your option) any later version. */
14 +/* This program is distributed in the hope that it will be useful, */
15 +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16 +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
17 +/* GNU General Public License for more details. */
19 +/* You should have received a copy of the GNU General Public License */
20 +/* along with this program; if not, write to the Free Software */
21 +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
22 +/***************************************************************************/
24 +/* A sockopt of such quality has hardly ever been seen before on the open
25 + * market! This little beauty, hardly ever used: above 64, so it's
26 + * traditionally used for firewalling, not touched (even once!) by the
27 + * 2.0, 2.2 and 2.4 kernels!
29 + * Comes with its own certificate of authenticity, valid anywhere in the
34 +#define SO_IP_POOL 81
36 +typedef int ip_pool_t; /* pool index */
37 +#define IP_POOL_NONE ((ip_pool_t)-1)
39 +struct ip_pool_request {
46 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
48 +#define IP_POOL_BAD001 0x00000010
50 +#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
51 +#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
52 +#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
53 +#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
54 +#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
55 +#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
56 +#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
57 +#define IP_POOL_USAGE 0x00000018 /* result in addr */
58 +#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
62 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
63 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
64 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
68 +#endif /*_IP_POOL_H*/
69 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h
70 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
71 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h 2004-04-29 09:47:00.000000000 +0200
77 +#define MASK(x,y) (x & y)
78 +#define MASK_SET(x,y) x |= y
79 +#define MASK_UNSET(x,y) x &= ~y
81 +#define USE_MARK 0x00000001
82 +#define USE_DROP 0x00000002
83 +#define USE_SIZE 0x00000004
96 + char iface[IFNAMSIZ];
99 +#endif /*_IPT_FWMON_H*/
100 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h
101 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
102 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h 2004-04-29 09:47:42.000000000 +0200
104 +/* TTL modification module for IP tables
105 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
116 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
118 +struct ipt_TTL_info {
125 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h
126 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
127 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-04-29 09:47:49.000000000 +0200
129 +#ifndef _IPT_CONNLIMIT_H
130 +#define _IPT_CONNLIMIT_H
132 +struct ipt_connlimit_data;
134 +struct ipt_connlimit_info {
138 + struct ipt_connlimit_data *data;
140 +#endif /* _IPT_CONNLIMIT_H */
141 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h
142 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
143 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-04-29 09:48:04.000000000 +0200
145 +#ifndef _IPT_DSTLIMIT_H
146 +#define _IPT_DSTLIMIT_H
148 +/* timings are in milliseconds. */
149 +#define IPT_DSTLIMIT_SCALE 10000
150 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
151 + seconds, or one every 59 hours. */
153 +/* details of this structure hidden by the implementation */
154 +struct ipt_dstlimit_htable;
156 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
157 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
158 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
160 +struct dstlimit_cfg {
161 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
162 + u_int32_t avg; /* Average secs between packets * scale */
163 + u_int32_t burst; /* Period multiplier for upper limit. */
165 + /* user specified */
166 + u_int32_t size; /* how many buckets */
167 + u_int32_t max; /* max number of entries */
168 + u_int32_t gc_interval; /* gc interval */
169 + u_int32_t expire; /* when do entries expire? */
172 +struct ipt_dstlimit_info {
173 + char name [IFNAMSIZ]; /* name */
174 + struct dstlimit_cfg cfg;
175 + struct ipt_dstlimit_htable *hinfo;
177 + /* Used internally by the kernel */
180 + struct ipt_dstlimit_info *master;
183 +#endif /*_IPT_DSTLIMIT_H*/
184 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h
185 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
186 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-04-29 09:48:15.000000000 +0200
188 +#ifndef _IPT_FUZZY_H
189 +#define _IPT_FUZZY_H
191 +#include <linux/param.h>
192 +#include <linux/types.h>
194 +#define MAXFUZZYRATE 10000000
195 +#define MINFUZZYRATE 3
197 +struct ipt_fuzzy_info {
198 + u_int32_t minimum_rate;
199 + u_int32_t maximum_rate;
200 + u_int32_t packets_total;
201 + u_int32_t bytes_total;
202 + u_int32_t previous_time;
203 + u_int32_t present_time;
204 + u_int32_t mean_rate;
205 + u_int8_t acceptance_rate;
208 +#endif /*_IPT_FUZZY_H*/
209 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h
210 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
211 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-04-29 09:48:49.000000000 +0200
213 +#ifndef __ipt_ipv4options_h_included__
214 +#define __ipt_ipv4options_h_included__
216 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
217 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
218 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
219 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
220 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
221 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
222 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
223 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
224 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
225 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
226 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
228 +struct ipt_ipv4options_info {
233 +#endif /* __ipt_ipv4options_h_included__ */
234 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h
235 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
236 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h 2004-04-29 09:49:01.000000000 +0200
238 +#ifndef _IPT_MPORT_H
239 +#define _IPT_MPORT_H
240 +#include <linux/netfilter_ipv4/ip_tables.h>
242 +#define IPT_MPORT_SOURCE (1<<0)
243 +#define IPT_MPORT_DESTINATION (1<<1)
244 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
246 +#define IPT_MULTI_PORTS 15
248 +/* Must fit inside union ipt_matchinfo: 32 bytes */
249 +/* every entry in ports[] except for the last one has one bit in pflags
250 + * associated with it. If this bit is set, the port is the first port of
251 + * a portrange, with the next entry being the last.
252 + * End of list is marked with pflags bit set and port=65535.
253 + * If 14 ports are used (last one does not have a pflag), the last port
254 + * is repeated to fill the last entry in ports[] */
257 + u_int8_t flags:2; /* Type of comparison */
258 + u_int16_t pflags:14; /* Port flags */
259 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
261 +#endif /*_IPT_MPORT_H*/
262 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h
263 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
264 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h 2004-04-29 09:49:13.000000000 +0200
269 +#include <linux/param.h>
270 +#include <linux/types.h>
272 +#ifndef IPT_NTH_NUM_COUNTERS
273 +#define IPT_NTH_NUM_COUNTERS 16
276 +struct ipt_nth_info {
284 +#endif /*_IPT_NTH_H*/
285 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h
286 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
287 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h 2004-04-29 09:49:24.000000000 +0200
292 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
295 + * This program is free software; you can redistribute it and/or modify
296 + * it under the terms of the GNU General Public License as published by
297 + * the Free Software Foundation; either version 2 of the License, or
298 + * (at your option) any later version.
300 + * This program is distributed in the hope that it will be useful,
301 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
302 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
303 + * GNU General Public License for more details.
305 + * You should have received a copy of the GNU General Public License
306 + * along with this program; if not, write to the Free Software
307 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
313 +#define MAXGENRELEN 32
314 +#define MAXDETLEN 64
316 +#define IPT_OSF_GENRE 1
317 +#define IPT_OSF_SMART 2
318 +#define IPT_OSF_LOG 4
319 +#define IPT_OSF_NETLINK 8
321 +#define IPT_OSF_LOGLEVEL_ALL 0
322 +#define IPT_OSF_LOGLEVEL_FIRST 1
324 +#include <linux/list.h>
327 +#include <netinet/ip.h>
328 +#include <netinet/tcp.h>
332 + struct list_head *prev, *next;
338 + char genre[MAXGENRELEN];
340 + unsigned long flags;
342 + int invert; /* UNSUPPORTED */
351 +/* This struct represents IANA options
352 + * http://www.iana.org/assignments/tcp-parameters
356 + unsigned char kind;
357 + unsigned char length;
363 + struct list_head flist;
368 + unsigned char genre[MAXGENRELEN];
369 + unsigned char version[MAXGENRELEN], subtype[MAXGENRELEN];
371 + /* Not needed, but for consistency with original table from Michal Zalewski */
372 + unsigned char details[MAXDETLEN];
375 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
379 +struct ipt_osf_nlmsg
381 + struct osf_finger f;
388 +/* Defines for IANA option kinds */
390 +#define OSFOPT_EOL 0 /* End of options */
391 +#define OSFOPT_NOP 1 /* NOP */
392 +#define OSFOPT_MSS 2 /* Maximum segment size */
393 +#define OSFOPT_WSO 3 /* Window scale option */
394 +#define OSFOPT_SACKP 4 /* SACK permitted */
395 +#define OSFOPT_SACK 5 /* SACK */
396 +#define OSFOPT_ECHO 6
397 +#define OSFOPT_ECHOREPLY 7
398 +#define OSFOPT_TS 8 /* Timestamp option */
399 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
400 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
401 +/* Others are not used in current OSF */
403 +static struct osf_opt IANA_opts[] =
410 + {5, 1 ,}, /* SACK length is not defined */
416 + {11, 1,}, /* CC: Suppose 1 */
417 + {12, 1,}, /* the same */
418 + {13, 1,}, /* and here too */
420 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
434 +#endif /* __KERNEL__ */
436 +#endif /* _IPT_OSF_H */
437 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h
438 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
439 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h 2004-04-29 09:49:29.000000000 +0200
444 +#include <linux/netfilter_ipv4/ip_pool.h>
446 +#define IPT_POOL_INV_SRC 0x00000001
447 +#define IPT_POOL_INV_DST 0x00000002
448 +#define IPT_POOL_DEL_SRC 0x00000004
449 +#define IPT_POOL_DEL_DST 0x00000008
450 +#define IPT_POOL_INV_MOD_SRC 0x00000010
451 +#define IPT_POOL_INV_MOD_DST 0x00000020
452 +#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
453 +#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
454 +#define IPT_POOL_MOD_SRC_DROP 0x00000100
455 +#define IPT_POOL_MOD_DST_DROP 0x00000200
458 +struct ipt_pool_info
465 +#endif /*_IPT_POOL_H*/
466 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h
467 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
468 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h 2004-04-29 09:49:40.000000000 +0200
473 +#include <linux/param.h>
474 +#include <linux/types.h>
477 + * High port numbers have a lower weight to reduce the frequency of false
478 + * positives, such as from passive mode FTP transfers.
480 +#define PORT_WEIGHT_PRIV 3
481 +#define PORT_WEIGHT_HIGH 1
484 + * Port scan detection thresholds: at least COUNT ports need to be scanned
485 + * from the same source, with no longer than DELAY ticks between ports.
487 +#define SCAN_MIN_COUNT 7
488 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
489 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
490 +#define SCAN_DELAY_THRESHOLD (HZ * 3)
493 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
494 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
495 + * HASH_MAX source addresses per the same hash value.
497 +#define LIST_SIZE 0x100
499 +#define HASH_SIZE (1 << HASH_LOG)
500 +#define HASH_MAX 0x10
502 +struct ipt_psd_info {
503 + unsigned int weight_threshold;
504 + unsigned int delay_threshold;
505 + unsigned short lo_ports_weight;
506 + unsigned short hi_ports_weight;
509 +#endif /*_IPT_PSD_H*/
510 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h
511 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
512 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h 2004-04-29 09:49:47.000000000 +0200
514 +#ifndef _IPT_QUOTA_H
515 +#define _IPT_QUOTA_H
517 +/* print debug info in both kernel/netfilter module & iptable library */
518 +//#define DEBUG_IPT_QUOTA
520 +struct ipt_quota_info {
524 +#endif /*_IPT_QUOTA_H*/
525 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h
526 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
527 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h 2004-04-29 09:49:54.000000000 +0200
532 +#include <linux/param.h>
533 +#include <linux/types.h>
535 +struct ipt_rand_info {
539 +#endif /*_IPT_RAND_H*/
540 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h
541 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
542 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h 2004-04-29 09:50:16.000000000 +0200
544 +#ifndef _IPT_REALM_H
545 +#define _IPT_REALM_H
547 +struct ipt_realm_info {
552 +#endif /*_IPT_REALM_H*/
553 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h
554 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
555 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h 2004-04-29 09:50:22.000000000 +0200
557 +#ifndef _IPT_SCTP_H_
558 +#define _IPT_SCTP_H_
560 +#define IPT_SCTP_SRC_PORTS 0x01
561 +#define IPT_SCTP_DEST_PORTS 0x02
562 +#define IPT_SCTP_CHUNK_TYPES 0x04
564 +#define IPT_SCTP_VALID_FLAGS 0x07
566 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
569 +struct ipt_sctp_flag_info {
570 + u_int8_t chunktype;
572 + u_int8_t flag_mask;
575 +#define IPT_NUM_SCTP_FLAGS 4
577 +struct ipt_sctp_info {
578 + u_int16_t dpts[2]; /* Min, Max */
579 + u_int16_t spts[2]; /* Min, Max */
581 + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
583 +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
584 +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
585 +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
587 + u_int32_t chunk_match_type;
588 + struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
592 + u_int32_t invflags;
595 +#define bytes(type) (sizeof(type) * 8)
597 +#define SCTP_CHUNKMAP_SET(chunkmap, type) \
599 + chunkmap[type / bytes(u_int32_t)] |= \
600 + 1 << (type % bytes(u_int32_t)); \
603 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
605 + chunkmap[type / bytes(u_int32_t)] &= \
606 + ~(1 << (type % bytes(u_int32_t))); \
609 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
611 + (chunkmap[type / bytes (u_int32_t)] & \
612 + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
615 +#define SCTP_CHUNKMAP_RESET(chunkmap) \
618 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
622 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
625 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
626 + chunkmap[i] = ~0; \
629 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
632 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
633 + destmap[i] = srcmap[i]; \
636 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
640 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
641 + if (chunkmap[i]) { \
649 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
653 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
654 + if (chunkmap[i] != ~0) { \
662 +#endif /* _IPT_SCTP_H_ */
664 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h
665 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
666 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h 2004-04-29 09:50:30.000000000 +0200
668 +#ifndef __ipt_time_h_included__
669 +#define __ipt_time_h_included__
672 +struct ipt_time_info {
673 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
674 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
675 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
676 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
680 +#endif /* __ipt_time_h_included__ */
681 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h
682 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
683 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h 2004-04-29 09:50:36.000000000 +0200
687 +#include <linux/netfilter_ipv4/ip_tables.h>
697 +struct ipt_u32_location_element
702 +struct ipt_u32_value_element
707 +/* *** any way to allow for an arbitrary number of elements?
708 + for now I settle for a limit of 10 of each */
709 +#define U32MAXSIZE 10
713 + struct ipt_u32_location_element location[U32MAXSIZE+1];
715 + struct ipt_u32_value_element value[U32MAXSIZE+1];
721 + struct ipt_u32_test tests[U32MAXSIZE+1];
724 +#endif /*_IPT_U32_H*/
725 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h
726 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
727 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h 2004-04-29 09:46:34.000000000 +0200
729 +/* Hop Limit modification module for ip6tables
730 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
731 + * Based on HW's TTL module */
742 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
744 +struct ip6t_HL_info {
746 + u_int8_t hop_limit;
751 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h
752 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-04-28 03:34:59.000000000 +0200
753 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-04-29 09:47:26.000000000 +0200
755 #define _IP6T_REJECT_H
757 enum ip6t_reject_with {
758 - IP6T_ICMP_NET_UNREACHABLE,
759 - IP6T_ICMP_HOST_UNREACHABLE,
760 - IP6T_ICMP_PROT_UNREACHABLE,
761 - IP6T_ICMP_PORT_UNREACHABLE,
762 - IP6T_ICMP_ECHOREPLY
763 + IP6T_ICMP6_NO_ROUTE,
764 + IP6T_ICMP6_ADM_PROHIBITED,
765 + IP6T_ICMP6_NOT_NEIGHBOUR,
766 + IP6T_ICMP6_ADDR_UNREACH,
767 + IP6T_ICMP6_PORT_UNREACH,
768 + IP6T_ICMP6_ECHOREPLY,
772 struct ip6t_reject_info {
773 enum ip6t_reject_with with; /* reject type */
776 -#endif /*_IPT_REJECT_H*/
777 +#endif /*_IP6T_REJECT_H*/
778 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
779 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
780 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-04-29 09:48:15.000000000 +0200
782 +#ifndef _IP6T_FUZZY_H
783 +#define _IP6T_FUZZY_H
785 +#include <linux/param.h>
786 +#include <linux/types.h>
788 +#define MAXFUZZYRATE 10000000
789 +#define MINFUZZYRATE 3
791 +struct ip6t_fuzzy_info {
792 + u_int32_t minimum_rate;
793 + u_int32_t maximum_rate;
794 + u_int32_t packets_total;
795 + u_int32_t bytes_total;
796 + u_int32_t previous_time;
797 + u_int32_t present_time;
798 + u_int32_t mean_rate;
799 + u_int8_t acceptance_rate;
802 +#endif /*_IP6T_FUZZY_H*/
803 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h
804 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
805 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h 2004-04-29 09:49:13.000000000 +0200
810 +#include <linux/param.h>
811 +#include <linux/types.h>
813 +#ifndef IP6T_NTH_NUM_COUNTERS
814 +#define IP6T_NTH_NUM_COUNTERS 16
817 +struct ip6t_nth_info {
825 +#endif /*_IP6T_NTH_H*/
826 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h
827 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
828 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h 2004-04-29 09:49:54.000000000 +0200
830 +#ifndef _IP6T_RAND_H
831 +#define _IP6T_RAND_H
833 +#include <linux/param.h>
834 +#include <linux/types.h>
836 +struct ip6t_rand_info {
840 +#endif /*_IP6T_RAND_H*/
841 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/skbuff.h linux-2.6.6-rc3/include/linux/skbuff.h
842 --- linux-2.6.6-rc3.org/include/linux/skbuff.h 2004-04-29 09:37:52.000000000 +0200
843 +++ linux-2.6.6-rc3/include/linux/skbuff.h 2004-04-29 09:45:51.000000000 +0200
844 @@ -1049,6 +1049,14 @@
846 atomic_inc(&nfct->master->use);
848 +static inline void nf_reset(struct sk_buff *skb)
850 + nf_conntrack_put(skb->nfct);
852 +#ifdef CONFIG_NETFILTER_DEBUG
857 #ifdef CONFIG_BRIDGE_NETFILTER
858 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
859 @@ -1061,9 +1069,10 @@
861 atomic_inc(&nf_bridge->use);
866 +#endif /* CONFIG_BRIDGE_NETFILTER */
867 +#else /* CONFIG_NETFILTER */
868 +static inline void nf_reset(struct sk_buff *skb) {}
869 +#endif /* CONFIG_NETFILTER */
871 #endif /* __KERNEL__ */
872 #endif /* _LINUX_SKBUFF_H */
873 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_gre.c linux-2.6.6-rc3/net/ipv4/ip_gre.c
874 --- linux-2.6.6-rc3.org/net/ipv4/ip_gre.c 2004-04-28 03:36:22.000000000 +0200
875 +++ linux-2.6.6-rc3/net/ipv4/ip_gre.c 2004-04-29 09:45:51.000000000 +0200
877 skb->dev = tunnel->dev;
878 dst_release(skb->dst);
880 -#ifdef CONFIG_NETFILTER
881 - nf_conntrack_put(skb->nfct);
883 -#ifdef CONFIG_NETFILTER_DEBUG
888 ipgre_ecn_decapsulate(iph, skb);
890 read_unlock(&ipgre_lock);
895 -#ifdef CONFIG_NETFILTER
896 - nf_conntrack_put(skb->nfct);
898 -#ifdef CONFIG_NETFILTER_DEBUG
906 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
907 --- linux-2.6.6-rc3.org/net/ipv4/ip_input.c 2004-04-28 03:35:06.000000000 +0200
908 +++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-29 09:45:51.000000000 +0200
909 @@ -202,17 +202,13 @@
911 #ifdef CONFIG_NETFILTER_DEBUG
912 nf_debug_ip_local_deliver(skb);
914 #endif /*CONFIG_NETFILTER_DEBUG*/
916 __skb_pull(skb, ihl);
918 -#ifdef CONFIG_NETFILTER
919 /* Free reference early: we don't need it any more, and it may
920 hold ip_conntrack module loaded indefinitely. */
921 - nf_conntrack_put(skb->nfct);
923 -#endif /*CONFIG_NETFILTER*/
926 /* Point into the IP datagram, just past the header. */
927 skb->h.raw = skb->data;
928 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
929 --- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-28 03:37:06.000000000 +0200
930 +++ linux-2.6.6-rc3/net/ipv4/ipip.c 2004-04-29 09:45:51.000000000 +0200
932 skb->dev = tunnel->dev;
933 dst_release(skb->dst);
935 -#ifdef CONFIG_NETFILTER
936 - nf_conntrack_put(skb->nfct);
938 -#ifdef CONFIG_NETFILTER_DEBUG
943 ipip_ecn_decapsulate(iph, skb);
945 read_unlock(&ipip_lock);
947 if ((iph->ttl = tiph->ttl) == 0)
948 iph->ttl = old_iph->ttl;
950 -#ifdef CONFIG_NETFILTER
951 - nf_conntrack_put(skb->nfct);
953 -#ifdef CONFIG_NETFILTER_DEBUG
961 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
962 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig 2004-04-28 03:36:31.000000000 +0200
963 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig 2004-04-29 09:50:36.000000000 +0200
965 <file:Documentation/modules.txt>. If unsure, say `N'.
968 +config IP_NF_TARGET_IPV4OPTSSTRIP
969 + tristate 'IPV4OPTSSTRIP target support'
970 + depends on IP_NF_MANGLE
973 +config IP_NF_TARGET_NETLINK
974 + tristate 'NETLINK target support'
975 + depends on IP_NF_FILTER
978 +config IP_NF_TARGET_TTL
979 + tristate 'TTL target support'
980 + depends on IP_NF_MANGLE
983 +config IP_NF_MATCH_CONNLIMIT
984 + tristate 'Connections/IP limit match support'
985 + depends on IP_NF_IPTABLES
988 +config IP_NF_MATCH_DSTLIMIT
989 + tristate 'dstlimit match support'
990 + depends on IP_NF_IPTABLES
993 +config IP_NF_MATCH_FUZZY
994 + tristate 'fuzzy match support'
995 + depends on IP_NF_IPTABLES
998 +config IP_NF_MATCH_IPV4OPTIONS
999 + tristate 'IPV4OPTIONS match support'
1000 + depends on IP_NF_IPTABLES
1003 +config IP_NF_MATCH_MPORT
1004 + tristate 'Multiple port with ranges match support'
1005 + depends on IP_NF_IPTABLES
1008 +config IP_NF_MATCH_NTH
1009 + tristate 'Nth match support'
1010 + depends on IP_NF_IPTABLES
1013 +config IP_NF_MATCH_OSF
1014 + tristate 'OSF match support'
1015 + depends on IP_NF_IPTABLES
1018 +config IP_POOL_STATISTICS
1019 + bool 'enable statistics on pool usage'
1020 + depends on IP_NF_POOL!=n
1023 + tristate 'IP address pool support'
1024 + depends on IP_NF_IPTABLES
1027 +config IP_NF_MATCH_PSD
1028 + tristate 'psd match support'
1029 + depends on IP_NF_IPTABLES
1032 +config IP_NF_MATCH_QUOTA
1033 + tristate 'quota match support'
1034 + depends on IP_NF_IPTABLES
1037 +config IP_NF_MATCH_RANDOM
1038 + tristate 'random match support'
1039 + depends on IP_NF_IPTABLES
1042 +config IP_NF_MATCH_REALM
1043 + tristate 'realm match support'
1044 + depends on IP_NF_IPTABLES && NET_CLS_ROUTE
1047 +config IP_NF_MATCH_SCTP
1048 + tristate 'SCTP protocol match support'
1049 + depends on IP_NF_IPTABLES
1052 +config IP_NF_MATCH_TIME
1053 + tristate 'TIME match support'
1054 + depends on IP_NF_IPTABLES
1057 +config IP_NF_MATCH_U32
1058 + tristate 'U32 match support'
1059 + depends on IP_NF_IPTABLES
1064 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
1065 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile 2004-04-28 03:35:21.000000000 +0200
1066 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-29 09:50:36.000000000 +0200
1069 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1070 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1071 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1072 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
1073 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
1074 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
1075 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
1076 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
1077 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
1079 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
1080 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1082 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1084 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1085 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1087 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1090 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
1092 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
1094 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
1097 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
1099 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
1102 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
1104 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
1106 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
1109 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
1111 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1114 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1115 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1116 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1117 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1118 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1119 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1121 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1124 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1125 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1126 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1127 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1128 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1129 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1130 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1131 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1132 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
1133 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c
1134 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-28 03:34:58.000000000 +0200
1135 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-29 09:46:00.000000000 +0200
1137 ip_conntrack_destroyed(ct);
1139 WRITE_LOCK(&ip_conntrack_lock);
1140 - /* Delete us from our own list to prevent corruption later */
1141 - list_del(&ct->sibling_list);
1142 + /* Make sure don't leave any orphaned expectations lying around */
1143 + if (ct->expecting)
1144 + remove_expectations(ct, 1);
1146 /* Delete our master expectation */
1148 @@ -692,42 +693,50 @@
1149 struct ip_conntrack_expect *, tuple);
1150 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
1152 - /* If master is not in hash table yet (ie. packet hasn't left
1153 - this machine yet), how can other end know about expected?
1154 - Hence these are not the droids you are looking for (if
1155 - master ct never got confirmed, we'd hold a reference to it
1156 - and weird things would happen to future packets). */
1157 - if (expected && !is_confirmed(expected->expectant))
1160 - /* Look up the conntrack helper for master connections only */
1162 - conntrack->helper = ip_ct_find_helper(&repl_tuple);
1164 - /* If the expectation is dying, then this is a loser. */
1166 - && expected->expectant->helper->timeout
1167 - && ! del_timer(&expected->timeout))
1171 - DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
1172 - conntrack, expected);
1173 - /* Welcome, Mr. Bond. We've been expecting you... */
1174 - IP_NF_ASSERT(master_ct(conntrack));
1175 - __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1176 - conntrack->master = expected;
1177 - expected->sibling = conntrack;
1178 - LIST_DELETE(&ip_conntrack_expect_list, expected);
1179 - expected->expectant->expecting--;
1180 - nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1182 - atomic_inc(&ip_conntrack_count);
1183 + /* If master is not in hash table yet (ie. packet hasn't left
1184 + this machine yet), how can other end know about expected?
1185 + Hence these are not the droids you are looking for (if
1186 + master ct never got confirmed, we'd hold a reference to it
1187 + and weird things would happen to future packets). */
1188 + if (!is_confirmed(expected->expectant)) {
1190 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
1194 + /* Expectation is dying... */
1195 + if (expected->expectant->helper->timeout
1196 + && ! del_timer(&expected->timeout)) {
1200 + DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
1201 + conntrack, expected);
1202 + /* Welcome, Mr. Bond. We've been expecting you... */
1203 + IP_NF_ASSERT(master_ct(conntrack));
1204 + __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1205 + conntrack->master = expected;
1206 + expected->sibling = conntrack;
1207 + LIST_DELETE(&ip_conntrack_expect_list, expected);
1208 + expected->expectant->expecting--;
1209 + nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1211 + /* this is a braindead... --pablo */
1212 + atomic_inc(&ip_conntrack_count);
1213 + WRITE_UNLOCK(&ip_conntrack_lock);
1215 + if (expected->expectfn)
1216 + expected->expectfn(conntrack);
1220 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
1222 +end: atomic_inc(&ip_conntrack_count);
1223 WRITE_UNLOCK(&ip_conntrack_lock);
1225 - if (expected && expected->expectfn)
1226 - expected->expectfn(conntrack);
1227 - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1228 +ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1231 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
1233 atomic_set(&new->use, 1);
1235 /* add to expected list for this connection */
1236 - list_add(&new->expected_list, &related_to->sibling_list);
1237 + list_add_tail(&new->expected_list, &related_to->sibling_list);
1238 /* add to global list of expectations */
1240 list_prepend(&ip_conntrack_expect_list, &new->list);
1241 /* add and start timer if required */
1242 if (related_to->helper->timeout) {
1243 @@ -1003,7 +1011,6 @@
1245 } else if (related_to->helper->max_expected &&
1246 related_to->expecting >= related_to->helper->max_expected) {
1247 - struct list_head *cur_item;
1249 if (!(related_to->helper->flags &
1250 IP_CT_HELPER_F_REUSE_EXPECT)) {
1251 @@ -1029,21 +1036,14 @@
1252 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
1254 /* choose the the oldest expectation to evict */
1255 - list_for_each(cur_item, &related_to->sibling_list) {
1256 - struct ip_conntrack_expect *cur;
1258 - cur = list_entry(cur_item,
1259 - struct ip_conntrack_expect,
1261 - if (cur->sibling == NULL) {
1263 + list_for_each_entry(old, &related_to->sibling_list,
1265 + if (old->sibling == NULL)
1270 - /* (!old) cannot happen, since related_to->expecting is the
1271 - * number of unconfirmed expects */
1272 - IP_NF_ASSERT(old);
1273 + /* We cannot fail since related_to->expecting is the number
1274 + * of unconfirmed expectations */
1275 + IP_NF_ASSERT(old && old->sibling == NULL);
1277 /* newnat14 does not reuse the real allocated memory
1278 * structures but rather unexpects the old and
1279 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c
1280 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c 2004-04-28 03:35:10.000000000 +0200
1281 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c 2004-04-29 09:43:53.000000000 +0200
1284 /* Have to grab read lock before sibling_list traversal */
1285 READ_LOCK(&ip_conntrack_lock);
1286 - list_for_each(cur_item, &ct->sibling_list) {
1287 + list_for_each_prev(cur_item, &ct->sibling_list) {
1288 exp = list_entry(cur_item, struct ip_conntrack_expect,
1291 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c
1292 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
1293 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c 2004-04-29 09:49:29.000000000 +0200
1295 +/* Kernel module for IP pool management */
1297 +#include <linux/module.h>
1298 +#include <linux/ip.h>
1299 +#include <linux/skbuff.h>
1300 +#include <linux/netfilter_ipv4/ip_tables.h>
1301 +#include <linux/netfilter_ipv4/ip_pool.h>
1302 +#include <linux/errno.h>
1303 +#include <asm/uaccess.h>
1304 +#include <asm/bitops.h>
1305 +#include <linux/interrupt.h>
1306 +#include <linux/spinlock.h>
1311 +#define DP(format, args...)
1314 +MODULE_LICENSE("GPL");
1317 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
1320 + u_int32_t first_ip; /* host byte order, included in range */
1321 + u_int32_t last_ip; /* host byte order, included in range */
1322 + void *members; /* the bitmap proper */
1323 + int nr_use; /* total nr. of tests through this */
1324 + int nr_match; /* total nr. of matches through this */
1328 +static struct ip_pool *POOL;
1330 +static inline struct ip_pool *lookup(ip_pool_t index)
1332 + if (index < 0 || index >= nr_pool) {
1333 + DP("ip_pool:lookup: bad index %d\n", index);
1336 + return POOL+index;
1339 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
1341 + struct ip_pool *pool = lookup(index);
1344 + if (!pool || !pool->members)
1346 + read_lock_bh(&pool->lock);
1347 + if (pool->members) {
1348 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
1349 + addr -= pool->first_ip;
1350 + if (test_bit(addr, pool->members)) {
1352 +#ifdef CONFIG_IP_POOL_STATISTICS
1357 +#ifdef CONFIG_IP_POOL_STATISTICS
1361 + read_unlock_bh(&pool->lock);
1364 +EXPORT_SYMBOL(ip_pool_match);
1366 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
1368 + struct ip_pool *pool;
1371 + pool = lookup(index);
1372 + if ( !pool || !pool->members
1373 + || addr < pool->first_ip || addr > pool->last_ip)
1375 + read_lock_bh(&pool->lock);
1376 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
1377 + addr -= pool->first_ip;
1379 + ? (0 != test_and_clear_bit(addr, pool->members))
1380 + : (0 != test_and_set_bit(addr, pool->members));
1382 + read_unlock_bh(&pool->lock);
1386 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
1388 + int res = pool_change(index,addr,isdel);
1390 + if (!isdel) res = !res;
1393 +EXPORT_SYMBOL(ip_pool_mod);
1395 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
1397 + return 4*((((b-a+8)/8)+3)/4);
1400 +static inline int poolbytes(ip_pool_t index)
1402 + struct ip_pool *pool = lookup(index);
1404 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
1407 +static int setpool(
1413 + struct ip_pool_request req;
1415 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
1416 + if (!capable(CAP_NET_ADMIN))
1418 + if (optval != SO_IP_POOL)
1420 + if (len != sizeof(req))
1422 + if (copy_from_user(&req, user, sizeof(req)) != 0)
1424 + printk("obsolete op - upgrade your ippool(8) utility.\n");
1428 +static int getpool(
1434 + struct ip_pool_request req;
1435 + struct ip_pool *pool;
1441 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
1442 + if (!capable(CAP_NET_ADMIN))
1444 + if (optval != SO_IP_POOL)
1446 + if (*len != sizeof(req)) {
1449 + if (copy_from_user(&req, user, sizeof(req)) != 0)
1451 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
1452 + if (req.op < IP_POOL_BAD001) {
1453 + printk("obsolete op - upgrade your ippool(8) utility.\n");
1457 + case IP_POOL_HIGH_NR:
1458 + DP("ip_pool HIGH_NR\n");
1459 + req.index = IP_POOL_NONE;
1460 + for (i=0; i<nr_pool; i++)
1461 + if (POOL[i].members)
1463 + return copy_to_user(user, &req, sizeof(req));
1464 + case IP_POOL_LOOKUP:
1465 + DP("ip_pool LOOKUP\n");
1466 + pool = lookup(req.index);
1469 + if (!pool->members)
1471 + req.addr = htonl(pool->first_ip);
1472 + req.addr2 = htonl(pool->last_ip);
1473 + return copy_to_user(user, &req, sizeof(req));
1474 + case IP_POOL_USAGE:
1475 + DP("ip_pool USE\n");
1476 + pool = lookup(req.index);
1479 + if (!pool->members)
1481 + req.addr = pool->nr_use;
1482 + req.addr2 = pool->nr_match;
1483 + return copy_to_user(user, &req, sizeof(req));
1484 + case IP_POOL_TEST_ADDR:
1485 + DP("ip_pool TEST 0x%08x\n", req.addr);
1486 + pool = lookup(req.index);
1490 + read_lock_bh(&pool->lock);
1491 + if (!pool->members) {
1492 + DP("ip_pool TEST_ADDR no members in pool\n");
1494 + goto unlock_and_return_res;
1496 + req.addr = ntohl(req.addr);
1497 + if (req.addr < pool->first_ip) {
1498 + DP("ip_pool TEST_ADDR address < pool bounds\n");
1500 + goto unlock_and_return_res;
1502 + if (req.addr > pool->last_ip) {
1503 + DP("ip_pool TEST_ADDR address > pool bounds\n");
1505 + goto unlock_and_return_res;
1507 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
1509 + read_unlock_bh(&pool->lock);
1510 + return copy_to_user(user, &req, sizeof(req));
1511 + case IP_POOL_FLUSH:
1512 + DP("ip_pool FLUSH not yet implemented.\n");
1514 + case IP_POOL_DESTROY:
1515 + DP("ip_pool DESTROY not yet implemented.\n");
1517 + case IP_POOL_INIT:
1518 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
1519 + pool = lookup(req.index);
1522 + req.addr = ntohl(req.addr);
1523 + req.addr2 = ntohl(req.addr2);
1524 + if (req.addr > req.addr2) {
1525 + DP("ip_pool INIT bad ip range\n");
1528 + newbytes = bitmap_bytes(req.addr, req.addr2);
1529 + newmembers = kmalloc(newbytes, GFP_KERNEL);
1530 + if (!newmembers) {
1531 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
1534 + memset(newmembers, 0, newbytes);
1535 + write_lock_bh(&pool->lock);
1536 + if (pool->members) {
1537 + DP("ip_pool INIT pool %d exists\n", req.index);
1538 + kfree(newmembers);
1540 + goto unlock_and_return_res;
1542 + pool->first_ip = req.addr;
1543 + pool->last_ip = req.addr2;
1545 + pool->nr_match = 0;
1546 + pool->members = newmembers;
1547 + write_unlock_bh(&pool->lock);
1549 + case IP_POOL_ADD_ADDR:
1550 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
1551 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
1552 + return copy_to_user(user, &req, sizeof(req));
1553 + case IP_POOL_DEL_ADDR:
1554 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
1555 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
1556 + return copy_to_user(user, &req, sizeof(req));
1558 + DP("ip_pool:getpool bad op %d\n", req.op);
1563 +unlock_and_return_res:
1565 + read_unlock_bh(&pool->lock);
1569 +static struct nf_sockopt_ops so_pool
1570 += { { NULL, NULL }, PF_INET,
1571 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
1572 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
1575 +MODULE_PARM(nr_pool, "i");
1577 +static int __init init(void)
1582 + if (nr_pool < 1) {
1583 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
1586 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
1588 + printk("ip_pool module init: out of memory for nr_pool %d\n",
1592 + for (i=0; i<nr_pool; i++) {
1593 + POOL[i].first_ip = 0;
1594 + POOL[i].last_ip = 0;
1595 + POOL[i].members = 0;
1596 + POOL[i].nr_use = 0;
1597 + POOL[i].nr_match = 0;
1598 + POOL[i].lock = RW_LOCK_UNLOCKED;
1600 + res = nf_register_sockopt(&so_pool);
1601 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
1609 +static void __exit fini(void)
1613 + DP("ip_pool:fini BYEBYE\n");
1614 + nf_unregister_sockopt(&so_pool);
1615 + for (i=0; i<nr_pool; i++) {
1616 + if (POOL[i].members) {
1617 + kfree(POOL[i].members);
1618 + POOL[i].members = 0;
1623 + DP("ip_pool:fini these are the famous last words\n");
1629 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c
1630 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c 2004-04-28 03:35:21.000000000 +0200
1631 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c 2004-04-29 09:46:20.000000000 +0200
1632 @@ -1716,9 +1716,9 @@
1635 #ifdef CONFIG_PROC_FS
1636 -static inline int print_name(const char *i,
1637 - off_t start_offset, char *buffer, int length,
1638 - off_t *pos, unsigned int *count)
1639 +static int print_name(const char *i,
1640 + off_t start_offset, char *buffer, int length,
1641 + off_t *pos, unsigned int *count)
1643 if ((*count)++ >= start_offset) {
1644 unsigned int namelen;
1645 @@ -1752,6 +1752,15 @@
1649 +static inline int print_target(const struct ipt_target *t,
1650 + off_t start_offset, char *buffer, int length,
1651 + off_t *pos, unsigned int *count)
1653 + if (t != &ipt_standard_target && t != &ipt_error_target)
1655 + return print_name((char *)t, start_offset, buffer, length, pos, count);
1658 static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
1661 @@ -1760,7 +1769,7 @@
1662 if (down_interruptible(&ipt_mutex) != 0)
1665 - LIST_FIND(&ipt_target, print_name, void *,
1666 + LIST_FIND(&ipt_target, print_target, struct ipt_target *,
1667 offset, buffer, length, &pos, &count);
1670 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
1671 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
1672 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-04-29 09:46:43.000000000 +0200
1675 + * Strip all IP options in the IP packet header.
1677 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
1678 + * This software is distributed under GNU GPL v2, 1991
1681 +#include <linux/module.h>
1682 +#include <linux/skbuff.h>
1683 +#include <linux/ip.h>
1684 +#include <net/checksum.h>
1686 +#include <linux/netfilter_ipv4/ip_tables.h>
1688 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
1689 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
1690 +MODULE_LICENSE("GPL");
1692 +static unsigned int
1693 +target(struct sk_buff **pskb,
1694 + const struct net_device *in,
1695 + const struct net_device *out,
1696 + unsigned int hooknum,
1697 + const void *targinfo,
1700 + struct iphdr *iph;
1701 + struct sk_buff *skb;
1702 + struct ip_options *opt;
1703 + unsigned char *optiph;
1706 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
1710 + iph = (*pskb)->nh.iph;
1711 + optiph = skb->nh.raw;
1712 + l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
1714 + /* if no options in packet then nothing to clear. */
1715 + if (iph->ihl * 4 == sizeof(struct iphdr))
1716 + return IPT_CONTINUE;
1718 + /* else clear all options */
1719 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
1720 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
1721 + opt = &(IPCB(skb)->opt);
1725 + skb->nfcache |= NFC_ALTERED;
1727 + return IPT_CONTINUE;
1731 +checkentry(const char *tablename,
1732 + const struct ipt_entry *e,
1734 + unsigned int targinfosize,
1735 + unsigned int hook_mask)
1737 + if (strcmp(tablename, "mangle")) {
1738 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1741 + /* nothing else to check because no parameters */
1745 +static struct ipt_target ipt_ipv4optsstrip_reg = {
1746 + .name = "IPV4OPTSSTRIP",
1748 + .checkentry = checkentry,
1749 + .me = THIS_MODULE };
1751 +static int __init init(void)
1753 + return ipt_register_target(&ipt_ipv4optsstrip_reg);
1756 +static void __exit fini(void)
1758 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
1763 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c
1764 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
1765 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c 2004-04-29 09:47:00.000000000 +0200
1767 +#include <linux/module.h>
1768 +#include <linux/version.h>
1769 +#include <linux/config.h>
1770 +#include <linux/socket.h>
1771 +#include <linux/skbuff.h>
1772 +#include <linux/kernel.h>
1773 +#include <linux/netlink.h>
1774 +#include <linux/netdevice.h>
1775 +#include <linux/mm.h>
1776 +#include <linux/socket.h>
1777 +#include <linux/netfilter_ipv4/ip_tables.h>
1778 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
1779 +#include <net/sock.h>
1781 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
1782 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
1783 +MODULE_LICENSE("GPL");
1786 +#define DEBUGP printk
1788 +#define DEBUGP(format, args...)
1791 +static struct sock *ipfwsk;
1793 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
1794 + unsigned int hooknum,
1795 + const struct net_device *in,
1796 + const struct net_device *out,
1797 + const void *targinfo, void *userinfo)
1799 + struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
1800 + struct iphdr *ip = (*pskb)->nh.iph;
1801 + struct sk_buff *outskb;
1802 + struct netlink_t nlhdr;
1805 + /* Allocate a socket buffer */
1806 + if ( MASK(nld->flags, USE_SIZE) )
1807 + len = nld->size+sizeof(nlhdr);
1809 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
1811 + outskb=alloc_skb(len, GFP_ATOMIC);
1816 + if ( MASK(nld->flags, USE_MARK) )
1817 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
1819 + nlhdr.mark=(*pskb)->nfmark;
1821 + if ( in && in->name ) {
1822 + strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
1823 + }else if ( out && out->name ){
1824 + strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
1827 + skb_put(outskb, len);
1828 + memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
1829 + memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
1830 + netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
1832 + if (net_ratelimit())
1833 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
1836 + if ( MASK(nld->flags, USE_DROP) )
1839 + return IPT_CONTINUE;
1842 +static int ipt_netlink_checkentry(const char *tablename,
1843 + const struct ipt_entry *e,
1845 + unsigned int targinfosize,
1846 + unsigned int hookmask)
1848 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
1853 +static struct ipt_target ipt_netlink_reg = {
1856 + ipt_netlink_target,
1857 + ipt_netlink_checkentry,
1862 +static int __init init(void)
1864 + DEBUGP("ipt_NETLINK: init module\n");
1866 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
1870 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
1877 +static void __exit fini(void)
1879 + DEBUGP("ipt_NETLINK: cleanup_module\n");
1880 + ipt_unregister_target(&ipt_netlink_reg);
1881 + if(ipfwsk->socket) sock_release(ipfwsk->socket);
1886 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c
1887 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
1888 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c 2004-04-29 09:49:29.000000000 +0200
1890 +/* ipt_POOL.c - netfilter target to manipulate IP pools
1892 + * This target can be used almost everywhere. It acts on some specified
1893 + * IP pool, adding or deleting some IP address in the pool. The address
1894 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
1895 + * of the packet under inspection.
1897 + * The target normally returns IPT_CONTINUE.
1900 +#include <linux/types.h>
1901 +#include <linux/ip.h>
1902 +#include <linux/timer.h>
1903 +#include <linux/module.h>
1904 +#include <linux/netfilter.h>
1905 +#include <linux/netdevice.h>
1906 +#include <linux/if.h>
1907 +#include <linux/inetdevice.h>
1908 +#include <net/protocol.h>
1909 +#include <net/checksum.h>
1910 +#include <linux/netfilter_ipv4.h>
1911 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
1912 +#include <linux/netfilter_ipv4/ipt_pool.h>
1915 +#define DEBUGP printk
1917 +#define DEBUGP(format, args...)
1920 +/*** NOTE NOTE NOTE NOTE ***
1922 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
1923 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
1924 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
1925 +** is modified for the source IP address of the packet under inspection.
1926 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
1928 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
1929 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
1931 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
1932 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
1933 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
1934 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
1938 +do_check(const char *tablename,
1939 + const struct ipt_entry *e,
1941 + unsigned int targinfosize,
1942 + unsigned int hook_mask)
1944 + const struct ipt_pool_info *ipi = targinfo;
1946 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
1947 + DEBUGP("POOL_check: size %u.\n", targinfosize);
1950 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
1954 +static unsigned int
1955 +do_target(struct sk_buff **pskb,
1956 + unsigned int hooknum,
1957 + const struct net_device *in,
1958 + const struct net_device *out,
1959 + const void *targinfo,
1962 + const struct ipt_pool_info *ipi = targinfo;
1964 + unsigned int verdict = IPT_CONTINUE;
1966 + if (ipi->src != IP_POOL_NONE) {
1967 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
1968 + ipi->flags & IPT_POOL_DEL_SRC);
1969 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
1970 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
1971 + verdict = NF_ACCEPT;
1972 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
1973 + verdict = NF_DROP;
1976 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
1977 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
1978 + ipi->flags & IPT_POOL_DEL_DST);
1979 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
1980 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
1981 + verdict = NF_ACCEPT;
1982 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
1983 + verdict = NF_DROP;
1989 +static struct ipt_target pool_reg
1990 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
1992 +static int __init init(void)
1994 + DEBUGP("init ipt_POOL\n");
1995 + return ipt_register_target(&pool_reg);
1998 +static void __exit fini(void)
2000 + DEBUGP("fini ipt_POOL\n");
2001 + ipt_unregister_target(&pool_reg);
2006 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c
2007 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
2008 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c 2004-04-29 09:47:42.000000000 +0200
2010 +/* TTL modification target for IP tables
2011 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
2013 + * Version: $Revision$
2015 + * This software is distributed under the terms of GNU GPL
2018 +#include <linux/module.h>
2019 +#include <linux/skbuff.h>
2020 +#include <linux/ip.h>
2021 +#include <net/checksum.h>
2023 +#include <linux/netfilter_ipv4/ip_tables.h>
2024 +#include <linux/netfilter_ipv4/ipt_TTL.h>
2026 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
2027 +MODULE_DESCRIPTION("IP tables TTL modification module");
2028 +MODULE_LICENSE("GPL");
2030 +static unsigned int
2031 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
2032 + const struct net_device *out, unsigned int hooknum,
2033 + const void *targinfo, void *userinfo)
2035 + struct iphdr *iph;
2036 + const struct ipt_TTL_info *info = targinfo;
2037 + u_int16_t diffs[2];
2040 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
2043 + iph = (*pskb)->nh.iph;
2045 + switch (info->mode) {
2047 + new_ttl = info->ttl;
2050 + new_ttl = iph->ttl + info->ttl;
2051 + if (new_ttl > 255)
2055 + new_ttl = iph->ttl + info->ttl;
2060 + new_ttl = iph->ttl;
2064 + if (new_ttl != iph->ttl) {
2065 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
2066 + iph->ttl = new_ttl;
2067 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
2068 + iph->check = csum_fold(csum_partial((char *)diffs,
2070 + iph->check^0xFFFF));
2071 + (*pskb)->nfcache |= NFC_ALTERED;
2074 + return IPT_CONTINUE;
2077 +static int ipt_ttl_checkentry(const char *tablename,
2078 + const struct ipt_entry *e,
2080 + unsigned int targinfosize,
2081 + unsigned int hook_mask)
2083 + struct ipt_TTL_info *info = targinfo;
2085 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
2086 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
2088 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
2092 + if (strcmp(tablename, "mangle")) {
2093 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
2097 + if (info->mode > IPT_TTL_MAXMODE) {
2098 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
2103 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
2104 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
2111 +static struct ipt_target ipt_TTL = {
2113 + .target = ipt_ttl_target,
2114 + .checkentry = ipt_ttl_checkentry,
2118 +static int __init init(void)
2120 + return ipt_register_target(&ipt_TTL);
2123 +static void __exit fini(void)
2125 + ipt_unregister_target(&ipt_TTL);
2130 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c
2131 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
2132 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c 2004-04-29 09:47:49.000000000 +0200
2135 + * netfilter module to limit the number of parallel tcp
2136 + * connections per IP address.
2137 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
2138 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
2139 + * only ignore TIME_WAIT or gone connections
2143 + * Kernel module to match connection tracking information.
2144 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
2146 +#include <linux/module.h>
2147 +#include <linux/skbuff.h>
2148 +#include <linux/list.h>
2149 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2150 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2151 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
2152 +#include <linux/netfilter_ipv4/ip_tables.h>
2153 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
2157 +MODULE_LICENSE("GPL");
2159 +/* we'll save the tuples of all connections we care about */
2160 +struct ipt_connlimit_conn
2162 + struct list_head list;
2163 + struct ip_conntrack_tuple tuple;
2166 +struct ipt_connlimit_data {
2168 + struct list_head iphash[256];
2171 +static int ipt_iphash(u_int32_t addr)
2175 + hash = addr & 0xff;
2176 + hash ^= (addr >> 8) & 0xff;
2177 + hash ^= (addr >> 16) & 0xff;
2178 + hash ^= (addr >> 24) & 0xff;
2182 +static int count_them(struct ipt_connlimit_data *data,
2183 + u_int32_t addr, u_int32_t mask,
2184 + struct ip_conntrack *ct)
2187 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
2188 + "fin_wait", "time_wait", "close", "close_wait",
2189 + "last_ack", "listen" };
2191 + int addit = 1, matches = 0;
2192 + struct ip_conntrack_tuple tuple;
2193 + struct ip_conntrack_tuple_hash *found;
2194 + struct ipt_connlimit_conn *conn;
2195 + struct list_head *hash,*lh;
2197 + spin_lock(&data->lock);
2198 + tuple = ct->tuplehash[0].tuple;
2199 + hash = &data->iphash[ipt_iphash(addr & mask)];
2201 + /* check the saved connections */
2202 + for (lh = hash->next; lh != hash; lh = lh->next) {
2203 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
2204 + found = ip_conntrack_find_get(&conn->tuple,ct);
2205 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
2207 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
2208 + /* Just to be sure we have it only once in the list.
2209 + We should'nt see tuples twice unless someone hooks this
2210 + into a table without "-p tcp --syn" */
2214 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
2215 + ipt_iphash(addr & mask),
2216 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
2217 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
2218 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
2220 + if (NULL == found) {
2221 + /* this one is gone */
2223 + list_del(lh->next);
2227 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
2228 + /* we don't care about connections which are
2229 + closed already -> ditch it */
2231 + list_del(lh->next);
2233 + nf_conntrack_put(&found->ctrack->infos[0]);
2236 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
2237 + /* same source IP address -> be counted! */
2240 + nf_conntrack_put(&found->ctrack->infos[0]);
2243 + /* save the new connection in our list */
2245 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
2246 + ipt_iphash(addr & mask),
2247 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
2248 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
2250 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
2253 + memset(conn,0,sizeof(*conn));
2254 + INIT_LIST_HEAD(&conn->list);
2255 + conn->tuple = tuple;
2256 + list_add(&conn->list,hash);
2259 + spin_unlock(&data->lock);
2264 +match(const struct sk_buff *skb,
2265 + const struct net_device *in,
2266 + const struct net_device *out,
2267 + const void *matchinfo,
2271 + const struct ipt_connlimit_info *info = matchinfo;
2272 + int connections, match;
2273 + struct ip_conntrack *ct;
2274 + enum ip_conntrack_info ctinfo;
2276 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2278 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
2282 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
2283 + if (-1 == connections) {
2284 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
2285 + *hotdrop = 1; /* let's free some memory :-) */
2288 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
2290 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
2291 + "connections=%d limit=%d match=%s\n",
2292 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
2293 + connections, info->limit, match ? "yes" : "no");
2299 +static int check(const char *tablename,
2300 + const struct ipt_ip *ip,
2302 + unsigned int matchsize,
2303 + unsigned int hook_mask)
2305 + struct ipt_connlimit_info *info = matchinfo;
2309 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
2312 + /* refuse anything but tcp */
2313 + if (ip->proto != IPPROTO_TCP)
2316 + /* init private data */
2317 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
2318 + spin_lock_init(&(info->data->lock));
2319 + for (i = 0; i < 256; i++)
2320 + INIT_LIST_HEAD(&(info->data->iphash[i]));
2325 +static void destroy(void *matchinfo, unsigned int matchinfosize)
2327 + struct ipt_connlimit_info *info = matchinfo;
2328 + struct ipt_connlimit_conn *conn;
2329 + struct list_head *hash;
2333 + for (i = 0; i < 256; i++) {
2334 + hash = &(info->data->iphash[i]);
2335 + while (hash != hash->next) {
2336 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
2337 + list_del(hash->next);
2341 + kfree(info->data);
2344 +static struct ipt_match connlimit_match = {
2345 + .name = "connlimit",
2347 + .checkentry = &check,
2348 + .destroy = &destroy,
2352 +static int __init init(void)
2354 + return ipt_register_match(&connlimit_match);
2357 +static void __exit fini(void)
2359 + ipt_unregister_match(&connlimit_match);
2364 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c
2365 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
2366 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c 2004-04-29 09:48:04.000000000 +0200
2368 +/* iptables match extension to limit the number of packets per second
2369 + * seperately for each destination.
2371 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2375 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2377 + * based on ipt_limit.c by:
2378 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
2379 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
2380 + * Rusty Russell <rusty@rustcorp.com.au>
2382 + * The general idea is to create a hash table for every dstip and have a
2383 + * seperate limit counter per tuple. This way you can do something like 'limit
2384 + * the number of syn packets for each of my internal addresses.
2386 + * Ideally this would just be implemented as a general 'hash' match, which would
2387 + * allow us to attach any iptables target to it's hash buckets. But this is
2388 + * not possible in the current iptables architecture. As always, pkttables for
2389 + * 2.7.x will help ;)
2391 +#include <linux/module.h>
2392 +#include <linux/skbuff.h>
2393 +#include <linux/spinlock.h>
2394 +#include <linux/random.h>
2395 +#include <linux/jhash.h>
2396 +#include <linux/slab.h>
2397 +#include <linux/vmalloc.h>
2398 +#include <linux/tcp.h>
2399 +#include <linux/udp.h>
2400 +#include <linux/proc_fs.h>
2401 +#include <linux/seq_file.h>
2403 +#define ASSERT_READ_LOCK(x)
2404 +#define ASSERT_WRITE_LOCK(x)
2405 +#include <linux/netfilter_ipv4/lockhelp.h>
2406 +#include <linux/netfilter_ipv4/listhelp.h>
2408 +#include <linux/netfilter_ipv4/ip_tables.h>
2409 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2411 +/* FIXME: this is just for IP_NF_ASSERRT */
2412 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2414 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2416 +MODULE_LICENSE("GPL");
2417 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2418 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2420 +/* need to declare this at the top */
2421 +static struct proc_dir_entry *dstlimit_procdir;
2422 +static struct file_operations dl_file_ops;
2424 +/* hash table crap */
2426 +struct dsthash_dst {
2432 +struct dsthash_ent {
2433 + /* static / read-only parts in the beginning */
2434 + struct list_head list;
2435 + struct dsthash_dst dst;
2437 + /* modified structure members in the end */
2438 + unsigned long expires; /* precalculated expiry time */
2440 + unsigned long prev; /* last modification */
2442 + u_int32_t credit_cap, cost;
2446 +struct ipt_dstlimit_htable {
2447 + struct list_head list; /* global list of all htables */
2450 + struct dstlimit_cfg cfg; /* config */
2452 + /* used internally */
2453 + spinlock_t lock; /* lock for list_head */
2454 + u_int32_t rnd; /* random seed for hash */
2455 + struct timer_list timer; /* timer for gc */
2456 + atomic_t count; /* number entries in table */
2458 + /* seq_file stuff */
2459 + struct proc_dir_entry *pde;
2461 + struct list_head hash[0]; /* hashtable itself */
2464 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
2465 +static LIST_HEAD(dstlimit_htables);
2466 +static kmem_cache_t *dstlimit_cachep;
2468 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
2470 + return (ent->dst.dst_ip == b->dst_ip
2471 + && ent->dst.port == b->port
2472 + && ent->dst.src_ip == b->src_ip);
2475 +static inline u_int32_t
2476 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
2478 + return (jhash_3words(dst->dst_ip, dst->port,
2479 + dst->src_ip, ht->rnd) % ht->cfg.size);
2482 +static inline struct dsthash_ent *
2483 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2485 + struct dsthash_ent *ent;
2486 + u_int32_t hash = hash_dst(ht, dst);
2487 + MUST_BE_LOCKED(&ht->lock);
2488 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
2492 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
2493 +static struct dsthash_ent *
2494 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2496 + struct dsthash_ent *ent;
2498 + /* initialize hash with random val at the time we allocate
2499 + * the first hashtable entry */
2501 + get_random_bytes(&ht->rnd, 4);
2503 + if (ht->cfg.max &&
2504 + atomic_read(&ht->count) >= ht->cfg.max) {
2505 + /* FIXME: do something. question is what.. */
2506 + if (net_ratelimit())
2507 + printk(KERN_WARNING
2508 + "ipt_dstlimit: max count of %u reached\n",
2513 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
2515 + if (net_ratelimit())
2517 + "ipt_dstlimit: can't allocate dsthash_ent\n");
2521 + atomic_inc(&ht->count);
2523 + ent->dst.dst_ip = dst->dst_ip;
2524 + ent->dst.port = dst->port;
2525 + ent->dst.src_ip = dst->src_ip;
2527 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
2533 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
2535 + MUST_BE_LOCKED(&ht->lock);
2537 + list_del(&ent->list);
2538 + kmem_cache_free(dstlimit_cachep, ent);
2539 + atomic_dec(&ht->count);
2541 +static void htable_gc(unsigned long htlong);
2543 +static int htable_create(struct ipt_dstlimit_info *minfo)
2546 + unsigned int size;
2547 + struct ipt_dstlimit_htable *hinfo;
2549 + if (minfo->cfg.size)
2550 + size = minfo->cfg.size;
2552 + size = (((num_physpages << PAGE_SHIFT) / 16384)
2553 + / sizeof(struct list_head));
2554 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
2559 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
2560 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
2561 + + (sizeof(struct list_head) * size));
2563 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
2566 + minfo->hinfo = hinfo;
2568 + /* copy match config into hashtable config */
2569 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
2570 + hinfo->cfg.size = size;
2571 + if (!hinfo->cfg.max)
2572 + hinfo->cfg.max = 8 * hinfo->cfg.size;
2573 + else if (hinfo->cfg.max < hinfo->cfg.size)
2574 + hinfo->cfg.max = hinfo->cfg.size;
2576 + for (i = 0; i < hinfo->cfg.size; i++)
2577 + INIT_LIST_HEAD(&hinfo->hash[i]);
2579 + atomic_set(&hinfo->count, 0);
2580 + atomic_set(&hinfo->use, 1);
2582 + hinfo->lock = SPIN_LOCK_UNLOCKED;
2583 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
2584 + if (!hinfo->pde) {
2588 + hinfo->pde->proc_fops = &dl_file_ops;
2589 + hinfo->pde->data = hinfo;
2591 + init_timer(&hinfo->timer);
2592 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
2593 + hinfo->timer.data = (unsigned long )hinfo;
2594 + hinfo->timer.function = htable_gc;
2595 + add_timer(&hinfo->timer);
2597 + WRITE_LOCK(&dstlimit_lock);
2598 + list_add(&hinfo->list, &dstlimit_htables);
2599 + WRITE_UNLOCK(&dstlimit_lock);
2604 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2609 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2611 + return (jiffies >= he->expires);
2614 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
2615 + int (*select)(struct ipt_dstlimit_htable *ht,
2616 + struct dsthash_ent *he))
2620 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
2622 + /* lock hash table and iterate over it */
2623 + LOCK_BH(&ht->lock);
2624 + for (i = 0; i < ht->cfg.size; i++) {
2625 + struct dsthash_ent *dh, *n;
2626 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
2627 + if ((*select)(ht, dh))
2628 + __dsthash_free(ht, dh);
2631 + UNLOCK_BH(&ht->lock);
2634 +/* hash table garbage collector, run by timer */
2635 +static void htable_gc(unsigned long htlong)
2637 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
2639 + htable_selective_cleanup(ht, select_gc);
2641 + /* re-add the timer accordingly */
2642 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
2643 + add_timer(&ht->timer);
2646 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
2648 + /* remove timer, if it is pending */
2649 + if (timer_pending(&hinfo->timer))
2650 + del_timer(&hinfo->timer);
2652 + /* remove proc entry */
2653 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
2655 + htable_selective_cleanup(hinfo, select_all);
2659 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
2661 + struct ipt_dstlimit_htable *hinfo;
2663 + READ_LOCK(&dstlimit_lock);
2664 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
2665 + if (!strcmp(name, hinfo->pde->name)) {
2666 + atomic_inc(&hinfo->use);
2667 + READ_UNLOCK(&dstlimit_lock);
2671 + READ_UNLOCK(&dstlimit_lock);
2676 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
2678 + if (atomic_dec_and_test(&hinfo->use)) {
2679 + WRITE_LOCK(&dstlimit_lock);
2680 + list_del(&hinfo->list);
2681 + WRITE_UNLOCK(&dstlimit_lock);
2682 + htable_destroy(hinfo);
2687 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
2688 + * see net/sched/sch_tbf.c in the linux source tree
2691 +/* Rusty: This is my (non-mathematically-inclined) understanding of
2692 + this algorithm. The `average rate' in jiffies becomes your initial
2693 + amount of credit `credit' and the most credit you can ever have
2694 + `credit_cap'. The `peak rate' becomes the cost of passing the
2697 + `prev' tracks the last packet hit: you gain one credit per jiffy.
2698 + If you get credit balance more than this, the extra credit is
2699 + discarded. Every time the match passes, you lose `cost' credits;
2700 + if you don't have that many, the test fails.
2702 + See Alexey's formal explanation in net/sched/sch_tbf.c.
2704 + To get the maximum range, we multiply by this factor (ie. you get N
2705 + credits per jiffy). We want to allow a rate as low as 1 per day
2706 + (slowest userspace tool allows), which means
2707 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
2709 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
2711 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
2712 + * us the power of 2 below the theoretical max, so GCC simply does a
2714 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
2715 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
2716 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
2717 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
2718 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
2719 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
2721 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
2723 +/* Precision saver. */
2724 +static inline u_int32_t
2725 +user2credits(u_int32_t user)
2727 + /* If multiplying would overflow... */
2728 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
2729 + /* Divide first. */
2730 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
2732 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
2735 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
2737 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
2738 + * CREDITS_PER_JIFFY;
2739 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
2740 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
2744 +dstlimit_match(const struct sk_buff *skb,
2745 + const struct net_device *in,
2746 + const struct net_device *out,
2747 + const void *matchinfo,
2751 + struct ipt_dstlimit_info *r =
2752 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
2753 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
2754 + unsigned long now = jiffies;
2755 + struct dsthash_ent *dh;
2756 + struct dsthash_dst dst;
2758 + memset(&dst, 0, sizeof(dst));
2760 + /* dest ip is always in hash */
2761 + dst.dst_ip = skb->nh.iph->daddr;
2763 + /* source ip only if respective hashmode, otherwise set to
2765 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
2766 + dst.src_ip = skb->nh.iph->saddr;
2768 + /* dest port only if respective mode */
2769 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
2772 + /* Must not be a fragment. */
2776 + /* Must be big enough to read ports (both UDP and TCP have
2777 + them at the start). */
2778 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
2779 + /* We've been asked to examine this packet, and we
2780 + can't. Hence, no choice but to drop. */
2785 + switch (skb->nh.iph->protocol) {
2786 + struct tcphdr *th;
2787 + struct udphdr *uh;
2789 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2790 + dst.port = th->dest;
2793 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2794 + dst.port = uh->dest;
2801 + LOCK_BH(&hinfo->lock);
2802 + dh = __dsthash_find(hinfo, &dst);
2804 + dh = __dsthash_alloc_init(hinfo, &dst);
2807 + /* enomem... don't match == DROP */
2808 + if (net_ratelimit())
2809 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
2810 + UNLOCK_BH(&hinfo->lock);
2814 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
2816 + dh->rateinfo.prev = jiffies;
2817 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
2818 + hinfo->cfg.burst);
2819 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
2820 + hinfo->cfg.burst);
2821 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
2823 + UNLOCK_BH(&hinfo->lock);
2827 + /* update expiration timeout */
2828 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
2830 + rateinfo_recalc(dh, now);
2831 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
2832 + /* We're underlimit. */
2833 + dh->rateinfo.credit -= dh->rateinfo.cost;
2834 + UNLOCK_BH(&hinfo->lock);
2838 + UNLOCK_BH(&hinfo->lock);
2840 + /* default case: we're overlimit, thus don't match */
2845 +dstlimit_checkentry(const char *tablename,
2846 + const struct ipt_ip *ip,
2848 + unsigned int matchsize,
2849 + unsigned int hook_mask)
2851 + struct ipt_dstlimit_info *r = matchinfo;
2853 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
2856 + /* Check for overflow. */
2857 + if (r->cfg.burst == 0
2858 + || user2credits(r->cfg.avg * r->cfg.burst) <
2859 + user2credits(r->cfg.avg)) {
2860 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
2861 + r->cfg.avg, r->cfg.burst);
2865 + if (r->cfg.mode == 0
2866 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
2867 + |IPT_DSTLIMIT_HASH_DIP
2868 + |IPT_DSTLIMIT_HASH_SIP))
2871 + if (!r->cfg.gc_interval)
2874 + if (!r->cfg.expire)
2877 + r->hinfo = htable_find_get(r->name);
2878 + if (!r->hinfo && (htable_create(r) != 0)) {
2882 + /* Ugly hack: For SMP, we only want to use one set */
2889 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
2891 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
2893 + htable_put(r->hinfo);
2896 +static struct ipt_match ipt_dstlimit = {
2897 + .list = { .prev = NULL, .next = NULL },
2898 + .name = "dstlimit",
2899 + .match = dstlimit_match,
2900 + .checkentry = dstlimit_checkentry,
2901 + .destroy = dstlimit_destroy,
2907 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
2909 + struct proc_dir_entry *pde = s->private;
2910 + struct ipt_dstlimit_htable *htable = pde->data;
2911 + unsigned int *bucket;
2913 + LOCK_BH(&htable->lock);
2914 + if (*pos >= htable->cfg.size)
2917 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
2919 + return ERR_PTR(-ENOMEM);
2925 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
2927 + struct proc_dir_entry *pde = s->private;
2928 + struct ipt_dstlimit_htable *htable = pde->data;
2929 + unsigned int *bucket = (unsigned int *)v;
2931 + *pos = ++(*bucket);
2932 + if (*pos >= htable->cfg.size) {
2939 +static void dl_seq_stop(struct seq_file *s, void *v)
2941 + struct proc_dir_entry *pde = s->private;
2942 + struct ipt_dstlimit_htable *htable = pde->data;
2943 + unsigned int *bucket = (unsigned int *)v;
2947 + UNLOCK_BH(&htable->lock);
2950 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
2952 + /* recalculate to show accurate numbers */
2953 + rateinfo_recalc(ent, jiffies);
2955 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
2956 + (ent->expires - jiffies)/HZ,
2957 + NIPQUAD(ent->dst.src_ip),
2958 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
2959 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
2960 + ent->rateinfo.cost);
2963 +static int dl_seq_show(struct seq_file *s, void *v)
2965 + struct proc_dir_entry *pde = s->private;
2966 + struct ipt_dstlimit_htable *htable = pde->data;
2967 + unsigned int *bucket = (unsigned int *)v;
2969 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
2970 + struct dsthash_ent *, s)) {
2971 + /* buffer was filled and unable to print that tuple */
2977 +static struct seq_operations dl_seq_ops = {
2978 + .start = dl_seq_start,
2979 + .next = dl_seq_next,
2980 + .stop = dl_seq_stop,
2981 + .show = dl_seq_show
2984 +static int dl_proc_open(struct inode *inode, struct file *file)
2986 + int ret = seq_open(file, &dl_seq_ops);
2989 + struct seq_file *sf = file->private_data;
2990 + sf->private = PDE(inode);
2995 +static struct file_operations dl_file_ops = {
2996 + .owner = THIS_MODULE,
2997 + .open = dl_proc_open,
2999 + .llseek = seq_lseek,
3000 + .release = seq_release
3003 +static int init_or_fini(int fini)
3010 + if (ipt_register_match(&ipt_dstlimit)) {
3012 + goto cleanup_nothing;
3015 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
3016 + * quite small ? */
3017 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
3018 + sizeof(struct dsthash_ent), 0,
3019 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3020 + if (!dstlimit_cachep) {
3021 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
3023 + goto cleanup_unreg_match;
3026 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
3027 + if (!dstlimit_procdir) {
3028 + printk(KERN_ERR "Unable to create proc dir entry\n");
3030 + goto cleanup_free_slab;
3036 + remove_proc_entry("ipt_dstlimit", proc_net);
3038 + kmem_cache_destroy(dstlimit_cachep);
3039 +cleanup_unreg_match:
3040 + ipt_unregister_match(&ipt_dstlimit);
3046 +static int __init init(void)
3048 + return init_or_fini(0);
3051 +static void __exit fini(void)
3058 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_fuzzy.c
3059 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
3060 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_fuzzy.c 2004-04-29 09:48:15.000000000 +0200
3063 + * This module implements a simple TSK FLC
3064 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
3065 + * to limit , in an adaptive and flexible way , the packet rate crossing
3066 + * a given stream . It serves as an initial and very simple (but effective)
3067 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
3068 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
3069 + * into our code in a precise , adaptive and efficient manner.
3070 + * The goal is very similar to that of "limit" match , but using techniques of
3071 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
3072 + * avoiding over and undershoots - and stuff like that .
3075 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
3076 + * 2002-08-17 : Changed to eliminate floating point operations .
3077 + * 2002-08-23 : Coding style changes .
3080 +#include <linux/module.h>
3081 +#include <linux/skbuff.h>
3082 +#include <linux/ip.h>
3083 +#include <linux/random.h>
3084 +#include <net/tcp.h>
3085 +#include <linux/spinlock.h>
3086 +#include <linux/netfilter_ipv4/ip_tables.h>
3087 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
3090 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
3091 + Expressed in percentage
3094 +#define PAR_LOW 1/100
3097 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
3099 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
3100 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
3101 +MODULE_LICENSE("GPL");
3103 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3111 + return ( (100*(tx-mini)) / (maxi-mini) );
3114 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3122 + return ( (100*( maxi - tx )) / ( maxi - mini ) );
3126 +ipt_fuzzy_match(const struct sk_buff *pskb,
3127 + const struct net_device *in,
3128 + const struct net_device *out,
3129 + const void *matchinfo,
3133 + /* From userspace */
3135 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
3137 + u_int8_t random_number;
3138 + unsigned long amount;
3139 + u_int8_t howhigh, howlow;
3142 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
3144 + info->bytes_total += pskb->len;
3145 + info->packets_total++;
3147 + info->present_time = jiffies;
3149 + if (info->present_time >= info->previous_time)
3150 + amount = info->present_time - info->previous_time;
3152 + /* There was a transition : I choose to re-sample
3153 + and keep the old acceptance rate...
3157 + info->previous_time = info->present_time;
3158 + info->bytes_total = info->packets_total = 0;
3161 + if (amount > HZ/10) /* More than 100 ms elapsed ... */
3164 + info->mean_rate = (u_int32_t) ((HZ*info->packets_total) \
3167 + info->previous_time = info->present_time;
3168 + info->bytes_total = info->packets_total = 0;
3170 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
3171 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
3173 + info->acceptance_rate = (u_int8_t) \
3174 + (howhigh*PAR_LOW + PAR_HIGH*howlow);
3176 + /* In fact , the above defuzzification would require a denominator
3177 + proportional to (howhigh+howlow) but , in this particular case ,
3178 + that expression is constant .
3179 + An imediate consequence is that it isn't necessary to call
3180 + both mf_high and mf_low - but to keep things understandable ,
3185 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
3188 + if ( info->acceptance_rate < 100 )
3190 + get_random_bytes((void *)(&random_number), 1);
3192 + /* If within the acceptance , it can pass => don't match */
3193 + if (random_number <= (255 * info->acceptance_rate) / 100)
3196 + return 1; /* It can't pass ( It matches ) */
3199 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
3204 +ipt_fuzzy_checkentry(const char *tablename,
3205 + const struct ipt_ip *e,
3207 + unsigned int matchsize,
3208 + unsigned int hook_mask)
3211 + const struct ipt_fuzzy_info *info = matchinfo;
3213 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
3214 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
3215 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
3219 + if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
3220 + || (info->minimum_rate >= info->maximum_rate )) {
3221 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
3228 +static struct ipt_match ipt_fuzzy_reg = {
3230 + .match = ipt_fuzzy_match,
3231 + .checkentry = ipt_fuzzy_checkentry,
3235 +static int __init init(void)
3237 + return ipt_register_match(&ipt_fuzzy_reg);
3240 +static void __exit fini(void)
3242 + ipt_unregister_match(&ipt_fuzzy_reg);
3247 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c
3248 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-04-28 03:36:22.000000000 +0200
3249 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c 2004-04-29 09:45:14.000000000 +0200
3251 struct ip_conntrack_expect *exp;
3252 struct ip_conntrack *ct;
3253 enum ip_conntrack_info ctinfo;
3255 + int ret = info->invert;
3257 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
3259 DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
3265 DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
3272 DEBUGP("master's name = %s , info->name = %s\n",
3273 exp->expectant->helper->name, info->name);
3275 - ret = !strncmp(exp->expectant->helper->name, info->name,
3276 - strlen(exp->expectant->helper->name)) ^ info->invert;
3277 + ret ^= !strncmp(exp->expectant->helper->name, info->name,
3278 + strlen(exp->expectant->helper->name));
3280 READ_UNLOCK(&ip_conntrack_lock);
3284 static int __init init(void)
3286 - need_ip_conntrack();
3287 return ipt_register_match(&helper_match);
3290 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_ipv4options.c
3291 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
3292 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_ipv4options.c 2004-04-29 09:48:49.000000000 +0200
3295 + This is a module which is used to match ipv4 options.
3296 + This file is distributed under the terms of the GNU General Public
3297 + License (GPL). Copies of the GPL can be obtained from:
3298 + ftp://prep.ai.mit.edu/pub/gnu/GPL
3300 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
3301 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
3302 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
3303 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
3304 + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
3307 +#include <linux/module.h>
3308 +#include <linux/skbuff.h>
3309 +#include <net/ip.h>
3311 +#include <linux/netfilter_ipv4/ip_tables.h>
3312 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
3314 +MODULE_LICENSE("GPL");
3315 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3318 +match(const struct sk_buff *skb,
3319 + const struct net_device *in,
3320 + const struct net_device *out,
3321 + const void *matchinfo,
3325 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
3326 + const struct iphdr *iph = skb->nh.iph;
3327 + const struct ip_options *opt;
3329 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
3330 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
3332 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
3333 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3334 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3335 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3336 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3337 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
3342 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
3343 + /* there are options, and we don't need to care which one */
3346 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
3347 + /* there are options but we don't want any ! */
3352 + opt = &(IPCB(skb)->opt);
3354 + /* source routing */
3355 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
3356 + if (!((opt->srr) & (opt->is_strictroute)))
3359 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
3360 + if (!((opt->srr) & (!opt->is_strictroute)))
3363 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
3367 + /* record route */
3368 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
3372 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
3377 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
3381 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3385 + /* router-alert option */
3386 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3387 + if (!opt->router_alert)
3390 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3391 + if (opt->router_alert)
3400 +checkentry(const char *tablename,
3401 + const struct ipt_ip *ip,
3403 + unsigned int matchsize,
3404 + unsigned int hook_mask)
3406 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
3407 + /* Check the size */
3408 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
3410 + /* Now check the coherence of the data ... */
3411 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
3412 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
3413 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
3414 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
3415 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
3416 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
3417 + return 0; /* opposites */
3418 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
3419 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3420 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3421 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3422 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3423 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
3424 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
3425 + return 0; /* opposites */
3426 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
3427 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
3428 + return 0; /* cannot match in the same time loose and strict source routing */
3429 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3430 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
3431 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
3432 + return 0; /* opposites */
3433 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
3434 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
3435 + return 0; /* opposites */
3436 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
3437 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
3438 + return 0; /* opposites */
3439 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
3440 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
3441 + return 0; /* opposites */
3443 + /* everything looks ok. */
3447 +static struct ipt_match ipv4options_match = {
3448 + .name = "ipv4options",
3450 + .checkentry = checkentry,
3454 +static int __init init(void)
3456 + return ipt_register_match(&ipv4options_match);
3459 +static void __exit fini(void)
3461 + ipt_unregister_match(&ipv4options_match);
3466 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_mport.c
3467 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
3468 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_mport.c 2004-04-29 09:49:01.000000000 +0200
3470 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
3471 + the same place so we can treat them as equal. */
3472 +#include <linux/module.h>
3473 +#include <linux/types.h>
3474 +#include <linux/udp.h>
3475 +#include <linux/skbuff.h>
3477 +#include <linux/netfilter_ipv4/ipt_mport.h>
3478 +#include <linux/netfilter_ipv4/ip_tables.h>
3480 +MODULE_LICENSE("GPL");
3483 +#define duprintf(format, args...) printk(format , ## args)
3485 +#define duprintf(format, args...)
3488 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3490 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
3494 + u_int16_t pflags = minfo->pflags;
3495 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
3499 + && minfo->ports[i] == 65535)
3502 + s = minfo->ports[i];
3505 + e = minfo->ports[++i];
3510 + if (minfo->flags & IPT_MPORT_SOURCE
3511 + && src >= s && src <= e)
3514 + if (minfo->flags & IPT_MPORT_DESTINATION
3515 + && dst >= s && dst <= e)
3523 +match(const struct sk_buff *skb,
3524 + const struct net_device *in,
3525 + const struct net_device *out,
3526 + const void *matchinfo,
3531 + const struct ipt_mport *minfo = matchinfo;
3536 + /* Must be big enough to read ports (both UDP and TCP have
3537 + them at the start). */
3538 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
3539 + /* We've been asked to examine this packet, and we
3540 + can't. Hence, no choice but to drop. */
3541 + duprintf("ipt_multiport:"
3542 + " Dropping evil offset=0 tinygram.\n");
3547 + return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
3550 +/* Called when user tries to insert an entry of this type. */
3552 +checkentry(const char *tablename,
3553 + const struct ipt_ip *ip,
3555 + unsigned int matchsize,
3556 + unsigned int hook_mask)
3558 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
3561 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
3562 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
3563 + && !(ip->invflags & IPT_INV_PROTO)
3564 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
3567 +static struct ipt_match mport_match = {
3570 + .checkentry = &checkentry,
3574 +static int __init init(void)
3576 + return ipt_register_match(&mport_match);
3579 +static void __exit fini(void)
3581 + ipt_unregister_match(&mport_match);
3586 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_nth.c
3587 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
3588 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_nth.c 2004-04-29 09:49:13.000000000 +0200
3591 + This is a module which is used for match support for every Nth packet
3592 + This file is distributed under the terms of the GNU General Public
3593 + License (GPL). Copies of the GPL can be obtained from:
3594 + ftp://prep.ai.mit.edu/pub/gnu/GPL
3596 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
3597 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
3598 + * added support for multiple counters
3599 + * added support for matching on individual packets
3600 + in the counter cycle
3601 + 2004-02-19 Harald Welte <laforge@netfilter.org>
3606 +#include <linux/module.h>
3607 +#include <linux/skbuff.h>
3608 +#include <linux/ip.h>
3609 +#include <net/tcp.h>
3610 +#include <linux/spinlock.h>
3611 +#include <linux/netfilter_ipv4/ip_tables.h>
3612 +#include <linux/netfilter_ipv4/ipt_nth.h>
3614 +MODULE_LICENSE("GPL");
3615 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3618 + * State information.
3625 +static struct state states[IPT_NTH_NUM_COUNTERS];
3628 +ipt_nth_match(const struct sk_buff *pskb,
3629 + const struct net_device *in,
3630 + const struct net_device *out,
3631 + const void *matchinfo,
3635 + /* Parameters from userspace */
3636 + const struct ipt_nth_info *info = matchinfo;
3637 + unsigned counter = info->counter;
3638 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
3640 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3644 + spin_lock(&states[counter].lock);
3646 + /* Are we matching every nth packet?*/
3647 + if (info->packet == 0xFF)
3649 + /* We're matching every nth packet and only every nth packet*/
3650 + /* Do we match or invert match? */
3651 + if (info->not == 0)
3653 + if (states[counter].number == 0)
3655 + ++states[counter].number;
3658 + if (states[counter].number >= info->every)
3659 + states[counter].number = 0; /* reset the counter */
3661 + ++states[counter].number;
3666 + if (states[counter].number == 0)
3668 + ++states[counter].number;
3671 + if (states[counter].number >= info->every)
3672 + states[counter].number = 0;
3674 + ++states[counter].number;
3680 + /* We're using the --packet, so there must be a rule for every value */
3681 + if (states[counter].number == info->packet)
3683 + /* only increment the counter when a match happens */
3684 + if (states[counter].number >= info->every)
3685 + states[counter].number = 0; /* reset the counter */
3687 + ++states[counter].number;
3696 + spin_unlock(&states[counter].lock);
3700 + spin_unlock(&states[counter].lock);
3705 +ipt_nth_checkentry(const char *tablename,
3706 + const struct ipt_ip *e,
3708 + unsigned int matchsize,
3709 + unsigned int hook_mask)
3711 + /* Parameters from userspace */
3712 + const struct ipt_nth_info *info = matchinfo;
3713 + unsigned counter = info->counter;
3714 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
3716 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3720 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
3721 + printk("nth: matchsize %u != %u\n", matchsize,
3722 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
3726 + states[counter].number = info->startat;
3731 +static struct ipt_match ipt_nth_reg = {
3733 + .match = ipt_nth_match,
3734 + .checkentry = ipt_nth_checkentry,
3738 +static int __init init(void)
3742 + memset(&states, 0, sizeof(states));
3743 + for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
3744 + spin_lock_init(&(states[counter].lock));
3746 + return ipt_register_match(&ipt_nth_reg);
3749 +static void __exit fini(void)
3751 + ipt_unregister_match(&ipt_nth_reg);
3756 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_osf.c
3757 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
3758 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_osf.c 2004-04-29 09:49:24.000000000 +0200
3763 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
3766 + * This program is free software; you can redistribute it and/or modify
3767 + * it under the terms of the GNU General Public License as published by
3768 + * the Free Software Foundation; either version 2 of the License, or
3769 + * (at your option) any later version.
3771 + * This program is distributed in the hope that it will be useful,
3772 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3773 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3774 + * GNU General Public License for more details.
3776 + * You should have received a copy of the GNU General Public License
3777 + * along with this program; if not, write to the Free Software
3778 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3782 + * OS fingerprint matching module.
3783 + * It simply compares various parameters from SYN packet with
3784 + * some hardcoded ones.
3786 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
3790 +#include <linux/config.h>
3791 +#include <linux/kernel.h>
3792 +#include <linux/types.h>
3793 +#include <linux/string.h>
3794 +#include <linux/smp.h>
3795 +#include <linux/module.h>
3796 +#include <linux/skbuff.h>
3797 +#include <linux/file.h>
3798 +#include <linux/ip.h>
3799 +#include <linux/proc_fs.h>
3800 +#include <linux/fs.h>
3801 +#include <linux/slab.h>
3802 +#include <linux/spinlock.h>
3803 +#include <linux/ctype.h>
3804 +#include <linux/list.h>
3805 +#include <linux/if.h>
3807 +#include <net/sock.h>
3808 +#include <net/ip.h>
3810 +#include <linux/netfilter_ipv4/ip_tables.h>
3812 +#include <linux/netfilter_ipv4/ipt_osf.h>
3817 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
3818 +#define loga(x...) printk(x)
3820 +#define log(x...) do {} while(0)
3821 +#define loga(x...) do {} while(0)
3824 +#define FMATCH_WRONG 0
3825 +#define FMATCH_OK 1
3826 +#define FMATCH_OPT_WRONG 2
3829 +#define OSFPDEL ':'
3830 +#define MAXOPTSTRLEN 128
3831 +#define OSFFLUSH "FLUSH"
3833 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
3834 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
3835 +static struct list_head finger_list;
3836 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
3837 + const void *, int,
3838 + const void *, u_int16_t,
3840 +static int checkentry(const char *, const struct ipt_ip *, void *,
3841 + unsigned int, unsigned int);
3843 +static unsigned long seq, ipt_osf_groups = 1;
3844 +static struct sock *nts;
3846 +static struct ipt_match osf_match =
3856 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
3858 + unsigned int size;
3859 + struct sk_buff *skb;
3860 + struct ipt_osf_nlmsg *data;
3861 + struct nlmsghdr *nlh;
3863 + size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
3865 + skb = alloc_skb(size, GFP_ATOMIC);
3868 + log("skb_alloc() failed.\n");
3872 + nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
3874 + data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
3876 + memcpy(&data->f, f, sizeof(struct osf_finger));
3877 + memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
3878 + memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
3880 + NETLINK_CB(skb).dst_groups = ipt_osf_groups;
3881 + netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
3887 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
3889 + struct iphdr *ip = skb->nh.iph;
3891 + if (flags & IPT_OSF_SMART)
3893 + struct in_device *in_dev = in_dev_get(skb->dev);
3897 + if (inet_ifa_match(ip->saddr, ifa))
3899 + in_dev_put(in_dev);
3900 + return (ip->ttl == f_ttl);
3903 + endfor_ifa(in_dev);
3905 + in_dev_put(in_dev);
3906 + return (ip->ttl <= f_ttl);
3909 + return (ip->ttl == f_ttl);
3913 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
3914 + const void *matchinfo, int offset,
3915 + const void *hdr, u_int16_t datalen,
3918 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
3919 + struct iphdr *ip = skb->nh.iph;
3920 + struct tcphdr *tcp;
3921 + int fmatch = FMATCH_WRONG, fcount = 0;
3922 + unsigned long totlen, optsize = 0, window;
3923 + unsigned char df, *optp = NULL, *_optp = NULL;
3924 + char check_WSS = 0;
3925 + struct list_head *ent;
3926 + struct osf_finger *f;
3931 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
3936 + totlen = ntohs(ip->tot_len);
3937 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
3938 + window = ntohs(tcp->window);
3940 + if (tcp->doff*4 > sizeof(struct tcphdr))
3942 + _optp = optp = (char *)(tcp+1);
3943 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
3947 + /* Actually we can create hash/table of all genres and search
3948 + * only in appropriate part, but here is initial variant,
3949 + * so will use slow path.
3951 + read_lock(&osf_lock);
3952 + list_for_each(ent, &finger_list)
3954 + f = list_entry(ent, struct osf_finger, flist);
3956 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
3960 + fmatch = FMATCH_WRONG;
3962 + if (totlen == f->ss && df == f->df &&
3963 + smart_dec(skb, info->flags, f->ttl))
3965 + unsigned long foptsize;
3967 + unsigned short mss = 0;
3971 + switch (f->wss.wc)
3973 + case 0: check_WSS = 0; break;
3974 + case 'S': check_WSS = 1; break;
3975 + case 'T': check_WSS = 2; break;
3976 + case '%': check_WSS = 3; break;
3977 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
3978 + f->wss.wc, f->genre, f->details);
3982 + if (check_WSS == 4)
3985 + /* Check options */
3988 + for (optnum=0; optnum<f->opt_num; ++optnum)
3989 + foptsize += f->opt[optnum].length;
3992 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
3997 + fmatch = FMATCH_OK;
3998 + loga("\tYEP : matching without options.\n");
3999 + if ((info->flags & IPT_OSF_LOG) &&
4000 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
4007 + for (optnum=0; optnum<f->opt_num; ++optnum)
4009 + if (f->opt[optnum].kind == (*optp))
4011 + unsigned char len = f->opt[optnum].length;
4012 + unsigned char *optend = optp + len;
4013 + int loop_cont = 0;
4015 + fmatch = FMATCH_OK;
4021 + mss = ntohs(*(unsigned short *)(optp+2));
4036 + /* Skip kind and length fields*/
4039 + if (f->opt[optnum].wc.val != 0)
4041 + unsigned long tmp = 0;
4043 + /* Hmmm... It looks a bit ugly. :) */
4044 + memcpy(&tmp, optp,
4045 + (len > sizeof(unsigned long)?
4046 + sizeof(unsigned long):len));
4047 + /* 2 + 2: optlen(2 bytes) +
4048 + * kind(1 byte) + length(1 byte) */
4054 + if (f->opt[optnum].wc.wc == '%')
4056 + if ((tmp % f->opt[optnum].wc.val) != 0)
4057 + fmatch = FMATCH_OPT_WRONG;
4059 + else if (tmp != f->opt[optnum].wc.val)
4060 + fmatch = FMATCH_OPT_WRONG;
4067 + fmatch = FMATCH_OPT_WRONG;
4069 + if (fmatch != FMATCH_OK)
4073 + if (fmatch != FMATCH_OPT_WRONG)
4075 + fmatch = FMATCH_WRONG;
4077 + switch (check_WSS)
4080 + if (f->wss.val == 0 || window == f->wss.val)
4081 + fmatch = FMATCH_OK;
4084 +/* Lurked in OpenBSD */
4085 +#define SMART_MSS 1460
4086 + if (window == f->wss.val*mss ||
4087 + window == f->wss.val*SMART_MSS)
4088 + fmatch = FMATCH_OK;
4091 + if (window == f->wss.val*(mss+40) ||
4092 + window == f->wss.val*(SMART_MSS+40))
4093 + fmatch = FMATCH_OK;
4096 + if ((window % f->wss.val) == 0)
4097 + fmatch = FMATCH_OK;
4103 + if (fmatch == FMATCH_OK)
4106 + log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
4107 + f->genre, f->version,
4108 + f->subtype, f->details,
4109 + NIPQUAD(ip->saddr), ntohs(tcp->source),
4110 + NIPQUAD(ip->daddr), ntohs(tcp->dest),
4111 + f->ttl - ip->ttl);
4112 + if (info->flags & IPT_OSF_NETLINK)
4114 + spin_lock_bh(&ipt_osf_netlink_lock);
4115 + ipt_osf_nlsend(f, skb);
4116 + spin_unlock_bh(&ipt_osf_netlink_lock);
4118 + if ((info->flags & IPT_OSF_LOG) &&
4119 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
4124 + if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
4126 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
4127 + unsigned int i, optsize;
4128 + struct osf_finger fg;
4130 + memset(&fg, 0, sizeof(fg));
4132 + if ((info->flags & IPT_OSF_LOG))
4133 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
4136 + optsize = tcp->doff * 4 - sizeof(struct tcphdr);
4137 + if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
4138 + opt, optsize) < 0)
4140 + if (info->flags & IPT_OSF_LOG)
4141 + loga("TRUNCATED");
4142 + if (info->flags & IPT_OSF_NETLINK)
4143 + strcpy(fg.details, "TRUNCATED");
4147 + for (i = 0; i < optsize; i++)
4149 + if (info->flags & IPT_OSF_LOG)
4150 + loga("%02X", opt[i]);
4152 + if (info->flags & IPT_OSF_NETLINK)
4153 + memcpy(fg.details, opt, MAXDETLEN);
4156 + if ((info->flags & IPT_OSF_LOG))
4157 + loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
4158 + NIPQUAD(ip->saddr), ntohs(tcp->source),
4159 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
4161 + if (info->flags & IPT_OSF_NETLINK)
4163 + fg.wss.val = window;
4167 + strncpy(fg.genre, "Unknown", MAXGENRELEN);
4169 + spin_lock_bh(&ipt_osf_netlink_lock);
4170 + ipt_osf_nlsend(&fg, skb);
4171 + spin_unlock_bh(&ipt_osf_netlink_lock);
4175 + read_unlock(&osf_lock);
4177 + return (fmatch == FMATCH_OK)?1:0;
4181 +checkentry(const char *tablename,
4182 + const struct ipt_ip *ip,
4184 + unsigned int matchsize,
4185 + unsigned int hook_mask)
4187 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
4189 + if (ip->proto != IPPROTO_TCP)
4195 +static char * osf_strchr(char *ptr, char c)
4199 + tmp = strchr(ptr, c);
4201 + while (tmp && tmp+1 && isspace(*(tmp+1)))
4207 +static struct osf_finger * finger_alloc(void)
4209 + struct osf_finger *f;
4211 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
4213 + memset(f, 0, sizeof(struct osf_finger));
4218 +static void finger_free(struct osf_finger *f)
4220 + memset(f, 0, sizeof(struct osf_finger));
4225 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
4229 + unsigned long val;
4233 + while (ptr != NULL && i < olen)
4242 + ptr = osf_strchr(&obuf[i], OPTDEL);
4247 + i += (int)(ptr-&obuf[i]);
4254 + op = OSFOPT_SACKP;
4255 + ptr = osf_strchr(&obuf[i], OPTDEL);
4260 + i += (int)(ptr-&obuf[i]);
4268 + ptr = osf_strchr(&obuf[i], OPTDEL);
4273 + i += (int)(ptr-&obuf[i]);
4281 + ptr = osf_strchr(&obuf[i], OPTDEL);
4284 + switch (obuf[i+1])
4286 + case '%': wc = '%'; break;
4287 + case 'S': wc = 'S'; break;
4288 + case 'T': wc = 'T'; break;
4289 + default: wc = 0; break;
4295 + val = simple_strtoul(&obuf[i+2], NULL, 10);
4297 + val = simple_strtoul(&obuf[i+1], NULL, 10);
4298 + i += (int)(ptr-&obuf[i]);
4306 + ptr = osf_strchr(&obuf[i], OPTDEL);
4309 + if (obuf[i+1] == '%')
4314 + val = simple_strtoul(&obuf[i+2], NULL, 10);
4316 + val = simple_strtoul(&obuf[i+1], NULL, 10);
4317 + i += (int)(ptr-&obuf[i]);
4325 + ptr = osf_strchr(&obuf[i], OPTDEL);
4330 + i += (int)(ptr-&obuf[i]);
4337 + ptr = osf_strchr(&obuf[i], OPTDEL);
4341 + i += (int)(ptr-&obuf[i]);
4349 + opt[*optnum].kind = IANA_opts[op].kind;
4350 + opt[*optnum].length = IANA_opts[op].length;
4351 + opt[*optnum].wc.wc = wc;
4352 + opt[*optnum].wc.val = val;
4358 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
4360 + struct list_head *ent;
4361 + struct osf_finger *f = NULL;
4367 + read_lock_bh(&osf_lock);
4368 + list_for_each(ent, &finger_list)
4370 + f = list_entry(ent, struct osf_finger, flist);
4372 + log("%s [%s]", f->genre, f->details);
4374 + count += sprintf(buf+count, "%s - %s[%s] : %s",
4375 + f->genre, f->version,
4376 + f->subtype, f->details);
4381 + //count += sprintf(buf+count, " OPT: ");
4382 + for (i=0; i<f->opt_num; ++i)
4384 + //count += sprintf(buf+count, "%d.%c%lu; ",
4385 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
4386 + loga("%d.%c%lu; ",
4387 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
4391 + count += sprintf(buf+count, "\n");
4393 + read_unlock_bh(&osf_lock);
4398 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
4402 + char obuf[MAXOPTSTRLEN];
4403 + struct osf_finger *finger;
4404 + struct list_head *ent, *n;
4406 + char *pbeg, *pend;
4408 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
4411 + write_lock_bh(&osf_lock);
4412 + list_for_each_safe(ent, n, &finger_list)
4415 + finger = list_entry(ent, struct osf_finger, flist);
4416 + list_del(&finger->flist);
4417 + finger_free(finger);
4419 + write_unlock_bh(&osf_lock);
4421 + log("Flushed %d entries.\n", i);
4428 + for (i=0; i<count && buffer[i] != '\0'; ++i)
4429 + if (buffer[i] == ':')
4432 + if (cnt != 8 || i != count)
4434 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
4439 + memset(obuf, 0, sizeof(obuf));
4441 + finger = finger_alloc();
4444 + log("Failed to allocate new fingerprint entry.\n");
4448 + pbeg = (char *)buffer;
4449 + pend = osf_strchr(pbeg, OSFPDEL);
4453 + if (pbeg[0] == 'S')
4455 + finger->wss.wc = 'S';
4456 + if (pbeg[1] == '%')
4457 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4458 + else if (pbeg[1] == '*')
4459 + finger->wss.val = 0;
4461 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4463 + else if (pbeg[0] == 'T')
4465 + finger->wss.wc = 'T';
4466 + if (pbeg[1] == '%')
4467 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4468 + else if (pbeg[1] == '*')
4469 + finger->wss.val = 0;
4471 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4473 + else if (pbeg[0] == '%')
4475 + finger->wss.wc = '%';
4476 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4478 + else if (isdigit(pbeg[0]))
4480 + finger->wss.wc = 0;
4481 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
4486 + pend = osf_strchr(pbeg, OSFPDEL);
4490 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
4493 + pend = osf_strchr(pbeg, OSFPDEL);
4497 + finger->df = simple_strtoul(pbeg, NULL, 10);
4500 + pend = osf_strchr(pbeg, OSFPDEL);
4504 + finger->ss = simple_strtoul(pbeg, NULL, 10);
4508 + pend = osf_strchr(pbeg, OSFPDEL);
4512 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
4516 + pend = osf_strchr(pbeg, OSFPDEL);
4520 + if (pbeg[0] == '@' || pbeg[0] == '*')
4521 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
4523 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
4527 + pend = osf_strchr(pbeg, OSFPDEL);
4531 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
4535 + pend = osf_strchr(pbeg, OSFPDEL);
4539 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
4543 + cnt = snprintf(finger->details,
4544 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
4547 + log("%s - %s[%s] : %s\n",
4548 + finger->genre, finger->version,
4549 + finger->subtype, finger->details);
4551 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
4554 + write_lock_bh(&osf_lock);
4555 + list_add_tail(&finger->flist, &finger_list);
4556 + write_unlock_bh(&osf_lock);
4561 +static int __init osf_init(void)
4564 + struct proc_dir_entry *p;
4566 + log("Startng OS fingerprint matching module.\n");
4568 + INIT_LIST_HEAD(&finger_list);
4570 + err = ipt_register_match(&osf_match);
4573 + log("Failed to register OS fingerprint matching module.\n");
4577 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
4580 + ipt_unregister_match(&osf_match);
4584 + p->write_proc = osf_proc_write;
4585 + p->read_proc = osf_proc_read;
4587 + nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
4590 + log("netlink_kernel_create() failed\n");
4591 + remove_proc_entry("sys/net/ipv4/osf", NULL);
4592 + ipt_unregister_match(&osf_match);
4599 +static void __exit osf_fini(void)
4601 + struct list_head *ent, *n;
4602 + struct osf_finger *f;
4604 + remove_proc_entry("sys/net/ipv4/osf", NULL);
4605 + ipt_unregister_match(&osf_match);
4606 + if (nts && nts->socket)
4607 + sock_release(nts->socket);
4609 + list_for_each_safe(ent, n, &finger_list)
4611 + f = list_entry(ent, struct osf_finger, flist);
4612 + list_del(&f->flist);
4616 + log("OS fingerprint matching module finished.\n");
4619 +module_init(osf_init);
4620 +module_exit(osf_fini);
4622 +MODULE_LICENSE("GPL");
4623 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
4624 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
4625 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_pool.c
4626 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
4627 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_pool.c 2004-04-29 09:49:29.000000000 +0200
4629 +/* Kernel module to match an IP address pool. */
4631 +#include <linux/module.h>
4632 +#include <linux/ip.h>
4633 +#include <linux/skbuff.h>
4635 +#include <linux/netfilter_ipv4/ip_tables.h>
4636 +#include <linux/netfilter_ipv4/ip_pool.h>
4637 +#include <linux/netfilter_ipv4/ipt_pool.h>
4639 +static inline int match_pool(
4644 + if (ip_pool_match(index, ntohl(addr)))
4650 + const struct sk_buff *skb,
4651 + const struct net_device *in,
4652 + const struct net_device *out,
4653 + const void *matchinfo,
4656 + u_int16_t datalen,
4659 + const struct ipt_pool_info *info = matchinfo;
4660 + const struct iphdr *iph = skb->nh.iph;
4662 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
4663 + info->flags&IPT_POOL_INV_SRC))
4666 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
4667 + info->flags&IPT_POOL_INV_DST))
4673 +static int checkentry(
4674 + const char *tablename,
4675 + const struct ipt_ip *ip,
4677 + unsigned int matchsize,
4678 + unsigned int hook_mask
4680 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
4685 +static struct ipt_match pool_match
4686 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
4688 +static int __init init(void)
4690 + return ipt_register_match(&pool_match);
4693 +static void __exit fini(void)
4695 + ipt_unregister_match(&pool_match);
4700 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_psd.c
4701 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
4702 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_psd.c 2004-04-29 09:49:40.000000000 +0200
4705 + This is a module which is used for PSD (portscan detection)
4706 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
4707 + and LOG target module.
4709 + Copyright (C) 2000,2001 astaro AG
4711 + This file is distributed under the terms of the GNU General Public
4712 + License (GPL). Copies of the GPL can be obtained from:
4713 + ftp://prep.ai.mit.edu/pub/gnu/GPL
4715 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
4716 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
4717 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
4718 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
4719 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
4722 +#include <linux/module.h>
4723 +#include <linux/skbuff.h>
4724 +#include <linux/ip.h>
4725 +#include <net/tcp.h>
4726 +#include <linux/spinlock.h>
4727 +#include <linux/netfilter_ipv4/ip_tables.h>
4728 +#include <linux/netfilter_ipv4/ipt_psd.h>
4731 +#define DEBUGP printk
4733 +#define DEBUGP(format, args...)
4736 +MODULE_LICENSE("GPL");
4737 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
4739 +#define HF_DADDR_CHANGING 0x01
4740 +#define HF_SPORT_CHANGING 0x02
4741 +#define HF_TOS_CHANGING 0x04
4742 +#define HF_TTL_CHANGING 0x08
4745 + * Information we keep per each target port
4748 + u_int16_t number; /* port number */
4749 + u_int8_t proto; /* protocol number */
4750 + u_int8_t and_flags; /* tcp ANDed flags */
4751 + u_int8_t or_flags; /* tcp ORed flags */
4755 + * Information we keep per each source address.
4758 + struct host *next; /* Next entry with the same hash */
4759 + clock_t timestamp; /* Last update time */
4760 + struct in_addr src_addr; /* Source address */
4761 + struct in_addr dest_addr; /* Destination address */
4762 + unsigned short src_port; /* Source port */
4763 + int count; /* Number of ports in the list */
4764 + int weight; /* Total weight of ports in the list */
4765 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
4766 + unsigned char tos; /* TOS */
4767 + unsigned char ttl; /* TTL */
4768 + unsigned char flags; /* HF_ flags bitmask */
4772 + * State information.
4776 + struct host list[LIST_SIZE]; /* List of source addresses */
4777 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
4778 + int index; /* Oldest entry to be replaced */
4782 + * Convert an IP address into a hash table index.
4784 +static inline int hashfunc(struct in_addr addr)
4786 + unsigned int value;
4789 + value = addr.s_addr;
4793 + } while ((value >>= HASH_LOG));
4795 + return hash & (HASH_SIZE - 1);
4799 +ipt_psd_match(const struct sk_buff *pskb,
4800 + const struct net_device *in,
4801 + const struct net_device *out,
4802 + const void *matchinfo,
4805 + u_int16_t datalen,
4808 + struct iphdr *ip_hdr;
4809 + struct tcphdr *tcp_hdr;
4810 + struct in_addr addr;
4811 + u_int16_t src_port,dest_port;
4812 + u_int8_t tcp_flags, proto;
4814 + struct host *curr, *last, **head;
4815 + int hash, index, count;
4817 + /* Parameters from userspace */
4818 + const struct ipt_psd_info *psdinfo = matchinfo;
4821 + ip_hdr = pskb->nh.iph;
4823 + /* Sanity check */
4824 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
4825 + DEBUGP("PSD: sanity check failed\n");
4829 + /* TCP or UDP ? */
4830 + proto = ip_hdr->protocol;
4832 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
4833 + DEBUGP("PSD: protocol not supported\n");
4837 + /* Get the source address, source & destination ports, and TCP flags */
4839 + addr.s_addr = ip_hdr->saddr;
4841 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
4843 + /* Yep, it´s dirty */
4844 + src_port = tcp_hdr->source;
4845 + dest_port = tcp_hdr->dest;
4847 + if (proto == IPPROTO_TCP) {
4848 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
4854 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
4855 + * them spoof us. [DHCP needs this feature - HW] */
4856 + if (!addr.s_addr) {
4857 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
4861 + /* Use jiffies here not to depend on someone setting the time while we're
4862 + * running; we need to be careful with possible return value overflows. */
4865 + spin_lock(&state.lock);
4867 + /* Do we know this source address already? */
4870 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
4872 + if (curr->src_addr.s_addr == addr.s_addr) break;
4874 + if (curr->next) last = curr;
4875 + } while ((curr = curr->next));
4879 + /* We know this address, and the entry isn't too old. Update it. */
4880 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
4881 + time_after_eq(now, curr->timestamp)) {
4883 + /* Just update the appropriate list entry if we've seen this port already */
4884 + for (index = 0; index < curr->count; index++) {
4885 + if (curr->ports[index].number == dest_port) {
4886 + curr->ports[index].proto = proto;
4887 + curr->ports[index].and_flags &= tcp_flags;
4888 + curr->ports[index].or_flags |= tcp_flags;
4889 + goto out_no_match;
4893 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
4894 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
4895 + goto out_no_match;
4897 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
4898 + curr->timestamp = now;
4900 + /* Logged this scan already? Then drop the packet. */
4901 + if (curr->weight >= psdinfo->weight_threshold)
4904 + /* Specify if destination address, source port, TOS or TTL are not fixed */
4905 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
4906 + curr->flags |= HF_DADDR_CHANGING;
4907 + if (curr->src_port != src_port)
4908 + curr->flags |= HF_SPORT_CHANGING;
4909 + if (curr->tos != ip_hdr->tos)
4910 + curr->flags |= HF_TOS_CHANGING;
4911 + if (curr->ttl != ip_hdr->ttl)
4912 + curr->flags |= HF_TTL_CHANGING;
4914 + /* Update the total weight */
4915 + curr->weight += (ntohs(dest_port) < 1024) ?
4916 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
4918 + /* Got enough destination ports to decide that this is a scan? */
4919 + /* Then log it and drop the packet. */
4920 + if (curr->weight >= psdinfo->weight_threshold)
4923 + /* Remember the new port */
4924 + if (curr->count < SCAN_MAX_COUNT) {
4925 + curr->ports[curr->count].number = dest_port;
4926 + curr->ports[curr->count].proto = proto;
4927 + curr->ports[curr->count].and_flags = tcp_flags;
4928 + curr->ports[curr->count].or_flags = tcp_flags;
4932 + goto out_no_match;
4935 + /* We know this address, but the entry is outdated. Mark it unused, and
4936 + * remove from the hash table. We'll allocate a new entry instead since
4937 + * this one might get re-used too soon. */
4938 + curr->src_addr.s_addr = 0;
4940 + last->next = last->next->next;
4942 + *head = (*head)->next;
4946 + /* We don't need an ACK from a new source address */
4947 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
4948 + goto out_no_match;
4950 + /* Got too many source addresses with the same hash value? Then remove the
4951 + * oldest one from the hash table, so that they can't take too much of our
4952 + * CPU time even with carefully chosen spoofed IP addresses. */
4953 + if (count >= HASH_MAX && last) last->next = NULL;
4955 + /* We're going to re-use the oldest list entry, so remove it from the hash
4956 + * table first (if it is really already in use, and isn't removed from the
4957 + * hash table already because of the HASH_MAX check above). */
4959 + /* First, find it */
4960 + if (state.list[state.index].src_addr.s_addr)
4961 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
4965 + if ((curr = *head))
4967 + if (curr == &state.list[state.index]) break;
4969 + } while ((curr = curr->next));
4971 + /* Then, remove it */
4974 + last->next = last->next->next;
4976 + *head = (*head)->next;
4979 + /* Get our list entry */
4980 + curr = &state.list[state.index++];
4981 + if (state.index >= LIST_SIZE) state.index = 0;
4983 + /* Link it into the hash table */
4984 + head = &state.hash[hash];
4985 + curr->next = *head;
4988 + /* And fill in the fields */
4989 + curr->timestamp = now;
4990 + curr->src_addr = addr;
4991 + curr->dest_addr.s_addr = ip_hdr->daddr;
4992 + curr->src_port = src_port;
4994 + curr->weight = (ntohs(dest_port) < 1024) ?
4995 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
4996 + curr->ports[0].number = dest_port;
4997 + curr->ports[0].proto = proto;
4998 + curr->ports[0].and_flags = tcp_flags;
4999 + curr->ports[0].or_flags = tcp_flags;
5000 + curr->tos = ip_hdr->tos;
5001 + curr->ttl = ip_hdr->ttl;
5004 + spin_unlock(&state.lock);
5008 + spin_unlock(&state.lock);
5012 +static int ipt_psd_checkentry(const char *tablename,
5013 + const struct ipt_ip *e,
5015 + unsigned int matchsize,
5016 + unsigned int hook_mask)
5018 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
5020 + /* we accept TCP only */
5021 +/* if (e->ip.proto != IPPROTO_TCP) { */
5022 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
5026 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
5027 + DEBUGP("PSD: matchsize %u != %u\n",
5029 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
5036 +static struct ipt_match ipt_psd_reg = {
5040 + ipt_psd_checkentry,
5044 +static int __init init(void)
5046 + if (ipt_register_match(&ipt_psd_reg))
5049 + memset(&state, 0, sizeof(state));
5051 + spin_lock_init(&(state.lock));
5053 + printk("netfilter PSD loaded - (c) astaro AG\n");
5057 +static void __exit fini(void)
5059 + ipt_unregister_match(&ipt_psd_reg);
5060 + printk("netfilter PSD unloaded - (c) astaro AG\n");
5065 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_quota.c
5066 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
5067 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_quota.c 2004-04-29 09:49:47.000000000 +0200
5070 + * netfilter module to enforce network quotas
5072 + * Sam Johnston <samj@samj.net>
5074 +#include <linux/module.h>
5075 +#include <linux/skbuff.h>
5076 +#include <linux/spinlock.h>
5077 +#include <linux/interrupt.h>
5079 +#include <linux/netfilter_ipv4/ip_tables.h>
5080 +#include <linux/netfilter_ipv4/ipt_quota.h>
5082 +MODULE_LICENSE("GPL");
5083 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
5085 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
5088 +match(const struct sk_buff *skb,
5089 + const struct net_device *in,
5090 + const struct net_device *out,
5091 + const void *matchinfo,
5092 + int offset, int *hotdrop)
5094 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
5095 + unsigned int datalen;
5097 + if (skb->len < sizeof(struct iphdr))
5100 + datalen = skb->len - skb->nh.iph->ihl*4;
5102 + spin_lock_bh("a_lock);
5104 + if (q->quota >= datalen) {
5105 + /* we can afford this one */
5106 + q->quota -= datalen;
5107 + spin_unlock_bh("a_lock);
5109 +#ifdef DEBUG_IPT_QUOTA
5110 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
5115 + /* so we do not allow even small packets from now on */
5118 +#ifdef DEBUG_IPT_QUOTA
5119 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
5122 + spin_unlock_bh("a_lock);
5127 +checkentry(const char *tablename,
5128 + const struct ipt_ip *ip,
5129 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
5131 + /* TODO: spinlocks? sanity checks? */
5132 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
5138 +static struct ipt_match quota_match = {
5141 + .checkentry = checkentry,
5148 + return ipt_register_match("a_match);
5154 + ipt_unregister_match("a_match);
5160 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_random.c
5161 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
5162 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_random.c 2004-04-29 09:49:54.000000000 +0200
5165 + This is a module which is used for a "random" match support.
5166 + This file is distributed under the terms of the GNU General Public
5167 + License (GPL). Copies of the GPL can be obtained from:
5168 + ftp://prep.ai.mit.edu/pub/gnu/GPL
5170 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
5173 +#include <linux/module.h>
5174 +#include <linux/skbuff.h>
5175 +#include <linux/ip.h>
5176 +#include <linux/random.h>
5177 +#include <net/tcp.h>
5178 +#include <linux/spinlock.h>
5179 +#include <linux/netfilter_ipv4/ip_tables.h>
5180 +#include <linux/netfilter_ipv4/ipt_random.h>
5182 +MODULE_LICENSE("GPL");
5185 +ipt_rand_match(const struct sk_buff *pskb,
5186 + const struct net_device *in,
5187 + const struct net_device *out,
5188 + const void *matchinfo,
5191 + u_int16_t datalen,
5194 + /* Parameters from userspace */
5195 + const struct ipt_rand_info *info = matchinfo;
5196 + u_int8_t random_number;
5198 + /* get 1 random number from the kernel random number generation routine */
5199 + get_random_bytes((void *)(&random_number), 1);
5201 + /* Do we match ? */
5202 + if (random_number <= info->average)
5209 +ipt_rand_checkentry(const char *tablename,
5210 + const struct ipt_ip *e,
5212 + unsigned int matchsize,
5213 + unsigned int hook_mask)
5215 + /* Parameters from userspace */
5216 + const struct ipt_rand_info *info = matchinfo;
5218 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
5219 + printk("ipt_random: matchsize %u != %u\n", matchsize,
5220 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
5224 + /* must be 1 <= average % <= 99 */
5225 + /* 1 x 2.55 = 2 */
5226 + /* 99 x 2.55 = 252 */
5227 + if ((info->average < 2) || (info->average > 252)) {
5228 + printk("ipt_random: invalid average %u\n", info->average);
5235 +static struct ipt_match ipt_rand_reg = {
5239 + ipt_rand_checkentry,
5243 +static int __init init(void)
5245 + if (ipt_register_match(&ipt_rand_reg))
5248 + printk("ipt_random match loaded\n");
5252 +static void __exit fini(void)
5254 + ipt_unregister_match(&ipt_rand_reg);
5255 + printk("ipt_random match unloaded\n");
5260 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_realm.c
5261 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 01:00:00.000000000 +0100
5262 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_realm.c 2004-04-29 09:50:16.000000000 +0200
5264 +/* IP tables module for matching the routing realm
5268 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
5270 + * This program is free software; you can redistribute it and/or modify
5271 + * it under the terms of the GNU General Public License version 2 as
5272 + * published by the Free Software Foundation.
5275 +#include <linux/module.h>
5276 +#include <linux/skbuff.h>
5277 +#include <linux/netdevice.h>
5278 +#include <net/route.h>
5280 +#include <linux/netfilter_ipv4/ipt_realm.h>
5281 +#include <linux/netfilter_ipv4/ip_tables.h>
5283 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
5284 +MODULE_LICENSE("GPL");
5287 +match(const struct sk_buff *skb,
5288 + const struct net_device *in,
5289 + const struct net_device *out,
5290 + const void *matchinfo,
5294 + const struct ipt_realm_info *info = matchinfo;
5295 + struct dst_entry *dst = skb->dst;
5300 + return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
5303 +static int check(const char *tablename,
5304 + const struct ipt_ip *ip,
5306 + unsigned int matchsize,
5307 + unsigned int hook_mask)
5310 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
5311 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
5312 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
5313 + "LOCAL_IN or FORWARD.\n");
5317 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
5323 +static struct ipt_match realm_match = {
5326 + .checkentry = check,
5330 +static int __init init(void)
5332 + return ipt_register_match(&realm_match);
5335 +static void __exit fini(void)
5337 + ipt_unregister_match(&realm_match);
5342 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_sctp.c
5343 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
5344 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_sctp.c 2004-04-29 09:50:22.000000000 +0200
5346 +#include <linux/module.h>
5347 +#include <linux/skbuff.h>
5348 +#include <net/ip.h>
5349 +#include <linux/sctp.h>
5351 +#include <linux/netfilter_ipv4/ip_tables.h>
5352 +#include <linux/netfilter_ipv4/ipt_sctp.h>
5355 +#define duprintf(format, args...) printk(format , ## args)
5357 +#define duprintf(format, args...)
5360 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
5361 + || (!!((invflag) & (option)) ^ (cond)))
5364 +match_flags(const struct ipt_sctp_flag_info *flag_info,
5365 + const int flag_count,
5366 + u_int8_t chunktype,
5367 + u_int8_t chunkflags)
5371 + for (i = 0; i < flag_count; i++) {
5372 + if (flag_info[i].chunktype == chunktype) {
5373 + return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
5381 +match_packet(const struct sk_buff *skb,
5382 + const u_int32_t *chunkmap,
5383 + int chunk_match_type,
5384 + const struct ipt_sctp_flag_info *flag_info,
5385 + const int flag_count,
5389 + u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
5390 + sctp_chunkhdr_t sch;
5394 + if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
5395 + SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
5398 + offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
5400 + if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
5401 + duprintf("Dropping invalid SCTP packet.\n");
5406 + duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
5407 + ++i, offset, sch.type, htons(sch.length), sch.flags);
5409 + offset += (htons(sch.length) + 3) & ~3;
5411 + duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
5413 + if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
5414 + switch (chunk_match_type) {
5415 + case SCTP_CHUNK_MATCH_ANY:
5416 + if (match_flags(flag_info, flag_count,
5417 + sch.type, sch.flags)) {
5422 + case SCTP_CHUNK_MATCH_ALL:
5423 + if (match_flags(flag_info, flag_count,
5424 + sch.type, sch.flags)) {
5425 + SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
5429 + case SCTP_CHUNK_MATCH_ONLY:
5430 + if (!match_flags(flag_info, flag_count,
5431 + sch.type, sch.flags)) {
5437 + switch (chunk_match_type) {
5438 + case SCTP_CHUNK_MATCH_ONLY:
5442 + } while (offset < skb->len);
5444 + switch (chunk_match_type) {
5445 + case SCTP_CHUNK_MATCH_ALL:
5446 + return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
5447 + case SCTP_CHUNK_MATCH_ANY:
5449 + case SCTP_CHUNK_MATCH_ONLY:
5453 + /* This will never be reached, but required to stop compiler whine */
5458 +match(const struct sk_buff *skb,
5459 + const struct net_device *in,
5460 + const struct net_device *out,
5461 + const void *matchinfo,
5465 + const struct ipt_sctp_info *info;
5466 + sctp_sctphdr_t sh;
5468 + info = (const struct ipt_sctp_info *)matchinfo;
5471 + duprintf("Dropping non-first fragment.. FIXME\n");
5475 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
5476 + duprintf("Dropping evil TCP offset=0 tinygram.\n");
5480 + duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
5482 + return SCCHECK(((ntohs(sh.source) >= info->spts[0])
5483 + && (ntohs(sh.source) <= info->spts[1])),
5484 + IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
5485 + && SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
5486 + && (ntohs(sh.dest) <= info->dpts[1])),
5487 + IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
5488 + && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
5489 + info->flag_info, info->flag_count,
5491 + IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
5495 +checkentry(const char *tablename,
5496 + const struct ipt_ip *ip,
5498 + unsigned int matchsize,
5499 + unsigned int hook_mask)
5501 + const struct ipt_sctp_info *info;
5503 + info = (const struct ipt_sctp_info *)matchinfo;
5505 + return ip->proto == IPPROTO_SCTP
5506 + && !(ip->invflags & IPT_INV_PROTO)
5507 + && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
5508 + && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
5509 + && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
5510 + && !(info->invflags & ~info->flags)
5511 + && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
5512 + (info->chunk_match_type &
5513 + (SCTP_CHUNK_MATCH_ALL
5514 + | SCTP_CHUNK_MATCH_ANY
5515 + | SCTP_CHUNK_MATCH_ONLY)));
5518 +static struct ipt_match sctp_match =
5520 + .list = { NULL, NULL},
5523 + .checkentry = &checkentry,
5528 +static int __init init(void)
5530 + return ipt_register_match(&sctp_match);
5533 +static void __exit fini(void)
5535 + ipt_unregister_match(&sctp_match);
5541 +MODULE_LICENSE("GPL");
5542 +MODULE_AUTHOR("Kiran Kumar Immidi");
5543 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
5545 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_time.c
5546 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
5547 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_time.c 2004-04-29 09:50:30.000000000 +0200
5550 + This is a module which is used for time matching
5551 + It is using some modified code from dietlibc (localtime() function)
5552 + that you can find at http://www.fefe.de/dietlibc/
5553 + This file is distributed under the terms of the GNU General Public
5554 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
5555 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
5556 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
5557 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
5558 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
5559 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
5560 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
5563 +#include <linux/module.h>
5564 +#include <linux/skbuff.h>
5565 +#include <linux/netfilter_ipv4/ip_tables.h>
5566 +#include <linux/netfilter_ipv4/ipt_time.h>
5567 +#include <linux/time.h>
5569 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5570 +MODULE_DESCRIPTION("Match arrival timestamp");
5571 +MODULE_LICENSE("GPL");
5575 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
5576 + int tm_min; /* Minutes. [0-59] */
5577 + int tm_hour; /* Hours. [0-23] */
5578 + int tm_mday; /* Day. [1-31] */
5579 + int tm_mon; /* Month. [0-11] */
5580 + int tm_year; /* Year - 1900. */
5581 + int tm_wday; /* Day of week. [0-6] */
5582 + int tm_yday; /* Days in year.[0-365] */
5583 + int tm_isdst; /* DST. [-1/0/1]*/
5585 + long int tm_gmtoff; /* we don't care, we count from GMT */
5586 + const char *tm_zone; /* we don't care, we count from GMT */
5590 +localtime(const time_t *timepr, struct tm *r);
5593 +match(const struct sk_buff *skb,
5594 + const struct net_device *in,
5595 + const struct net_device *out,
5596 + const void *matchinfo,
5599 + u_int16_t datalen,
5602 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
5603 + struct tm currenttime; /* time human readable */
5604 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
5605 + u_int16_t packet_time;
5606 + struct timeval kerneltimeval;
5607 + time_t packet_local_time;
5609 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
5610 + if (info->kerneltime)
5612 + do_gettimeofday(&kerneltimeval);
5613 + packet_local_time = kerneltimeval.tv_sec;
5616 + packet_local_time = skb->stamp.tv_sec;
5618 + /* Transform the timestamp of the packet, in a human readable form */
5619 + localtime(&packet_local_time, ¤ttime);
5621 + /* check if we match this timestamp, we start by the days... */
5622 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
5623 + return 0; /* the day doesn't match */
5625 + /* ... check the time now */
5626 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
5627 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
5630 + /* here we match ! */
5635 +checkentry(const char *tablename,
5636 + const struct ipt_ip *ip,
5638 + unsigned int matchsize,
5639 + unsigned int hook_mask)
5641 + struct ipt_time_info *info = matchinfo; /* match info for rule */
5643 + /* First, check that we are in the correct hook */
5644 + /* PRE_ROUTING, LOCAL_IN or FROWARD */
5646 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
5648 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
5651 + /* we use the kerneltime if we are in forward or output */
5652 + info->kerneltime = 1;
5653 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
5654 + /* if not, we use the skb time */
5655 + info->kerneltime = 0;
5657 + /* Check the size */
5658 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
5660 + /* Now check the coherence of the data ... */
5661 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
5662 + (info->time_stop > 1439))
5664 + printk(KERN_WARNING "ipt_time: invalid argument\n");
5671 +static struct ipt_match time_match
5672 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
5674 +static int __init init(void)
5676 + printk("ipt_time loading\n");
5677 + return ipt_register_match(&time_match);
5680 +static void __exit fini(void)
5682 + ipt_unregister_match(&time_match);
5683 + printk("ipt_time unloaded\n");
5690 +/* The part below is borowed and modified from dietlibc */
5692 +/* seconds per day */
5693 +#define SPD 24*60*60
5696 +localtime(const time_t *timepr, struct tm *r) {
5699 + extern struct timezone sys_tz;
5700 + const unsigned int __spm[12] =
5707 + (31+28+31+30+31+30),
5708 + (31+28+31+30+31+30+31),
5709 + (31+28+31+30+31+30+31+31),
5710 + (31+28+31+30+31+30+31+31+30),
5711 + (31+28+31+30+31+30+31+31+30+31),
5712 + (31+28+31+30+31+30+31+31+30+31+30),
5714 + register time_t work;
5716 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
5718 + r->tm_sec=work%60; work/=60;
5719 + r->tm_min=work%60; r->tm_hour=work/60;
5721 + r->tm_wday=(4+work)%7;
5722 + for (i=1970; ; ++i) {
5723 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
5729 + r->tm_year=i-1900;
5730 + for (i=11; i && __spm[i]>work; --i) ;
5732 + r->tm_mday=work-__spm[i]+1;
5734 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_u32.c
5735 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
5736 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_u32.c 2004-04-29 09:50:36.000000000 +0200
5738 +/* Kernel module to match u32 packet content. */
5741 +U32 tests whether quantities of up to 4 bytes extracted from a packet
5742 +have specified values. The specification of what to extract is general
5743 +enough to find data at given offsets from tcp headers or payloads.
5746 + The argument amounts to a program in a small language described below.
5747 + tests := location = value | tests && location = value
5748 + value := range | value , range
5749 + range := number | number : number
5750 + a single number, n, is interpreted the same as n:n
5751 + n:m is interpreted as the range of numbers >=n and <=m
5752 + location := number | location operator number
5753 + operator := & | << | >> | @
5755 + The operators &, <<, >>, && mean the same as in c. The = is really a set
5756 + membership operator and the value syntax describes a set. The @ operator
5757 + is what allows moving to the next header and is described further below.
5759 + *** Until I can find out how to avoid it, there are some artificial limits
5760 + on the size of the tests:
5761 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
5762 + - no more than 10 ranges (and 9 commas) per value
5763 + - no more than 10 numbers (and 9 operators) per location
5765 + To describe the meaning of location, imagine the following machine that
5766 + interprets it. There are three registers:
5767 + A is of type char*, initially the address of the IP header
5768 + B and C are unsigned 32 bit integers, initially zero
5770 + The instructions are:
5771 + number B = number;
5772 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
5773 + &number C = C&number
5774 + <<number C = C<<number
5775 + >>number C = C>>number
5776 + @number A = A+C; then do the instruction number
5777 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
5778 + Otherwise the result of the computation is the final value of C.
5780 + Whitespace is allowed but not required in the tests.
5781 + However the characters that do occur there are likely to require
5782 + shell quoting, so it's a good idea to enclose the arguments in quotes.
5785 + match IP packets with total length >= 256
5786 + The IP header contains a total length field in bytes 2-3.
5787 + --u32 "0&0xFFFF=0x100:0xFFFF"
5789 + AND that with FFFF (giving bytes 2-3),
5790 + and test whether that's in the range [0x100:0xFFFF]
5792 +Example: (more realistic, hence more complicated)
5793 + match icmp packets with icmp type 0
5794 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
5795 + --u32 "6&0xFF=1 && ...
5796 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
5797 + Next test that it's not a fragment.
5798 + (If so it might be part of such a packet but we can't always tell.)
5799 + n.b. This test is generally needed if you want to match anything
5800 + beyond the IP header.
5801 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
5802 + packet (not a fragment). Alternatively, you can allow first fragments
5803 + by only testing the last 5 bits of byte 6.
5804 + ... 4&0x3FFF=0 && ...
5805 + Last test: the first byte past the IP header (the type) is 0
5806 + This is where we have to use the @syntax. The length of the IP header
5807 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
5809 + ... 0>>22&0x3C@0>>24=0"
5810 + The first 0 means read bytes 0-3,
5811 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
5812 + the first byte, so only 22 bits is four times that plus a few more bits.
5813 + &3C then eliminates the two extra bits on the right and the first four
5814 + bits of the first byte.
5815 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
5816 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
5817 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
5818 + @ means to use this number as a new offset into the packet, and read
5819 + four bytes starting from there. This is the first 4 bytes of the icmp
5820 + payload, of which byte 0 is the icmp type. Therefore we simply shift
5821 + the value 24 to the right to throw out all but the first byte and compare
5822 + the result with 0.
5825 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
5826 + First we test that the packet is a tcp packet (similar to icmp).
5827 + --u32 "6&0xFF=6 && ...
5828 + Next, test that it's not a fragment (same as above).
5829 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
5830 + 0>>22&3C as above computes the number of bytes in the IP header.
5831 + @ makes this the new offset into the packet, which is the start of the
5832 + tcp header. The length of the tcp header (again in 32 bit words) is
5833 + the left half of byte 12 of the tcp header. The 12>>26&3C
5834 + computes this length in bytes (similar to the IP header before).
5835 + @ makes this the new offset, which is the start of the tcp payload.
5836 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
5837 + result is any of 1, 2, 5 or 8
5840 +#include <linux/module.h>
5841 +#include <linux/skbuff.h>
5843 +#include <linux/netfilter_ipv4/ipt_u32.h>
5844 +#include <linux/netfilter_ipv4/ip_tables.h>
5846 +/* #include <asm-i386/timex.h> for timing */
5848 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
5849 +MODULE_DESCRIPTION("IP tables u32 matching module");
5850 +MODULE_LICENSE("GPL");
5853 +match(const struct sk_buff *skb,
5854 + const struct net_device *in,
5855 + const struct net_device *out,
5856 + const void *matchinfo,
5859 + u_int16_t datalen,
5862 + const struct ipt_u32 *data = matchinfo;
5864 + unsigned char* origbase = (char*)skb->nh.iph;
5865 + unsigned char* base = origbase;
5866 + unsigned char* head = skb->head;
5867 + unsigned char* end = skb->end;
5869 + u_int32_t pos, val;
5870 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
5871 + cycles1 = get_cycles(); */
5873 + for (testind=0; testind < data->ntests; testind++) {
5874 + base = origbase; /* reset for each test */
5875 + pos = data->tests[testind].location[0].number;
5876 + if (base+pos+3 > end || base+pos < head)
5878 + val = (base[pos]<<24) + (base[pos+1]<<16) +
5879 + (base[pos+2]<<8) + base[pos+3];
5880 + nnums = data->tests[testind].nnums;
5881 + for (i=1; i < nnums; i++) {
5882 + u_int32_t number = data->tests[testind].location[i].number;
5883 + switch (data->tests[testind].location[i].nextop) {
5885 + val = val & number;
5887 + case IPT_U32_LEFTSH:
5888 + val = val << number;
5890 + case IPT_U32_RIGHTSH:
5891 + val = val >> number;
5894 + base = base + val;
5896 + if (base+pos+3 > end || base+pos < head)
5898 + val = (base[pos]<<24) + (base[pos+1]<<16) +
5899 + (base[pos+2]<<8) + base[pos+3];
5903 + nvals = data->tests[testind].nvalues;
5904 + for (i=0; i < nvals; i++) {
5905 + if ((data->tests[testind].value[i].min <= val) &&
5906 + (val <= data->tests[testind].value[i].max)) {
5910 + if (i >= data->tests[testind].nvalues) {
5911 + /* cycles2 = get_cycles();
5912 + printk("failed %d in %d cycles\n", testind,
5913 + cycles2-cycles1); */
5917 + /* cycles2 = get_cycles();
5918 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
5923 +checkentry(const char *tablename,
5924 + const struct ipt_ip *ip,
5926 + unsigned int matchsize,
5927 + unsigned int hook_mask)
5929 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
5934 +static struct ipt_match u32_match
5935 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
5937 +static int __init init(void)
5939 + return ipt_register_match(&u32_match);
5942 +static void __exit fini(void)
5944 + ipt_unregister_match(&u32_match);
5949 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/ip6_tunnel.c linux-2.6.6-rc3/net/ipv6/ip6_tunnel.c
5950 --- linux-2.6.6-rc3.org/net/ipv6/ip6_tunnel.c 2004-04-28 03:35:06.000000000 +0200
5951 +++ linux-2.6.6-rc3/net/ipv6/ip6_tunnel.c 2004-04-29 09:45:51.000000000 +0200
5952 @@ -715,13 +715,7 @@
5953 ipv6h->nexthdr = proto;
5954 ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
5955 ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
5956 -#ifdef CONFIG_NETFILTER
5957 - nf_conntrack_put(skb->nfct);
5959 -#ifdef CONFIG_NETFILTER_DEBUG
5960 - skb->nf_debug = 0;
5965 err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
5966 skb->dst->dev, dst_output);
5967 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig
5968 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig 2004-04-28 03:36:33.000000000 +0200
5969 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig 2004-04-29 09:49:54.000000000 +0200
5970 @@ -230,5 +230,30 @@
5971 <file:Documentation/modules.txt>. If unsure, say `N'.
5974 +config IP6_NF_TARGET_HL
5975 + tristate 'HL target support'
5976 + depends on IP6_NF_MANGLE
5979 +config IP6_NF_TARGET_REJECT
5980 + tristate 'REJECT target support'
5981 + depends on IP6_NF_FILTER
5984 +config IP6_NF_MATCH_FUZZY
5985 + tristate 'Fuzzy match support'
5986 + depends on IP6_NF_FILTER
5989 +config IP6_NF_MATCH_NTH
5990 + tristate 'Nth match support'
5991 + depends on IP6_NF_IPTABLES
5994 +config IP6_NF_MATCH_RANDOM
5995 + tristate 'Random match support'
5996 + depends on IP6_NF_IPTABLES
6001 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc3/net/ipv6/netfilter/Makefile
6002 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile 2004-04-28 03:36:01.000000000 +0200
6003 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Makefile 2004-04-29 09:49:54.000000000 +0200
6005 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
6006 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
6007 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
6008 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
6009 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
6010 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
6011 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
6013 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
6014 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
6015 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
6016 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
6017 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
6018 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
6020 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
6022 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
6023 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
6024 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
6025 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
6026 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_HL.c
6027 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
6028 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_HL.c 2004-04-29 09:46:34.000000000 +0200
6031 + * Hop Limit modification target for ip6tables
6032 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
6033 + * Based on HW's TTL module
6035 + * This software is distributed under the terms of GNU GPL
6038 +#include <linux/module.h>
6039 +#include <linux/skbuff.h>
6040 +#include <linux/ip.h>
6042 +#include <linux/netfilter_ipv6/ip6_tables.h>
6043 +#include <linux/netfilter_ipv6/ip6t_HL.h>
6045 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
6046 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
6047 +MODULE_LICENSE("GPL");
6049 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
6050 + const struct net_device *in, const struct net_device *out,
6051 + const void *targinfo, void *userinfo)
6053 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
6054 + const struct ip6t_HL_info *info = targinfo;
6055 + u_int16_t diffs[2];
6058 + switch (info->mode) {
6060 + new_hl = info->hop_limit;
6063 + new_hl = ip6h->hop_limit + info->hop_limit;
6068 + new_hl = ip6h->hop_limit + info->hop_limit;
6073 + new_hl = ip6h->hop_limit;
6077 + if (new_hl != ip6h->hop_limit) {
6078 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
6079 + ip6h->hop_limit = new_hl;
6080 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
6083 + return IP6T_CONTINUE;
6086 +static int ip6t_hl_checkentry(const char *tablename,
6087 + const struct ip6t_entry *e,
6089 + unsigned int targinfosize,
6090 + unsigned int hook_mask)
6092 + struct ip6t_HL_info *info = targinfo;
6094 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
6095 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
6097 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
6101 + if (strcmp(tablename, "mangle")) {
6102 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6106 + if (info->mode > IP6T_HL_MAXMODE) {
6107 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
6112 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
6113 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
6120 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
6121 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
6123 +static int __init init(void)
6125 + return ip6t_register_target(&ip6t_HL);
6128 +static void __exit fini(void)
6130 + ip6t_unregister_target(&ip6t_HL);
6135 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_REJECT.c
6136 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
6137 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_REJECT.c 2004-04-29 09:47:26.000000000 +0200
6140 + * IP6 tables REJECT target module
6141 + * Linux INET6 implementation
6143 + * Copyright (C)2003 USAGI/WIDE Project
6146 + * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
6148 + * Based on net/ipv4/netfilter/ipt_REJECT.c
6150 + * This program is free software; you can redistribute it and/or
6151 + * modify it under the terms of the GNU General Public License
6152 + * as published by the Free Software Foundation; either version
6153 + * 2 of the License, or (at your option) any later version.
6156 +#include <linux/config.h>
6157 +#include <linux/module.h>
6158 +#include <linux/skbuff.h>
6159 +#include <linux/icmpv6.h>
6160 +#include <net/ipv6.h>
6161 +#include <net/tcp.h>
6162 +#include <net/icmp.h>
6163 +#include <net/ip6_fib.h>
6164 +#include <net/ip6_route.h>
6165 +#include <net/flow.h>
6166 +#include <linux/netfilter_ipv6/ip6_tables.h>
6167 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
6169 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
6170 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
6171 +MODULE_LICENSE("GPL");
6174 +#define DEBUGP printk
6176 +#define DEBUGP(format, args...)
6180 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
6182 + void (*attach)(struct sk_buff *, struct nf_ct_info *);
6183 + if (nfct && (attach = ip6_ct_attach) != NULL) {
6185 + attach(new_skb, nfct);
6190 +static int maybe_reroute(struct sk_buff *skb)
6192 + if (skb->nfcache & NFC_ALTERED){
6193 + if (ip6_route_me_harder(skb) != 0){
6199 + return dst_output(skb);
6202 +/* Send RST reply */
6203 +static void send_reset(struct sk_buff *oldskb)
6205 + struct sk_buff *nskb;
6206 + struct tcphdr otcph, *tcph;
6207 + unsigned int otcplen, tcphoff, hh_len;
6209 + struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
6210 + struct dst_entry *dst = NULL;
6213 + proto = oip6h->nexthdr;
6216 + if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
6217 + (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
6218 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6222 + tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
6223 + &proto, oldskb->len - ((u8*)(oip6h+1)
6226 + if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
6227 + DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
6231 + otcplen = oldskb->len - tcphoff;
6233 + /* IP header checks: fragment, too short. */
6234 + if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
6235 + DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
6240 + if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
6241 + if (net_ratelimit())
6242 + printk("ip6t_REJECT: Can't copy tcp header\n");
6246 + /* No RST for RST. */
6248 + DEBUGP("ip6t_REJECT: RST is set\n");
6252 + /* Check checksum. */
6253 + if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
6254 + skb_checksum(oldskb, tcphoff, otcplen, 0))) {
6255 + DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
6259 + memset(&fl, 0, sizeof(fl));
6260 + fl.proto = IPPROTO_TCP;
6261 + ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
6262 + ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
6263 + fl.fl_ip_sport = otcph.dest;
6264 + fl.fl_ip_dport = otcph.source;
6265 + err = ip6_dst_lookup(NULL, &dst, &fl);
6267 + if (net_ratelimit())
6268 + printk("ip6t_REJECT: can't find dst. err = %d\n", err);
6272 + hh_len = (dst->dev->hard_header_len + 15)&~15;
6273 + nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
6274 + + sizeof(struct tcphdr) + dst->trailer_len,
6278 + if (net_ratelimit())
6279 + printk("ip6t_REJECT: Can't alloc skb\n");
6287 + skb_reserve(nskb, hh_len + dst->header_len);
6289 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6290 + skb_put(nskb, sizeof(struct ipv6hdr));
6291 + ip6h->version = 6;
6292 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6293 + ip6h->nexthdr = IPPROTO_TCP;
6294 + ip6h->payload_len = htons(sizeof(struct tcphdr));
6295 + ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
6296 + ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
6298 + tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
6299 + /* Truncate to length (no data) */
6300 + tcph->doff = sizeof(struct tcphdr)/4;
6301 + tcph->source = otcph.dest;
6302 + tcph->dest = otcph.source;
6306 + tcph->seq = otcph.ack_seq;
6307 + tcph->ack_seq = 0;
6310 + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
6311 + + otcplen - (otcph.doff<<2));
6316 + ((u_int8_t *)tcph)[13] = 0;
6318 + tcph->ack = needs_ack;
6320 + tcph->urg_ptr = 0;
6323 + /* Adjust TCP checksum */
6324 + tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
6325 + &nskb->nh.ipv6h->daddr,
6326 + sizeof(struct tcphdr), IPPROTO_TCP,
6327 + csum_partial((char *)tcph,
6328 + sizeof(struct tcphdr), 0));
6331 + connection_attach(nskb, oldskb->nfct);
6334 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6340 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
6342 + struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
6343 + struct icmp6hdr *icmp6h;
6344 + struct dst_entry *dst = NULL;
6345 + struct rt6_info *rt;
6348 + unsigned int len, datalen, hh_len;
6349 + int saddr_type, daddr_type;
6350 + unsigned int ptr, ip6off;
6353 + struct sk_buff *nskb;
6356 + saddr_type = ipv6_addr_type(&hdr->saddr);
6357 + daddr_type = ipv6_addr_type(&hdr->daddr);
6359 + if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
6360 + (!(daddr_type & IPV6_ADDR_UNICAST))) {
6361 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6365 + ip6off = skb_in->nh.raw - skb_in->data;
6366 + proto = hdr->nexthdr;
6367 + ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
6368 + skb_in->len - ip6off);
6370 + if ((ptr < 0) || (ptr > skb_in->len)) {
6371 + ptr = ip6off + sizeof(struct ipv6hdr);
6372 + proto = hdr->nexthdr;
6373 + } else if (proto == IPPROTO_ICMPV6) {
6376 + if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
6377 + icmp6_type), &type, 1)) {
6378 + DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
6382 + if (!(type & ICMPV6_INFOMSG_MASK)) {
6383 + DEBUGP("ip6t_REJECT: no reply to icmp error\n");
6386 + } else if (proto == IPPROTO_UDP) {
6387 + int plen = skb_in->len - (ptr - ip6off);
6390 + if (plen < sizeof(struct udphdr)) {
6391 + DEBUGP("ip6t_REJECT: too short\n");
6395 + if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
6397 + if (net_ratelimit())
6398 + printk("ip6t_REJECT: can't get copy from skb");
6403 + csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
6405 + skb_checksum(skb_in, ptr, plen, 0))) {
6406 + DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
6411 + memset(&fl, 0, sizeof(fl));
6412 + fl.proto = IPPROTO_ICMPV6;
6413 + ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
6414 + ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
6415 + fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
6416 + fl.fl_icmp_code = code;
6418 + if (ip6_dst_lookup(NULL, &dst, &fl)) {
6422 + rt = (struct rt6_info *)dst;
6425 + if (rt->rt6i_dst.plen < 128)
6426 + tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
6428 + if (!xrlim_allow(dst, tmo)) {
6429 + if (net_ratelimit())
6430 + printk("ip6t_REJECT: rate limitted\n");
6431 + goto dst_release_out;
6434 + len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
6436 + if (len > dst_pmtu(dst))
6437 + len = dst_pmtu(dst);
6438 + if (len > IPV6_MIN_MTU)
6439 + len = IPV6_MIN_MTU;
6441 + datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
6442 + hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
6444 + nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
6448 + if (net_ratelimit())
6449 + printk("ip6t_REJECT: can't alloc skb\n");
6450 + goto dst_release_out;
6453 + nskb->priority = 0;
6457 + skb_reserve(nskb, hh_len + dst->header_len);
6459 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6460 + skb_put(nskb, sizeof(struct ipv6hdr));
6461 + ip6h->version = 6;
6462 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6463 + ip6h->nexthdr = IPPROTO_ICMPV6;
6464 + ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
6465 + ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
6466 + ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
6468 + icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
6469 + icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
6470 + icmp6h->icmp6_code = code;
6471 + icmp6h->icmp6_cksum = 0;
6473 + data = skb_put(nskb, datalen);
6475 + csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
6476 + csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
6477 + icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
6478 + datalen + sizeof(struct icmp6hdr),
6479 + IPPROTO_ICMPV6, csum);
6482 + connection_attach(nskb, skb_in->nfct);
6484 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6491 +static unsigned int reject6_target(struct sk_buff **pskb,
6492 + unsigned int hooknum,
6493 + const struct net_device *in,
6494 + const struct net_device *out,
6495 + const void *targinfo,
6498 + const struct ip6t_reject_info *reject = targinfo;
6500 + DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
6501 + /* WARNING: This code causes reentry within ip6tables.
6502 + This means that the ip6tables jump stack is now crap. We
6503 + must return an absolute verdict. --RR */
6504 + switch (reject->with) {
6505 + case IP6T_ICMP6_NO_ROUTE:
6506 + send_unreach(*pskb, ICMPV6_NOROUTE);
6508 + case IP6T_ICMP6_ADM_PROHIBITED:
6509 + send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
6511 + case IP6T_ICMP6_NOT_NEIGHBOUR:
6512 + send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
6514 + case IP6T_ICMP6_ADDR_UNREACH:
6515 + send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
6517 + case IP6T_ICMP6_PORT_UNREACH:
6518 + send_unreach(*pskb, ICMPV6_PORT_UNREACH);
6520 + case IP6T_ICMP6_ECHOREPLY:
6523 + case IP6T_TCP_RESET:
6524 + send_reset(*pskb);
6527 + if (net_ratelimit())
6528 + printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
6535 +static int check(const char *tablename,
6536 + const struct ip6t_entry *e,
6538 + unsigned int targinfosize,
6539 + unsigned int hook_mask)
6541 + const struct ip6t_reject_info *rejinfo = targinfo;
6543 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
6544 + DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
6548 + /* Only allow these for packet filtering. */
6549 + if (strcmp(tablename, "filter") != 0) {
6550 + DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
6554 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
6555 + | (1 << NF_IP6_FORWARD)
6556 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
6557 + DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
6561 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
6562 + printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
6564 + } else if (rejinfo->with == IP6T_TCP_RESET) {
6565 + /* Must specify that it's a TCP packet */
6566 + if (e->ipv6.proto != IPPROTO_TCP
6567 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
6568 + DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
6576 +static struct ip6t_target ip6t_reject_reg = {
6578 + .target = reject6_target,
6579 + .checkentry = check,
6583 +static int __init init(void)
6585 + if (ip6t_register_target(&ip6t_reject_reg))
6590 +static void __exit fini(void)
6592 + ip6t_unregister_target(&ip6t_reject_reg);
6597 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_fuzzy.c
6598 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
6599 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_fuzzy.c 2004-04-29 09:48:15.000000000 +0200
6602 + * This module implements a simple TSK FLC
6603 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
6604 + * to limit , in an adaptive and flexible way , the packet rate crossing
6605 + * a given stream . It serves as an initial and very simple (but effective)
6606 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
6607 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
6608 + * into our code in a precise , adaptive and efficient manner.
6609 + * The goal is very similar to that of "limit" match , but using techniques of
6610 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
6611 + * avoiding over and undershoots - and stuff like that .
6614 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
6615 + * 2002-08-17 : Changed to eliminate floating point operations .
6616 + * 2002-08-23 : Coding style changes .
6617 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
6620 +#include <linux/module.h>
6621 +#include <linux/skbuff.h>
6622 +#include <linux/ipv6.h>
6623 +#include <linux/random.h>
6624 +#include <net/tcp.h>
6625 +#include <linux/spinlock.h>
6626 +#include <linux/netfilter_ipv6/ip6_tables.h>
6627 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
6630 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
6631 + Expressed in percentage
6634 +#define PAR_LOW 1/100
6637 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
6639 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
6640 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
6641 +MODULE_LICENSE("GPL");
6643 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6645 + if (tx >= maxi) return 100;
6647 + if (tx <= mini) return 0;
6649 + return ((100 * (tx-mini)) / (maxi-mini));
6652 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6654 + if (tx <= mini) return 100;
6656 + if (tx >= maxi) return 0;
6658 + return ((100 * (maxi - tx)) / (maxi - mini));
6663 +ip6t_fuzzy_match(const struct sk_buff *pskb,
6664 + const struct net_device *in,
6665 + const struct net_device *out,
6666 + const void *matchinfo,
6669 + u_int16_t datalen,
6672 + /* From userspace */
6674 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
6676 + u_int8_t random_number;
6677 + unsigned long amount;
6678 + u_int8_t howhigh, howlow;
6681 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
6683 + info->bytes_total += pskb->len;
6684 + info->packets_total++;
6686 + info->present_time = jiffies;
6688 + if (info->present_time >= info->previous_time)
6689 + amount = info->present_time - info->previous_time;
6691 + /* There was a transition : I choose to re-sample
6692 + and keep the old acceptance rate...
6696 + info->previous_time = info->present_time;
6697 + info->bytes_total = info->packets_total = 0;
6700 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
6702 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
6705 + info->previous_time = info->present_time;
6706 + info->bytes_total = info->packets_total = 0;
6708 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
6709 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
6711 + info->acceptance_rate = (u_int8_t) \
6712 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
6714 + /* In fact, the above defuzzification would require a denominator
6715 + * proportional to (howhigh+howlow) but, in this particular case,
6716 + * that expression is constant.
6717 + * An imediate consequence is that it is not necessary to call
6718 + * both mf_high and mf_low - but to keep things understandable,
6724 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
6727 + if (info->acceptance_rate < 100)
6729 + get_random_bytes((void *)(&random_number), 1);
6731 + /* If within the acceptance , it can pass => don't match */
6732 + if (random_number <= (255 * info->acceptance_rate) / 100)
6735 + return 1; /* It can't pass (It matches) */
6738 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
6743 +ip6t_fuzzy_checkentry(const char *tablename,
6744 + const struct ip6t_ip6 *ip,
6746 + unsigned int matchsize,
6747 + unsigned int hook_mask)
6750 + const struct ip6t_fuzzy_info *info = matchinfo;
6752 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
6753 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
6754 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
6758 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
6759 + || (info->minimum_rate >= info->maximum_rate)) {
6760 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
6767 +static struct ip6t_match ip6t_fuzzy_reg = {
6771 + ip6t_fuzzy_checkentry,
6775 +static int __init init(void)
6777 + if (ip6t_register_match(&ip6t_fuzzy_reg))
6783 +static void __exit fini(void)
6785 + ip6t_unregister_match(&ip6t_fuzzy_reg);
6790 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_nth.c
6791 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
6792 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_nth.c 2004-04-29 09:49:13.000000000 +0200
6795 + This is a module which is used for match support for every Nth packet
6796 + This file is distributed under the terms of the GNU General Public
6797 + License (GPL). Copies of the GPL can be obtained from:
6798 + ftp://prep.ai.mit.edu/pub/gnu/GPL
6800 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
6801 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
6802 + * added support for multiple counters
6803 + * added support for matching on individual packets
6804 + in the counter cycle
6805 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
6809 +#include <linux/module.h>
6810 +#include <linux/skbuff.h>
6811 +#include <linux/ip.h>
6812 +#include <net/tcp.h>
6813 +#include <linux/spinlock.h>
6814 +#include <linux/netfilter_ipv6/ip6_tables.h>
6815 +#include <linux/netfilter_ipv6/ip6t_nth.h>
6817 +MODULE_LICENSE("GPL");
6820 + * State information.
6827 +static struct state states[IP6T_NTH_NUM_COUNTERS];
6830 +ip6t_nth_match(const struct sk_buff *pskb,
6831 + const struct net_device *in,
6832 + const struct net_device *out,
6833 + const void *matchinfo,
6836 + u_int16_t datalen,
6839 + /* Parameters from userspace */
6840 + const struct ip6t_nth_info *info = matchinfo;
6841 + unsigned counter = info->counter;
6842 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
6844 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
6848 + spin_lock(&states[counter].lock);
6850 + /* Are we matching every nth packet?*/
6851 + if (info->packet == 0xFF)
6853 + /* We're matching every nth packet and only every nth packet*/
6854 + /* Do we match or invert match? */
6855 + if (info->not == 0)
6857 + if (states[counter].number == 0)
6859 + ++states[counter].number;
6862 + if (states[counter].number >= info->every)
6863 + states[counter].number = 0; /* reset the counter */
6865 + ++states[counter].number;
6870 + if (states[counter].number == 0)
6872 + ++states[counter].number;
6875 + if (states[counter].number >= info->every)
6876 + states[counter].number = 0;
6878 + ++states[counter].number;
6884 + /* We're using the --packet, so there must be a rule for every value */
6885 + if (states[counter].number == info->packet)
6887 + /* only increment the counter when a match happens */
6888 + if (states[counter].number >= info->every)
6889 + states[counter].number = 0; /* reset the counter */
6891 + ++states[counter].number;
6900 + spin_unlock(&states[counter].lock);
6904 + spin_unlock(&states[counter].lock);
6909 +ip6t_nth_checkentry(const char *tablename,
6910 + const struct ip6t_ip6 *e,
6912 + unsigned int matchsize,
6913 + unsigned int hook_mask)
6915 + /* Parameters from userspace */
6916 + const struct ip6t_nth_info *info = matchinfo;
6917 + unsigned counter = info->counter;
6918 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
6920 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
6924 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
6925 + printk("nth: matchsize %u != %u\n", matchsize,
6926 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
6930 + states[counter].number = info->startat;
6935 +static struct ip6t_match ip6t_nth_reg = {
6939 + ip6t_nth_checkentry,
6943 +static int __init init(void)
6946 + memset(&states, 0, sizeof(states));
6947 + if (ip6t_register_match(&ip6t_nth_reg))
6950 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
6952 + spin_lock_init(&(states[counter].lock));
6955 + printk("ip6t_nth match loaded\n");
6959 +static void __exit fini(void)
6961 + ip6t_unregister_match(&ip6t_nth_reg);
6962 + printk("ip6t_nth match unloaded\n");
6967 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_random.c
6968 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
6969 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_random.c 2004-04-29 09:49:54.000000000 +0200
6972 + This is a module which is used for a "random" match support.
6973 + This file is distributed under the terms of the GNU General Public
6974 + License (GPL). Copies of the GPL can be obtained from:
6975 + ftp://prep.ai.mit.edu/pub/gnu/GPL
6977 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
6978 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
6981 +#include <linux/module.h>
6982 +#include <linux/skbuff.h>
6983 +#include <linux/ip.h>
6984 +#include <linux/random.h>
6985 +#include <net/tcp.h>
6986 +#include <linux/spinlock.h>
6987 +#include <linux/netfilter_ipv6/ip6_tables.h>
6988 +#include <linux/netfilter_ipv6/ip6t_random.h>
6990 +MODULE_LICENSE("GPL");
6993 +ip6t_rand_match(const struct sk_buff *pskb,
6994 + const struct net_device *in,
6995 + const struct net_device *out,
6996 + const void *matchinfo,
6999 + u_int16_t datalen,
7002 + /* Parameters from userspace */
7003 + const struct ip6t_rand_info *info = matchinfo;
7004 + u_int8_t random_number;
7006 + /* get 1 random number from the kernel random number generation routine */
7007 + get_random_bytes((void *)(&random_number), 1);
7009 + /* Do we match ? */
7010 + if (random_number <= info->average)
7017 +ip6t_rand_checkentry(const char *tablename,
7018 + const struct ip6t_ip6 *e,
7020 + unsigned int matchsize,
7021 + unsigned int hook_mask)
7023 + /* Parameters from userspace */
7024 + const struct ip6t_rand_info *info = matchinfo;
7026 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
7027 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
7028 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
7032 + /* must be 1 <= average % <= 99 */
7033 + /* 1 x 2.55 = 2 */
7034 + /* 99 x 2.55 = 252 */
7035 + if ((info->average < 2) || (info->average > 252)) {
7036 + printk("ip6t_random: invalid average %u\n", info->average);
7043 +static struct ip6t_match ip6t_rand_reg = {
7047 + ip6t_rand_checkentry,
7051 +static int __init init(void)
7053 + if (ip6t_register_match(&ip6t_rand_reg))
7056 + printk("ip6t_random match loaded\n");
7060 +static void __exit fini(void)
7062 + ip6t_unregister_match(&ip6t_rand_reg);
7063 + printk("ip6t_random match unloaded\n");
7068 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/sit.c linux-2.6.6-rc3/net/ipv6/sit.c
7069 --- linux-2.6.6-rc3.org/net/ipv6/sit.c 2004-04-28 03:36:36.000000000 +0200
7070 +++ linux-2.6.6-rc3/net/ipv6/sit.c 2004-04-29 09:45:51.000000000 +0200
7071 @@ -388,13 +388,7 @@
7072 skb->dev = tunnel->dev;
7073 dst_release(skb->dst);
7075 -#ifdef CONFIG_NETFILTER
7076 - nf_conntrack_put(skb->nfct);
7078 -#ifdef CONFIG_NETFILTER_DEBUG
7079 - skb->nf_debug = 0;
7083 ipip6_ecn_decapsulate(iph, skb);
7085 read_unlock(&ipip6_lock);
7086 @@ -580,13 +574,7 @@
7087 if ((iph->ttl = tiph->ttl) == 0)
7088 iph->ttl = iph6->hop_limit;
7090 -#ifdef CONFIG_NETFILTER
7091 - nf_conntrack_put(skb->nfct);
7093 -#ifdef CONFIG_NETFILTER_DEBUG
7094 - skb->nf_debug = 0;
7100 tunnel->recursion--;