3 updates/01_linux-2.6.4.patch
4 updates/02_iptables-1.2.11-multi.patch
5 updates/02_linux-2.6.5.patch
6 updates/03_linux-2.6.6.patch
7 updates/04_linux-2.6.6-helper_reassign.patch
8 updates/05_linux-2.6.6-orphaned_expect.patch
9 updates/06_linux-2.6.6-skb_len_check.patch
10 updates/07_linux-2.6.7.patch
11 updates/08_linux-2.6.7-user_attr.patch
12 updates/09_linux-2.6.7-ipt_LOG_doff_fix.patch
13 updates/10_linux-2.6.7-tcp_opt.patch
14 pending/CLASSIFY_more-hooks amanda_offset-fix
15 pending/conntrack-acct
16 pending/conntrack-cacheline-opt
17 pending/conntrack-seqfile
18 pending/conntrack_error-api
19 pending/early-drop-norandom
20 pending/expect-evict-order
21 pending/expect-slab-cache
22 pending/init_conntrack-optimize
23 pending/ip_nat_helper_static
24 pending/ip_queue_nonlinear_skbs
25 pending/ipt_helper-invert-fix
26 pending/mangle-reroute
29 pending/proc_net_conntrack-permissions
30 pending/proc-no-internal-targets
33 base/IPV4OPTSSTRIP + require fix: s/<linux/ip.h>/<net/ip.h>/ in net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
55 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h
56 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-09-07 12:07:45.184838544 +0200
57 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack.h 2004-09-07 12:32:45.881697944 +0200
59 union ip_conntrack_expect_help help;
62 +struct ip_conntrack_counter
68 struct ip_conntrack_helper;
72 plus 1 for any connection(s) we are `master' for */
73 struct nf_conntrack ct_general;
75 - /* These are my tuples; original and reply */
76 - struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
78 /* Have we seen traffic both ways yet? (bitset) */
81 /* Timer function; drops refcnt when it goes off. */
82 struct timer_list timeout;
84 +#ifdef CONFIG_IP_NF_CT_ACCT
85 + /* Accounting Information (same cache line as other written members) */
86 + struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
89 /* If we're expecting another related connection, this will be
90 in expected linked list */
91 struct list_head sibling_list;
94 #endif /* CONFIG_IP_NF_NAT_NEEDED */
96 + /* Traversed often, so hopefully in different cacheline to top */
97 + /* These are my tuples; original and reply */
98 + struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
101 /* get master conntrack via master expectation */
103 const struct ip_conntrack_tuple *orig);
105 /* Refresh conntrack for this many jiffies */
106 -extern void ip_ct_refresh(struct ip_conntrack *ct,
107 - unsigned long extra_jiffies);
108 +extern void ip_ct_refresh_acct(struct ip_conntrack *ct,
109 + enum ip_conntrack_info ctinfo,
110 + const struct sk_buff *skb,
111 + unsigned long extra_jiffies);
113 /* These are for NAT. Icky. */
114 /* Call me when a conntrack is destroyed. */
115 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h
116 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-09-07 12:07:45.184838544 +0200
117 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_core.h 2004-09-07 12:32:47.916388624 +0200
119 extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol);
120 extern struct list_head protocol_list;
122 -/* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */
123 -extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
124 - enum ip_conntrack_info *ctinfo,
125 - unsigned int hooknum);
126 -extern int get_tuple(const struct iphdr *iph,
127 - const struct sk_buff *skb,
128 - unsigned int dataoff,
129 - struct ip_conntrack_tuple *tuple,
130 - const struct ip_conntrack_protocol *protocol);
132 +ip_ct_get_tuple(const struct iphdr *iph,
133 + const struct sk_buff *skb,
134 + unsigned int dataoff,
135 + struct ip_conntrack_tuple *tuple,
136 + const struct ip_conntrack_protocol *protocol);
139 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
140 + const struct ip_conntrack_tuple *orig,
141 + const struct ip_conntrack_protocol *protocol);
143 /* Find a connection corresponding to a tuple. */
144 struct ip_conntrack_tuple_hash *
145 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
146 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-09-07 12:07:45.184838544 +0200
147 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 2004-09-07 12:32:47.917388472 +0200
149 #define _IP_CONNTRACK_PROTOCOL_H
150 #include <linux/netfilter_ipv4/ip_conntrack.h>
152 +/* length of buffer to which print_tuple/print_conntrack members are
155 +#define IP_CT_PRINT_BUFLEN 100
157 struct ip_conntrack_protocol
161 int (*exp_matches_pkt)(struct ip_conntrack_expect *exp,
162 const struct sk_buff *skb);
164 + int (*error)(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
165 + unsigned int hooknum);
167 /* Module (if any) which this is connected to. */
171 extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
172 extern struct ip_conntrack_protocol ip_conntrack_protocol_icmp;
173 extern int ip_conntrack_protocol_tcp_init(void);
175 +/* Log invalid packets */
176 +extern unsigned int ip_ct_log_invalid;
178 +#ifdef DEBUG_INVALID_PACKETS
179 +#define LOG_INVALID(proto) \
180 + (ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW)
182 +#define LOG_INVALID(proto) \
183 + ((ip_ct_log_invalid == (proto) || ip_ct_log_invalid == IPPROTO_RAW) \
184 + && net_ratelimit())
187 #endif /*_IP_CONNTRACK_PROTOCOL_H*/
188 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.6.7/include/linux/netfilter_ipv4/ip_nat_helper.h
189 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_nat_helper.h 2004-09-07 12:07:45.156842800 +0200
190 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_nat_helper.h 2004-09-07 12:32:56.182132040 +0200
192 struct ip_nat_info *info);
195 -extern struct list_head helpers;
197 extern int ip_nat_helper_register(struct ip_nat_helper *me);
198 extern void ip_nat_helper_unregister(struct ip_nat_helper *me);
200 +extern struct ip_nat_helper *
201 +ip_nat_find_helper(const struct ip_conntrack_tuple *tuple);
203 /* These return true or false. */
204 extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
205 struct ip_conntrack *ct,
206 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.7/include/linux/netfilter_ipv4/ip_tables.h
207 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_tables.h 2004-09-07 12:07:45.184838544 +0200
208 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_tables.h 2004-09-07 12:32:37.051040408 +0200
210 * Main firewall chains definitions and global var's definitions.
213 +extern struct semaphore ipt_mutex;
214 static DECLARE_MUTEX(ipt_mutex);
216 #include <linux/init.h>
217 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h
218 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
219 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h 2004-09-07 12:33:09.040177320 +0200
221 +/* TTL modification module for IP tables
222 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
233 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
235 +struct ipt_TTL_info {
242 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_connlimit.h
243 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
244 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-09-07 12:33:10.090017720 +0200
246 +#ifndef _IPT_CONNLIMIT_H
247 +#define _IPT_CONNLIMIT_H
249 +struct ipt_connlimit_data;
251 +struct ipt_connlimit_info {
255 + struct ipt_connlimit_data *data;
257 +#endif /* _IPT_CONNLIMIT_H */
258 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h
259 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
260 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-09-07 12:33:11.098864352 +0200
262 +#ifndef _IPT_DSTLIMIT_H
263 +#define _IPT_DSTLIMIT_H
265 +/* timings are in milliseconds. */
266 +#define IPT_DSTLIMIT_SCALE 10000
267 +/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
268 + seconds, or one every 59 hours. */
270 +/* details of this structure hidden by the implementation */
271 +struct ipt_dstlimit_htable;
273 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
274 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
275 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
277 +struct dstlimit_cfg {
278 + u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
279 + u_int32_t avg; /* Average secs between packets * scale */
280 + u_int32_t burst; /* Period multiplier for upper limit. */
282 + /* user specified */
283 + u_int32_t size; /* how many buckets */
284 + u_int32_t max; /* max number of entries */
285 + u_int32_t gc_interval; /* gc interval */
286 + u_int32_t expire; /* when do entries expire? */
289 +struct ipt_dstlimit_info {
290 + char name [IFNAMSIZ]; /* name */
291 + struct dstlimit_cfg cfg;
292 + struct ipt_dstlimit_htable *hinfo;
294 + /* Used internally by the kernel */
297 + struct ipt_dstlimit_info *master;
300 +#endif /*_IPT_DSTLIMIT_H*/
301 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h
302 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
303 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-09-07 12:33:12.079715240 +0200
305 +#ifndef _IPT_FUZZY_H
306 +#define _IPT_FUZZY_H
308 +#include <linux/param.h>
309 +#include <linux/types.h>
311 +#define MAXFUZZYRATE 10000000
312 +#define MINFUZZYRATE 3
314 +struct ipt_fuzzy_info {
315 + u_int32_t minimum_rate;
316 + u_int32_t maximum_rate;
317 + u_int32_t packets_total;
318 + u_int32_t bytes_total;
319 + u_int32_t previous_time;
320 + u_int32_t present_time;
321 + u_int32_t mean_rate;
322 + u_int8_t acceptance_rate;
325 +#endif /*_IPT_FUZZY_H*/
326 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h
327 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
328 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-09-07 12:33:15.333220632 +0200
330 +#ifndef __ipt_ipv4options_h_included__
331 +#define __ipt_ipv4options_h_included__
333 +#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
334 +#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
335 +#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
336 +#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
337 +#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
338 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
339 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
340 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
341 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
342 +#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
343 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
345 +struct ipt_ipv4options_info {
350 +#endif /* __ipt_ipv4options_h_included__ */
351 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h
352 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
353 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h 2004-09-07 12:33:16.383061032 +0200
355 +#ifndef _IPT_MPORT_H
356 +#define _IPT_MPORT_H
357 +#include <linux/netfilter_ipv4/ip_tables.h>
359 +#define IPT_MPORT_SOURCE (1<<0)
360 +#define IPT_MPORT_DESTINATION (1<<1)
361 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
363 +#define IPT_MULTI_PORTS 15
365 +/* Must fit inside union ipt_matchinfo: 32 bytes */
366 +/* every entry in ports[] except for the last one has one bit in pflags
367 + * associated with it. If this bit is set, the port is the first port of
368 + * a portrange, with the next entry being the last.
369 + * End of list is marked with pflags bit set and port=65535.
370 + * If 14 ports are used (last one does not have a pflag), the last port
371 + * is repeated to fill the last entry in ports[] */
374 + u_int8_t flags:2; /* Type of comparison */
375 + u_int16_t pflags:14; /* Port flags */
376 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
378 +#endif /*_IPT_MPORT_H*/
379 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h
380 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
381 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h 2004-09-07 12:33:17.546884104 +0200
386 +#include <linux/param.h>
387 +#include <linux/types.h>
389 +#ifndef IPT_NTH_NUM_COUNTERS
390 +#define IPT_NTH_NUM_COUNTERS 16
393 +struct ipt_nth_info {
401 +#endif /*_IPT_NTH_H*/
402 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h
403 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
404 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_osf.h 2004-09-07 12:33:18.674712648 +0200
409 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
412 + * This program is free software; you can redistribute it and/or modify
413 + * it under the terms of the GNU General Public License as published by
414 + * the Free Software Foundation; either version 2 of the License, or
415 + * (at your option) any later version.
417 + * This program is distributed in the hope that it will be useful,
418 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
419 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
420 + * GNU General Public License for more details.
422 + * You should have received a copy of the GNU General Public License
423 + * along with this program; if not, write to the Free Software
424 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
430 +#define MAXGENRELEN 32
431 +#define MAXDETLEN 64
433 +#define IPT_OSF_GENRE 1
434 +#define IPT_OSF_SMART 2
435 +#define IPT_OSF_LOG 4
436 +#define IPT_OSF_NETLINK 8
438 +#define IPT_OSF_LOGLEVEL_ALL 0
439 +#define IPT_OSF_LOGLEVEL_FIRST 1
441 +#include <linux/list.h>
442 +#include <net/tcp.h>
445 +#include <netinet/ip.h>
446 +#include <netinet/tcp.h>
450 + struct list_head *prev, *next;
456 + char genre[MAXGENRELEN];
458 + unsigned long flags;
460 + int invert; /* UNSUPPORTED */
469 +/* This struct represents IANA options
470 + * http://www.iana.org/assignments/tcp-parameters
474 + unsigned char kind;
475 + unsigned char length;
481 + struct list_head flist;
486 + unsigned char genre[MAXGENRELEN];
487 + unsigned char version[MAXGENRELEN], subtype[MAXGENRELEN];
489 + /* Not needed, but for consistency with original table from Michal Zalewski */
490 + unsigned char details[MAXDETLEN];
493 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
497 +struct ipt_osf_nlmsg
499 + struct osf_finger f;
506 +/* Defines for IANA option kinds */
508 +#define OSFOPT_EOL 0 /* End of options */
509 +#define OSFOPT_NOP 1 /* NOP */
510 +#define OSFOPT_MSS 2 /* Maximum segment size */
511 +#define OSFOPT_WSO 3 /* Window scale option */
512 +#define OSFOPT_SACKP 4 /* SACK permitted */
513 +#define OSFOPT_SACK 5 /* SACK */
514 +#define OSFOPT_ECHO 6
515 +#define OSFOPT_ECHOREPLY 7
516 +#define OSFOPT_TS 8 /* Timestamp option */
517 +#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
518 +#define OSFOPT_POSP 10 /* Partial Order Service Profile */
519 +/* Others are not used in current OSF */
521 +static struct osf_opt IANA_opts[] =
528 + {5, 1 ,}, /* SACK length is not defined */
534 + {11, 1,}, /* CC: Suppose 1 */
535 + {12, 1,}, /* the same */
536 + {13, 1,}, /* and here too */
538 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
552 +#endif /* __KERNEL__ */
554 +#endif /* _IPT_OSF_H */
555 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h
556 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
557 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h 2004-09-07 12:33:19.723553200 +0200
562 +#include <linux/param.h>
563 +#include <linux/types.h>
566 + * High port numbers have a lower weight to reduce the frequency of false
567 + * positives, such as from passive mode FTP transfers.
569 +#define PORT_WEIGHT_PRIV 3
570 +#define PORT_WEIGHT_HIGH 1
573 + * Port scan detection thresholds: at least COUNT ports need to be scanned
574 + * from the same source, with no longer than DELAY ticks between ports.
576 +#define SCAN_MIN_COUNT 7
577 +#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
578 +#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
579 +#define SCAN_DELAY_THRESHOLD (300) /* old usage of HZ here was erroneously and broke under uml */
582 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
583 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
584 + * HASH_MAX source addresses per the same hash value.
586 +#define LIST_SIZE 0x100
588 +#define HASH_SIZE (1 << HASH_LOG)
589 +#define HASH_MAX 0x10
591 +struct ipt_psd_info {
592 + unsigned int weight_threshold;
593 + unsigned int delay_threshold;
594 + unsigned short lo_ports_weight;
595 + unsigned short hi_ports_weight;
598 +#endif /*_IPT_PSD_H*/
599 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h
600 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
601 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h 2004-09-07 12:33:20.689406368 +0200
603 +#ifndef _IPT_QUOTA_H
604 +#define _IPT_QUOTA_H
606 +/* print debug info in both kernel/netfilter module & iptable library */
607 +//#define DEBUG_IPT_QUOTA
609 +struct ipt_quota_info {
613 +#endif /*_IPT_QUOTA_H*/
614 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h
615 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
616 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_sctp.h 2004-09-07 12:33:05.389732272 +0200
618 +#ifndef _IPT_SCTP_H_
619 +#define _IPT_SCTP_H_
621 +#define IPT_SCTP_SRC_PORTS 0x01
622 +#define IPT_SCTP_DEST_PORTS 0x02
623 +#define IPT_SCTP_CHUNK_TYPES 0x04
625 +#define IPT_SCTP_VALID_FLAGS 0x07
627 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
630 +struct ipt_sctp_flag_info {
631 + u_int8_t chunktype;
633 + u_int8_t flag_mask;
636 +#define IPT_NUM_SCTP_FLAGS 4
638 +struct ipt_sctp_info {
639 + u_int16_t dpts[2]; /* Min, Max */
640 + u_int16_t spts[2]; /* Min, Max */
642 + u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */
644 +#define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */
645 +#define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */
646 +#define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */
648 + u_int32_t chunk_match_type;
649 + struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
653 + u_int32_t invflags;
656 +#define bytes(type) (sizeof(type) * 8)
658 +#define SCTP_CHUNKMAP_SET(chunkmap, type) \
660 + chunkmap[type / bytes(u_int32_t)] |= \
661 + 1 << (type % bytes(u_int32_t)); \
664 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \
666 + chunkmap[type / bytes(u_int32_t)] &= \
667 + ~(1 << (type % bytes(u_int32_t))); \
670 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \
672 + (chunkmap[type / bytes (u_int32_t)] & \
673 + (1 << (type % bytes (u_int32_t)))) ? 1: 0; \
676 +#define SCTP_CHUNKMAP_RESET(chunkmap) \
679 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
683 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap) \
686 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
687 + chunkmap[i] = ~0; \
690 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap) \
693 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) \
694 + destmap[i] = srcmap[i]; \
697 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \
701 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
702 + if (chunkmap[i]) { \
710 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \
714 + for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \
715 + if (chunkmap[i] != ~0) { \
723 +#endif /* _IPT_SCTP_H_ */
725 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h
726 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
727 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h 2004-09-07 12:33:22.072196152 +0200
729 +#ifndef __ipt_time_h_included__
730 +#define __ipt_time_h_included__
733 +struct ipt_time_info {
734 + u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
735 + u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
736 + u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
737 + u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
743 +#endif /* __ipt_time_h_included__ */
744 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h
745 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
746 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_u32.h 2004-09-07 12:38:33.376870648 +0200
750 +#include <linux/netfilter_ipv4/ip_tables.h>
760 +struct ipt_u32_location_element
765 +struct ipt_u32_value_element
770 +/* *** any way to allow for an arbitrary number of elements?
771 + for now I settle for a limit of 10 of each */
772 +#define U32MAXSIZE 10
776 + struct ipt_u32_location_element location[U32MAXSIZE+1];
778 + struct ipt_u32_value_element value[U32MAXSIZE+1];
784 + struct ipt_u32_test tests[U32MAXSIZE+1];
787 +#endif /*_IPT_U32_H*/
788 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h
789 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
790 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h 2004-09-07 12:33:06.516560968 +0200
792 +/* Hop Limit modification module for ip6tables
793 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
794 + * Based on HW's TTL module */
805 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
807 +struct ip6t_HL_info {
809 + u_int8_t hop_limit;
814 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h
815 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-09-07 12:07:45.155842952 +0200
816 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-09-07 12:33:08.262295576 +0200
818 #define _IP6T_REJECT_H
820 enum ip6t_reject_with {
821 - IP6T_ICMP_NET_UNREACHABLE,
822 - IP6T_ICMP_HOST_UNREACHABLE,
823 - IP6T_ICMP_PROT_UNREACHABLE,
824 - IP6T_ICMP_PORT_UNREACHABLE,
825 - IP6T_ICMP_ECHOREPLY
826 + IP6T_ICMP6_NO_ROUTE,
827 + IP6T_ICMP6_ADM_PROHIBITED,
828 + IP6T_ICMP6_NOT_NEIGHBOUR,
829 + IP6T_ICMP6_ADDR_UNREACH,
830 + IP6T_ICMP6_PORT_UNREACH,
831 + IP6T_ICMP6_ECHOREPLY,
835 struct ip6t_reject_info {
836 enum ip6t_reject_with with; /* reject type */
839 -#endif /*_IPT_REJECT_H*/
840 +#endif /*_IP6T_REJECT_H*/
841 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h
842 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
843 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-09-07 12:33:12.080715088 +0200
845 +#ifndef _IP6T_FUZZY_H
846 +#define _IP6T_FUZZY_H
848 +#include <linux/param.h>
849 +#include <linux/types.h>
851 +#define MAXFUZZYRATE 10000000
852 +#define MINFUZZYRATE 3
854 +struct ip6t_fuzzy_info {
855 + u_int32_t minimum_rate;
856 + u_int32_t maximum_rate;
857 + u_int32_t packets_total;
858 + u_int32_t bytes_total;
859 + u_int32_t previous_time;
860 + u_int32_t present_time;
861 + u_int32_t mean_rate;
862 + u_int8_t acceptance_rate;
865 +#endif /*_IP6T_FUZZY_H*/
866 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h
867 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
868 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h 2004-09-07 12:33:17.547883952 +0200
873 +#include <linux/param.h>
874 +#include <linux/types.h>
876 +#ifndef IP6T_NTH_NUM_COUNTERS
877 +#define IP6T_NTH_NUM_COUNTERS 16
880 +struct ip6t_nth_info {
888 +#endif /*_IP6T_NTH_H*/
889 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/sysctl.h linux-2.6.7/include/linux/sysctl.h
890 --- linux-2.6.7.org/include/linux/sysctl.h 2004-09-07 12:07:45.225832312 +0200
891 +++ linux-2.6.7/include/linux/sysctl.h 2004-09-07 12:32:47.918388320 +0200
893 NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
894 NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
895 NET_IPV4_NF_CONNTRACK_BUCKETS=14,
896 + NET_IPV4_NF_CONNTRACK_LOG_INVALID=15,
899 /* /proc/sys/net/ipv6 */
900 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Kconfig linux-2.6.7/net/ipv4/netfilter/Kconfig
901 --- linux-2.6.7.org/net/ipv4/netfilter/Kconfig 2004-09-07 12:07:46.566628480 +0200
902 +++ linux-2.6.7/net/ipv4/netfilter/Kconfig 2004-09-07 12:38:33.380870040 +0200
903 @@ -628,5 +628,174 @@
904 If you want to compile it as a module, say M here and read
905 Documentation/modules.txt. If unsure, say `N'.
907 +config IP_NF_CT_ACCT
908 + bool "Connection tracking flow accounting"
909 + depends on IP_NF_CONNTRACK
911 +config IP_NF_MATCH_SCTP
912 + tristate 'SCTP protocol match support'
913 + depends on IP_NF_IPTABLES
915 +config IP_NF_TARGET_IPV4OPTSSTRIP
916 + tristate 'IPV4OPTSSTRIP target support'
917 + depends on IP_NF_MANGLE
919 + This option adds an IPV4OPTSSTRIP target.
920 + This target allows you to strip all IP options in a packet.
922 + If you want to compile it as a module, say M here and read
923 + Documentation/modules.txt. If unsure, say `N'.
925 +config IP_NF_TARGET_TTL
926 + tristate 'TTL target support'
927 + depends on IP_NF_MANGLE
929 + This option adds a `TTL' target, which enables the user to set
930 + the TTL value or increment / decrement the TTL value by a given
933 + If you want to compile it as a module, say M here and read
934 + Documentation/modules.txt. If unsure, say `N'.
936 +config IP_NF_MATCH_CONNLIMIT
937 + tristate 'Connections/IP limit match support'
938 + depends on IP_NF_IPTABLES
940 + This match allows you to restrict the number of parallel TCP
941 + connections to a server per client IP address (or address block).
943 + If you want to compile it as a module, say M here and read
944 + Documentation/modules.txt. If unsure, say `N'.
946 +config IP_NF_MATCH_DSTLIMIT
947 + tristate 'dstlimit match support'
948 + depends on IP_NF_IPTABLES
950 +config IP_NF_MATCH_FUZZY
951 + tristate 'fuzzy match support'
952 + depends on IP_NF_IPTABLES
954 + This option adds a `fuzzy' match, which allows you to match
955 + packets according to a fuzzy logic based law.
957 + If you want to compile it as a module, say M here and read
958 + Documentation/modules.txt. If unsure, say `N'.
960 +config IP_NF_MATCH_IPV4OPTIONS
961 + tristate 'IPV4OPTIONS match support'
962 + depends on IP_NF_IPTABLES
964 + This option adds a IPV4OPTIONS match.
965 + It allows you to filter options like source routing,
966 + record route, timestamp and router-altert.
968 + If you say Y here, try iptables -m ipv4options --help for more information.
970 + If you want to compile it as a module, say M here and read
971 + Documentation/modules.txt. If unsure, say `N'.
973 +config IP_NF_MATCH_MPORT
974 + tristate 'Multiple port with ranges match support'
975 + depends on IP_NF_IPTABLES
977 + This is an enhanced multiport match which supports port
978 + ranges as well as single ports.
980 + If you want to compile it as a module, say M here and read
981 + Documentation/modules.txt. If unsure, say `N'.
983 +config IP_NF_MATCH_NTH
984 + tristate 'Nth match support'
985 + depends on IP_NF_IPTABLES
987 + This option adds a `Nth' match, which allow you to make
988 + rules that match every Nth packet. By default there are
989 + 16 different counters.
992 + --every Nth Match every Nth packet
993 + [--counter] num Use counter 0-15 (default:0)
994 + [--start] num Initialize the counter at the number 'num'
995 + instead of 0. Must be between 0 and Nth-1
996 + [--packet] num Match on 'num' packet. Must be between 0
999 + If --packet is used for a counter than
1000 + there must be Nth number of --packet
1001 + rules, covering all values between 0 and
1002 + Nth-1 inclusively.
1004 + If you want to compile it as a module, say M here and read
1005 + Documentation/modules.txt. If unsure, say `N'.
1007 +config IP_NF_MATCH_OSF
1008 + tristate 'OSF match support'
1009 + depends on IP_NF_IPTABLES
1012 + The idea of passive OS fingerprint matching exists for quite a long time,
1013 + but was created as extension fo OpenBSD pf only some weeks ago.
1014 + Original idea was lurked in some OpenBSD mailing list (thanks
1015 + grange@open...) and than adopted for Linux netfilter in form of this code.
1017 + Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
1018 + his excellent p0f and than changed a bit for more convenience.
1020 + This module compares some data(WS, MSS, options and it's order, ttl,
1021 + df and others) from first SYN packet (actually from packets with SYN
1022 + bit set) with hardcoded in fingers[] table ones.
1024 + If you say Y here, try iptables -m osf --help for more information.
1026 + If you want to compile it as a module, say M here and read
1027 + Documentation/modules.txt. If unsure, say `N'.
1029 +config IP_NF_MATCH_PSD
1030 + tristate 'psd match support'
1031 + depends on IP_NF_IPTABLES
1033 + This option adds a `psd' match, which allows you to create rules in
1034 + any iptables table wich will detect TCP and UDP port scans.
1036 + If you want to compile it as a module, say M here and read
1037 + Documentation/modules.txt. If unsure, say `N'.
1039 +config IP_NF_MATCH_QUOTA
1040 + tristate 'quota match support'
1041 + depends on IP_NF_IPTABLES
1043 + This match implements network quotas.
1045 + If you want to compile it as a module, say M here and read
1046 + Documentation/modules.txt. If unsure, say `N'.
1049 +config IP_NF_MATCH_TIME
1050 + tristate 'TIME match support'
1051 + depends on IP_NF_IPTABLES
1053 + This option adds a `time' match, which allows you
1054 + to match based on the packet arrival time/date
1055 + (arrival time/date at the machine which netfilter is running on) or
1056 + departure time/date (for locally generated packets).
1058 + If you say Y here, try iptables -m time --help for more information.
1060 + If you want to compile it as a module, say M here and read
1061 + Documentation/modules.txt. If unsure, say `N'.
1063 +config IP_NF_MATCH_U32
1064 + tristate 'U32 match support'
1065 + depends on IP_NF_IPTABLES
1067 + U32 allows you to extract quantities of up to 4 bytes from a packet,
1068 + AND them with specified masks, shift them by specified amounts and
1069 + test whether the results are in any of a set of specified ranges.
1070 + The specification of what to extract is general enough to skip over
1071 + headers with lengths stored in the packet, as in IP or TCP header
1074 + Details and examples are in the kernel module source.
1078 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Makefile linux-2.6.7/net/ipv4/netfilter/Makefile
1079 --- linux-2.6.7.org/net/ipv4/netfilter/Makefile 2004-09-07 12:07:46.565628632 +0200
1080 +++ linux-2.6.7/net/ipv4/netfilter/Makefile 2004-09-07 12:38:33.381869888 +0200
1083 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1084 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1085 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
1086 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
1087 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1088 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
1089 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
1090 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
1092 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
1093 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1095 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1097 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1098 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1100 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1103 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
1105 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
1108 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
1110 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
1113 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
1115 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
1117 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
1120 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
1122 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1125 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1126 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1127 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1128 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1129 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1130 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1132 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1133 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1134 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1135 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1136 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1137 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1138 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1139 obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
1140 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_amanda.c
1141 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-09-07 12:07:46.566628480 +0200
1142 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_amanda.c 2004-09-07 12:32:44.773866360 +0200
1145 /* increase the UDP timeout of the master connection as replies from
1146 * Amanda clients to the server can be quite delayed */
1147 - ip_ct_refresh(ct, master_timeout * HZ);
1148 + ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ);
1151 dataoff = skb->nh.iph->ihl*4 + sizeof(struct udphdr);
1152 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c
1153 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-09-07 12:07:46.565628632 +0200
1154 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c 2004-09-07 12:32:54.736351832 +0200
1157 DECLARE_RWLOCK(ip_conntrack_lock);
1158 DECLARE_RWLOCK(ip_conntrack_expect_tuple_lock);
1159 +static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
1161 void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL;
1162 LIST_HEAD(ip_conntrack_expect_list);
1164 static LIST_HEAD(helpers);
1165 unsigned int ip_conntrack_htable_size = 0;
1166 int ip_conntrack_max;
1167 -static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
1168 struct list_head *ip_conntrack_hash;
1169 static kmem_cache_t *ip_conntrack_cachep;
1170 +static kmem_cache_t *ip_conntrack_expect_cachep;
1171 struct ip_conntrack ip_conntrack_untracked;
1173 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
1174 @@ -127,11 +128,11 @@
1178 -get_tuple(const struct iphdr *iph,
1179 - const struct sk_buff *skb,
1180 - unsigned int dataoff,
1181 - struct ip_conntrack_tuple *tuple,
1182 - const struct ip_conntrack_protocol *protocol)
1183 +ip_ct_get_tuple(const struct iphdr *iph,
1184 + const struct sk_buff *skb,
1185 + unsigned int dataoff,
1186 + struct ip_conntrack_tuple *tuple,
1187 + const struct ip_conntrack_protocol *protocol)
1190 if (iph->frag_off & htons(IP_OFFSET)) {
1191 @@ -147,10 +148,10 @@
1192 return protocol->pkt_to_tuple(skb, dataoff, tuple);
1196 -invert_tuple(struct ip_conntrack_tuple *inverse,
1197 - const struct ip_conntrack_tuple *orig,
1198 - const struct ip_conntrack_protocol *protocol)
1200 +ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
1201 + const struct ip_conntrack_tuple *orig,
1202 + const struct ip_conntrack_protocol *protocol)
1204 inverse->src.ip = orig->dst.ip;
1205 inverse->dst.ip = orig->src.ip;
1207 IP_NF_ASSERT(atomic_read(&exp->use) == 0);
1208 IP_NF_ASSERT(!timer_pending(&exp->timeout));
1211 + kmem_cache_free(ip_conntrack_expect_cachep, exp);
1214 inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
1216 list_del(&ct->master->expected_list);
1217 master = ct->master->expectant;
1219 - kfree(ct->master);
1220 + kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
1222 WRITE_UNLOCK(&ip_conntrack_lock);
1224 @@ -496,83 +497,6 @@
1228 -/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
1229 -struct ip_conntrack *
1230 -icmp_error_track(struct sk_buff *skb,
1231 - enum ip_conntrack_info *ctinfo,
1232 - unsigned int hooknum)
1234 - struct ip_conntrack_tuple innertuple, origtuple;
1236 - struct icmphdr icmp;
1239 - struct ip_conntrack_protocol *innerproto;
1240 - struct ip_conntrack_tuple_hash *h;
1243 - IP_NF_ASSERT(skb->nfct == NULL);
1245 - /* Not enough header? */
1246 - if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
1249 - if (inside.icmp.type != ICMP_DEST_UNREACH
1250 - && inside.icmp.type != ICMP_SOURCE_QUENCH
1251 - && inside.icmp.type != ICMP_TIME_EXCEEDED
1252 - && inside.icmp.type != ICMP_PARAMETERPROB
1253 - && inside.icmp.type != ICMP_REDIRECT)
1256 - /* Ignore ICMP's containing fragments (shouldn't happen) */
1257 - if (inside.ip.frag_off & htons(IP_OFFSET)) {
1258 - DEBUGP("icmp_error_track: fragment of proto %u\n",
1259 - inside.ip.protocol);
1263 - innerproto = ip_ct_find_proto(inside.ip.protocol);
1264 - dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
1265 - /* Are they talking about one of our connections? */
1266 - if (!get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
1267 - DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
1271 - /* Ordinarily, we'd expect the inverted tupleproto, but it's
1272 - been preserved inside the ICMP. */
1273 - if (!invert_tuple(&innertuple, &origtuple, innerproto)) {
1274 - DEBUGP("icmp_error_track: Can't invert tuple\n");
1278 - *ctinfo = IP_CT_RELATED;
1280 - h = ip_conntrack_find_get(&innertuple, NULL);
1282 - /* Locally generated ICMPs will match inverted if they
1283 - haven't been SNAT'ed yet */
1284 - /* FIXME: NAT code has to handle half-done double NAT --RR */
1285 - if (hooknum == NF_IP_LOCAL_OUT)
1286 - h = ip_conntrack_find_get(&origtuple, NULL);
1289 - DEBUGP("icmp_error_track: no match\n");
1292 - /* Reverse direction from that found */
1293 - if (DIRECTION(h) != IP_CT_DIR_REPLY)
1294 - *ctinfo += IP_CT_IS_REPLY;
1296 - if (DIRECTION(h) == IP_CT_DIR_REPLY)
1297 - *ctinfo += IP_CT_IS_REPLY;
1300 - /* Update skb to refer to this connection */
1301 - skb->nfct = &h->ctrack->infos[*ctinfo];
1305 /* There's a small race here where we may free a just-assured
1306 connection. Too bad: we're in trouble anyway. */
1307 static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
1310 struct ip_conntrack_expect *expected;
1312 - static unsigned int drop_next;
1314 if (!ip_conntrack_hash_rnd_initted) {
1315 get_random_bytes(&ip_conntrack_hash_rnd, 4);
1316 @@ -637,15 +560,10 @@
1318 hash = hash_conntrack(tuple);
1320 - if (ip_conntrack_max &&
1321 - atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
1322 - /* Try dropping from random chain, or else from the
1323 - chain about to put into (in case they're trying to
1324 - bomb one hash chain). */
1325 - unsigned int next = (drop_next++)%ip_conntrack_htable_size;
1327 - if (!early_drop(&ip_conntrack_hash[next])
1328 - && !early_drop(&ip_conntrack_hash[hash])) {
1329 + if (ip_conntrack_max
1330 + && atomic_read(&ip_conntrack_count) >= ip_conntrack_max) {
1331 + /* Try dropping from this hash chain. */
1332 + if (!early_drop(&ip_conntrack_hash[hash])) {
1333 if (net_ratelimit())
1335 "ip_conntrack: table full, dropping"
1340 - if (!invert_tuple(&repl_tuple, tuple, protocol)) {
1341 + if (!ip_ct_invert_tuple(&repl_tuple, tuple, protocol)) {
1342 DEBUGP("Can't invert tuple.\n");
1345 @@ -693,41 +611,48 @@
1346 struct ip_conntrack_expect *, tuple);
1347 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
1349 - /* If master is not in hash table yet (ie. packet hasn't left
1350 - this machine yet), how can other end know about expected?
1351 - Hence these are not the droids you are looking for (if
1352 - master ct never got confirmed, we'd hold a reference to it
1353 - and weird things would happen to future packets). */
1354 - if (expected && !is_confirmed(expected->expectant))
1357 - /* Look up the conntrack helper for master connections only */
1359 - conntrack->helper = ip_ct_find_helper(&repl_tuple);
1361 + /* If master is not in hash table yet (ie. packet hasn't left
1362 + this machine yet), how can other end know about expected?
1363 + Hence these are not the droids you are looking for (if
1364 + master ct never got confirmed, we'd hold a reference to it
1365 + and weird things would happen to future packets). */
1366 + if (!is_confirmed(expected->expectant)) {
1367 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
1371 - /* If the expectation is dying, then this is a loser. */
1373 - && expected->expectant->helper->timeout
1374 - && ! del_timer(&expected->timeout))
1376 + /* Expectation is dying... */
1377 + if (expected->expectant->helper->timeout
1378 + && !del_timer(&expected->timeout))
1382 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
1383 conntrack, expected);
1384 /* Welcome, Mr. Bond. We've been expecting you... */
1385 + IP_NF_ASSERT(master_ct(conntrack));
1386 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1387 conntrack->master = expected;
1388 expected->sibling = conntrack;
1389 LIST_DELETE(&ip_conntrack_expect_list, expected);
1390 expected->expectant->expecting--;
1391 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1393 - atomic_inc(&ip_conntrack_count);
1395 + /* this is a braindead... --pablo */
1396 + atomic_inc(&ip_conntrack_count);
1397 + WRITE_UNLOCK(&ip_conntrack_lock);
1399 + if (expected->expectfn)
1400 + expected->expectfn(conntrack);
1404 + conntrack->helper = ip_ct_find_helper(&repl_tuple);
1406 +end: atomic_inc(&ip_conntrack_count);
1407 WRITE_UNLOCK(&ip_conntrack_lock);
1409 - if (expected && expected->expectfn)
1410 - expected->expectfn(conntrack);
1411 - return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1412 +ret: return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
1415 /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
1418 IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
1420 - if (!get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4, &tuple, proto))
1421 + if (!ip_ct_get_tuple(skb->nh.iph, skb, skb->nh.iph->ihl*4,
1425 /* look for tuple match */
1426 @@ -828,10 +754,12 @@
1428 proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
1430 - /* It may be an icmp error... */
1431 - if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
1432 - && icmp_error_track(*pskb, &ctinfo, hooknum))
1434 + /* It may be an special packet, error, unclean...
1435 + * inverse of the return code tells to the netfilter
1436 + * core what to do with the packet. */
1437 + if (proto->error != NULL
1438 + && (ret = proto->error(*pskb, &ctinfo, hooknum)) <= 0)
1441 if (!(ct = resolve_normal_ct(*pskb, proto,&set_reply,hooknum,&ctinfo)))
1442 /* Not valid part of a connection */
1444 int invert_tuplepr(struct ip_conntrack_tuple *inverse,
1445 const struct ip_conntrack_tuple *orig)
1447 - return invert_tuple(inverse, orig, ip_ct_find_proto(orig->dst.protonum));
1448 + return ip_ct_invert_tuple(inverse, orig,
1449 + ip_ct_find_proto(orig->dst.protonum));
1452 static inline int resent_expect(const struct ip_conntrack_expect *i,
1454 ip_conntrack_expect_alloc(void)
1456 struct ip_conntrack_expect *new;
1458 - new = (struct ip_conntrack_expect *)
1459 - kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
1461 + new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
1463 DEBUGP("expect_related: OOM allocating expect\n");
1467 /* tuple_cmp compares whole union, we have to initialized cleanly */
1468 memset(new, 0, sizeof(struct ip_conntrack_expect));
1469 + atomic_set(&new->use, 1);
1474 DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
1475 new->expectant = related_to;
1476 new->sibling = NULL;
1477 - atomic_set(&new->use, 1);
1479 /* add to expected list for this connection */
1480 list_add_tail(&new->expected_list, &related_to->sibling_list);
1484 WRITE_UNLOCK(&ip_conntrack_lock);
1486 + /* This expectation is not inserted so no need to lock */
1487 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
1490 } else if (related_to->helper->max_expected &&
1491 @@ -1015,7 +944,7 @@
1492 related_to->helper->name,
1493 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
1494 NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
1496 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
1499 DEBUGP("ip_conntrack: max number of expected "
1500 @@ -1049,7 +978,7 @@
1501 WRITE_UNLOCK(&ip_conntrack_lock);
1502 DEBUGP("expect_related: busy!\n");
1505 + kmem_cache_free(ip_conntrack_expect_cachep, expect);
1509 @@ -1164,21 +1093,39 @@
1513 -/* Refresh conntrack for this many jiffies. */
1514 -void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
1515 +static inline void ct_add_counters(struct ip_conntrack *ct,
1516 + enum ip_conntrack_info ctinfo,
1517 + const struct sk_buff *skb)
1519 +#ifdef CONFIG_IP_NF_CT_ACCT
1521 + ct->counters[CTINFO2DIR(ctinfo)].packets++;
1522 + ct->counters[CTINFO2DIR(ctinfo)].bytes +=
1523 + ntohs(skb->nh.iph->tot_len);
1528 +/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */
1529 +void ip_ct_refresh_acct(struct ip_conntrack *ct,
1530 + enum ip_conntrack_info ctinfo,
1531 + const struct sk_buff *skb,
1532 + unsigned long extra_jiffies)
1534 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
1536 /* If not in hash table, timer will not be active yet */
1537 - if (!is_confirmed(ct))
1538 + if (!is_confirmed(ct)) {
1539 ct->timeout.expires = extra_jiffies;
1541 + ct_add_counters(ct, ctinfo, skb);
1543 WRITE_LOCK(&ip_conntrack_lock);
1544 /* Need del_timer for race avoidance (may already be dying). */
1545 if (del_timer(&ct->timeout)) {
1546 ct->timeout.expires = jiffies + extra_jiffies;
1547 add_timer(&ct->timeout);
1549 + ct_add_counters(ct, ctinfo, skb);
1550 WRITE_UNLOCK(&ip_conntrack_lock);
1553 @@ -1368,6 +1315,7 @@
1556 kmem_cache_destroy(ip_conntrack_cachep);
1557 + kmem_cache_destroy(ip_conntrack_expect_cachep);
1558 vfree(ip_conntrack_hash);
1559 nf_unregister_sockopt(&so_getorigdst);
1561 @@ -1420,6 +1368,15 @@
1562 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
1566 + ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
1567 + sizeof(struct ip_conntrack_expect),
1568 + 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
1569 + if (!ip_conntrack_expect_cachep) {
1570 + printk(KERN_ERR "Unable to create ip_expect slab cache\n");
1571 + goto err_free_conntrack_slab;
1574 /* Don't NEED lock here, but good form anyway. */
1575 WRITE_LOCK(&ip_conntrack_lock);
1576 /* Sew in builtin protocols. */
1577 @@ -1447,6 +1404,8 @@
1581 +err_free_conntrack_slab:
1582 + kmem_cache_destroy(ip_conntrack_cachep);
1584 vfree(ip_conntrack_hash);
1586 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c
1587 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-09-07 12:07:46.565628632 +0200
1588 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_generic.c 2004-09-07 12:32:47.921387864 +0200
1590 /* Returns verdict for packet, or -1 for invalid. */
1591 static int packet(struct ip_conntrack *conntrack,
1592 const struct sk_buff *skb,
1593 - enum ip_conntrack_info conntrackinfo)
1594 + enum ip_conntrack_info ctinfo)
1596 - ip_ct_refresh(conntrack, ip_ct_generic_timeout);
1597 + ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_generic_timeout);
1605 -struct ip_conntrack_protocol ip_conntrack_generic_protocol
1606 -= { { NULL, NULL }, 0, "unknown",
1607 - generic_pkt_to_tuple, generic_invert_tuple, generic_print_tuple,
1608 - generic_print_conntrack, packet, new, NULL, NULL, NULL };
1610 +struct ip_conntrack_protocol ip_conntrack_generic_protocol =
1613 + .name = "unknown",
1614 + .pkt_to_tuple = generic_pkt_to_tuple,
1615 + .invert_tuple = generic_invert_tuple,
1616 + .print_tuple = generic_print_tuple,
1617 + .print_conntrack = generic_print_conntrack,
1621 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
1622 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-09-07 12:07:46.565628632 +0200
1623 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-09-07 12:32:47.930386496 +0200
1625 #include <linux/netfilter.h>
1626 #include <linux/in.h>
1627 #include <linux/icmp.h>
1628 +#include <net/ip.h>
1629 +#include <net/checksum.h>
1630 +#include <linux/netfilter.h>
1631 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1632 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
1633 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
1635 unsigned long ip_ct_icmp_timeout = 30*HZ;
1637 ct->timeout.function((unsigned long)ct);
1639 atomic_inc(&ct->proto.icmp.count);
1640 - ip_ct_refresh(ct, ip_ct_icmp_timeout);
1641 + ip_ct_refresh_acct(ct, ctinfo, skb, ip_ct_icmp_timeout);
1645 @@ -122,7 +127,147 @@
1649 -struct ip_conntrack_protocol ip_conntrack_protocol_icmp
1650 -= { { NULL, NULL }, IPPROTO_ICMP, "icmp",
1651 - icmp_pkt_to_tuple, icmp_invert_tuple, icmp_print_tuple,
1652 - icmp_print_conntrack, icmp_packet, icmp_new, NULL, NULL, NULL };
1654 +icmp_error_message(struct sk_buff *skb,
1655 + enum ip_conntrack_info *ctinfo,
1656 + unsigned int hooknum)
1658 + struct ip_conntrack_tuple innertuple, origtuple;
1660 + struct icmphdr icmp;
1663 + struct ip_conntrack_protocol *innerproto;
1664 + struct ip_conntrack_tuple_hash *h;
1667 + IP_NF_ASSERT(skb->nfct == NULL);
1669 + /* Not enough header? */
1670 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &inside, sizeof(inside))!=0)
1673 + /* Ignore ICMP's containing fragments (shouldn't happen) */
1674 + if (inside.ip.frag_off & htons(IP_OFFSET)) {
1675 + DEBUGP("icmp_error_track: fragment of proto %u\n",
1676 + inside.ip.protocol);
1680 + innerproto = ip_ct_find_proto(inside.ip.protocol);
1681 + dataoff = skb->nh.iph->ihl*4 + sizeof(inside.icmp) + inside.ip.ihl*4;
1682 + /* Are they talking about one of our connections? */
1683 + if (!ip_ct_get_tuple(&inside.ip, skb, dataoff, &origtuple, innerproto)) {
1684 + DEBUGP("icmp_error: ! get_tuple p=%u", inside.ip.protocol);
1688 + /* Ordinarily, we'd expect the inverted tupleproto, but it's
1689 + been preserved inside the ICMP. */
1690 + if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
1691 + DEBUGP("icmp_error_track: Can't invert tuple\n");
1695 + *ctinfo = IP_CT_RELATED;
1697 + h = ip_conntrack_find_get(&innertuple, NULL);
1699 + /* Locally generated ICMPs will match inverted if they
1700 + haven't been SNAT'ed yet */
1701 + /* FIXME: NAT code has to handle half-done double NAT --RR */
1702 + if (hooknum == NF_IP_LOCAL_OUT)
1703 + h = ip_conntrack_find_get(&origtuple, NULL);
1706 + DEBUGP("icmp_error_track: no match\n");
1709 + /* Reverse direction from that found */
1710 + if (DIRECTION(h) != IP_CT_DIR_REPLY)
1711 + *ctinfo += IP_CT_IS_REPLY;
1713 + if (DIRECTION(h) == IP_CT_DIR_REPLY)
1714 + *ctinfo += IP_CT_IS_REPLY;
1717 + /* Update skb to refer to this connection */
1718 + skb->nfct = &h->ctrack->infos[*ctinfo];
1719 + return -NF_ACCEPT;
1722 +/* Small and modified version of icmp_rcv */
1724 +icmp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
1725 + unsigned int hooknum)
1727 + struct icmphdr icmph;
1729 + /* Not enough header? */
1730 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &icmph, sizeof(icmph))!=0) {
1731 + if (LOG_INVALID(IPPROTO_ICMP))
1732 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1733 + "ip_ct_icmp: short packet ");
1734 + return -NF_ACCEPT;
1737 + /* See ip_conntrack_proto_tcp.c */
1738 + if (hooknum != NF_IP_PRE_ROUTING)
1739 + goto checksum_skipped;
1741 + switch (skb->ip_summed) {
1743 + if (!(u16)csum_fold(skb->csum))
1745 + if (LOG_INVALID(IPPROTO_ICMP))
1746 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1747 + "ip_ct_icmp: bad HW ICMP checksum ");
1748 + return -NF_ACCEPT;
1749 + case CHECKSUM_NONE:
1750 + if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) {
1751 + if (LOG_INVALID(IPPROTO_ICMP))
1752 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1753 + "ip_ct_icmp: bad ICMP checksum ");
1754 + return -NF_ACCEPT;
1762 + * 18 is the highest 'known' ICMP type. Anything else is a mystery
1764 + * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently
1767 + if (icmph.type > NR_ICMP_TYPES) {
1768 + if (LOG_INVALID(IPPROTO_ICMP))
1769 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1770 + "ip_ct_icmp: invalid ICMP type ");
1771 + return -NF_ACCEPT;
1774 + /* Need to track icmp error message? */
1775 + if (icmph.type != ICMP_DEST_UNREACH
1776 + && icmph.type != ICMP_SOURCE_QUENCH
1777 + && icmph.type != ICMP_TIME_EXCEEDED
1778 + && icmph.type != ICMP_PARAMETERPROB
1779 + && icmph.type != ICMP_REDIRECT)
1782 + return icmp_error_message(skb, ctinfo, hooknum);
1785 +struct ip_conntrack_protocol ip_conntrack_protocol_icmp =
1787 + .proto = IPPROTO_ICMP,
1789 + .pkt_to_tuple = icmp_pkt_to_tuple,
1790 + .invert_tuple = icmp_invert_tuple,
1791 + .print_tuple = icmp_print_tuple,
1792 + .print_conntrack = icmp_print_conntrack,
1793 + .packet = icmp_packet,
1795 + .error = icmp_error,
1797 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
1798 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-09-07 12:07:46.566628480 +0200
1799 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-09-07 12:32:47.922387712 +0200
1801 set_bit(IPS_ASSURED_BIT, &conntrack->status);
1803 out: WRITE_UNLOCK(&tcp_lock);
1804 - ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
1805 + ip_ct_refresh_acct(conntrack, ctinfo, skb, *tcp_timeouts[newconntrack]);
1809 @@ -268,7 +268,15 @@
1810 return between(exp->seq, ntohl(tcph.seq), ntohl(tcph.seq) + datalen);
1813 -struct ip_conntrack_protocol ip_conntrack_protocol_tcp
1814 -= { { NULL, NULL }, IPPROTO_TCP, "tcp",
1815 - tcp_pkt_to_tuple, tcp_invert_tuple, tcp_print_tuple, tcp_print_conntrack,
1816 - tcp_packet, tcp_new, NULL, tcp_exp_matches_pkt, NULL };
1817 +struct ip_conntrack_protocol ip_conntrack_protocol_tcp =
1819 + .proto = IPPROTO_TCP,
1821 + .pkt_to_tuple = tcp_pkt_to_tuple,
1822 + .invert_tuple = tcp_invert_tuple,
1823 + .print_tuple = tcp_print_tuple,
1824 + .print_conntrack = tcp_print_conntrack,
1825 + .packet = tcp_packet,
1827 + .exp_matches_pkt = tcp_exp_matches_pkt,
1829 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c
1830 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-09-07 12:07:46.565628632 +0200
1831 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-09-07 12:32:47.931386344 +0200
1833 #include <linux/netfilter.h>
1834 #include <linux/in.h>
1835 #include <linux/udp.h>
1836 +#include <net/checksum.h>
1837 +#include <linux/netfilter.h>
1838 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
1840 unsigned long ip_ct_udp_timeout = 30*HZ;
1842 /* Returns verdict for packet, and may modify conntracktype */
1843 static int udp_packet(struct ip_conntrack *conntrack,
1844 const struct sk_buff *skb,
1845 - enum ip_conntrack_info conntrackinfo)
1846 + enum ip_conntrack_info ctinfo)
1848 /* If we've seen traffic both ways, this is some kind of UDP
1849 stream. Extend timeout. */
1850 if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
1851 - ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
1852 + ip_ct_refresh_acct(conntrack, ctinfo, skb,
1853 + ip_ct_udp_timeout_stream);
1854 /* Also, more likely to be important, and not a probe */
1855 set_bit(IPS_ASSURED_BIT, &conntrack->status);
1857 - ip_ct_refresh(conntrack, ip_ct_udp_timeout);
1858 + ip_ct_refresh_acct(conntrack, ctinfo, skb, ip_ct_udp_timeout);
1866 -struct ip_conntrack_protocol ip_conntrack_protocol_udp
1867 -= { { NULL, NULL }, IPPROTO_UDP, "udp",
1868 - udp_pkt_to_tuple, udp_invert_tuple, udp_print_tuple, udp_print_conntrack,
1869 - udp_packet, udp_new, NULL, NULL, NULL };
1870 +static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
1871 + unsigned int hooknum)
1873 + struct iphdr *iph = skb->nh.iph;
1874 + unsigned int udplen = skb->len - iph->ihl * 4;
1875 + struct udphdr hdr;
1877 + /* Header is too small? */
1878 + if (skb_copy_bits(skb, iph->ihl*4, &hdr, sizeof(hdr)) != 0) {
1879 + if (LOG_INVALID(IPPROTO_UDP))
1880 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1881 + "ip_ct_udp: short packet ");
1882 + return -NF_ACCEPT;
1885 + /* Truncated/malformed packets */
1886 + if (ntohs(hdr.len) > udplen || ntohs(hdr.len) < sizeof(hdr)) {
1887 + if (LOG_INVALID(IPPROTO_UDP))
1888 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1889 + "ip_ct_udp: truncated/malformed packet ");
1890 + return -NF_ACCEPT;
1893 + /* Packet with no checksum */
1897 + /* Checksum invalid? Ignore.
1898 + * We skip checking packets on the outgoing path
1899 + * because the semantic of CHECKSUM_HW is different there
1900 + * and moreover root might send raw packets.
1901 + * FIXME: Source route IP option packets --RR */
1902 + if (hooknum == NF_IP_PRE_ROUTING
1903 + && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
1904 + skb->ip_summed == CHECKSUM_HW ? skb->csum
1905 + : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
1906 + if (LOG_INVALID(IPPROTO_UDP))
1907 + nf_log_packet(PF_INET, 0, skb, NULL, NULL,
1908 + "ip_ct_udp: bad UDP checksum ");
1909 + return -NF_ACCEPT;
1915 +struct ip_conntrack_protocol ip_conntrack_protocol_udp =
1917 + .proto = IPPROTO_UDP,
1919 + .pkt_to_tuple = udp_pkt_to_tuple,
1920 + .invert_tuple = udp_invert_tuple,
1921 + .print_tuple = udp_print_tuple,
1922 + .print_conntrack = udp_print_conntrack,
1923 + .packet = udp_packet,
1925 + .error = udp_error,
1927 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c
1928 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-09-07 12:07:46.565628632 +0200
1929 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-09-07 12:32:47.924387408 +0200
1931 #include <linux/module.h>
1932 #include <linux/skbuff.h>
1933 #include <linux/proc_fs.h>
1934 +#include <linux/seq_file.h>
1935 #ifdef CONFIG_SYSCTL
1936 #include <linux/sysctl.h>
1938 @@ -63,128 +64,225 @@
1942 -/* FIXME: Don't print source proto part. --RR */
1943 +#ifdef CONFIG_IP_NF_CT_ACCT
1945 -print_expect(char *buffer, const struct ip_conntrack_expect *expect)
1946 +seq_print_counters(struct seq_file *s, struct ip_conntrack_counter *counter)
1950 - if (expect->expectant->helper->timeout)
1951 - len = sprintf(buffer, "EXPECTING: %lu ",
1952 - timer_pending(&expect->timeout)
1953 - ? (expect->timeout.expires - jiffies)/HZ : 0);
1955 - len = sprintf(buffer, "EXPECTING: - ");
1956 - len += sprintf(buffer + len, "use=%u proto=%u ",
1957 - atomic_read(&expect->use), expect->tuple.dst.protonum);
1958 - len += print_tuple(buffer + len, &expect->tuple,
1959 - __ip_ct_find_proto(expect->tuple.dst.protonum));
1960 - len += sprintf(buffer + len, "\n");
1962 + return seq_printf(s, "packets=%llu bytes=%llu ",
1963 + counter->packets, counter->bytes);
1966 +#define seq_print_counters(x, y) 0
1969 -static unsigned int
1970 -print_conntrack(char *buffer, struct ip_conntrack *conntrack)
1971 +static void *ct_seq_start(struct seq_file *s, loff_t *pos)
1974 - struct ip_conntrack_protocol *proto
1975 - = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1976 - .tuple.dst.protonum);
1978 - len = sprintf(buffer, "%-8s %u %lu ",
1980 - conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
1981 - .tuple.dst.protonum,
1982 - timer_pending(&conntrack->timeout)
1983 - ? (conntrack->timeout.expires - jiffies)/HZ : 0);
1984 + unsigned int *bucket;
1986 - len += proto->print_conntrack(buffer + len, conntrack);
1987 - len += print_tuple(buffer + len,
1988 - &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
1990 - if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
1991 - len += sprintf(buffer + len, "[UNREPLIED] ");
1992 - len += print_tuple(buffer + len,
1993 - &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
1995 - if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
1996 - len += sprintf(buffer + len, "[ASSURED] ");
1997 - len += sprintf(buffer + len, "use=%u ",
1998 - atomic_read(&conntrack->ct_general.use));
1999 - len += sprintf(buffer + len, "\n");
2000 + /* strange seq_file api calls stop even if we fail,
2001 + * thus we need to grab lock since stop unlocks */
2002 + READ_LOCK(&ip_conntrack_lock);
2004 + if (*pos >= ip_conntrack_htable_size)
2008 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
2010 + return ERR_PTR(-ENOMEM);
2017 +static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
2019 + unsigned int *bucket = (unsigned int *) v;
2021 -/* Returns true when finished. */
2023 -conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
2024 - char *buffer, off_t offset, off_t *upto,
2025 - unsigned int *len, unsigned int maxlen)
2026 + *pos = ++(*bucket);
2027 + if (*pos >= ip_conntrack_htable_size) {
2034 +static void ct_seq_stop(struct seq_file *s, void *v)
2036 - unsigned int newlen;
2037 - IP_NF_ASSERT(hash->ctrack);
2038 + READ_UNLOCK(&ip_conntrack_lock);
2041 +/* return 0 on success, 1 in case of error */
2042 +static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
2043 + struct seq_file *s)
2045 + struct ip_conntrack *conntrack = hash->ctrack;
2046 + struct ip_conntrack_protocol *proto;
2047 + char buffer[IP_CT_PRINT_BUFLEN];
2049 MUST_BE_READ_LOCKED(&ip_conntrack_lock);
2051 - /* Only count originals */
2052 + IP_NF_ASSERT(conntrack);
2054 + /* we only want to print DIR_ORIGINAL */
2055 if (DIRECTION(hash))
2058 - if ((*upto)++ < offset)
2060 + proto = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
2061 + .tuple.dst.protonum);
2062 + IP_NF_ASSERT(proto);
2064 - newlen = print_conntrack(buffer + *len, hash->ctrack);
2065 - if (*len + newlen > maxlen)
2066 + if (seq_printf(s, "%-8s %u %lu ",
2068 + conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
2069 + timer_pending(&conntrack->timeout)
2070 + ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
2073 + proto->print_conntrack(buffer, conntrack);
2074 + if (seq_puts(s, buffer))
2077 + print_tuple(buffer, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
2080 + if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
2083 + if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
2084 + if (seq_printf(s, "[UNREPLIED] "))
2087 + print_tuple(buffer, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
2089 + if (seq_puts(s, buffer))
2092 + if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
2095 + if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
2096 + if (seq_printf(s, "[ASSURED] "))
2099 + if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
2101 - else *len += newlen;
2107 -list_conntracks(char *buffer, char **start, off_t offset, int length)
2109 +static int ct_seq_show(struct seq_file *s, void *v)
2112 - unsigned int len = 0;
2114 - struct list_head *e;
2115 + unsigned int *bucket = (unsigned int *) v;
2117 - READ_LOCK(&ip_conntrack_lock);
2118 - /* Traverse hash; print originals then reply. */
2119 - for (i = 0; i < ip_conntrack_htable_size; i++) {
2120 - if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
2121 - struct ip_conntrack_tuple_hash *,
2122 - buffer, offset, &upto, &len, length))
2124 + if (LIST_FIND(&ip_conntrack_hash[*bucket], ct_seq_real_show,
2125 + struct ip_conntrack_tuple_hash *, s)) {
2126 + /* buffer was filled and unable to print that tuple */
2132 +static struct seq_operations ct_seq_ops = {
2133 + .start = ct_seq_start,
2134 + .next = ct_seq_next,
2135 + .stop = ct_seq_stop,
2136 + .show = ct_seq_show
2139 +static int ct_open(struct inode *inode, struct file *file)
2141 + return seq_open(file, &ct_seq_ops);
2144 - /* Now iterate through expecteds. */
2145 +static struct file_operations ct_file_ops = {
2146 + .owner = THIS_MODULE,
2149 + .llseek = seq_lseek,
2150 + .release = seq_release
2154 +static void *exp_seq_start(struct seq_file *s, loff_t *pos)
2156 + struct list_head *e = &ip_conntrack_expect_list;
2159 + /* strange seq_file api calls stop even if we fail,
2160 + * thus we need to grab lock since stop unlocks */
2161 + READ_LOCK(&ip_conntrack_lock);
2162 READ_LOCK(&ip_conntrack_expect_tuple_lock);
2163 - list_for_each(e, &ip_conntrack_expect_list) {
2164 - unsigned int last_len;
2165 - struct ip_conntrack_expect *expect
2166 - = (struct ip_conntrack_expect *)e;
2167 - if (upto++ < offset) continue;
2170 - len += print_expect(buffer + len, expect);
2171 - if (len > length) {
2173 - goto finished_expects;
2176 + if (list_empty(e))
2179 + for (i = 0; i <= *pos; i++) {
2181 + if (e == &ip_conntrack_expect_list)
2187 +static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
2189 + struct list_head *e = v;
2193 + if (e == &ip_conntrack_expect_list)
2200 +static void exp_seq_stop(struct seq_file *s, void *v)
2202 READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
2204 READ_UNLOCK(&ip_conntrack_lock);
2207 - /* `start' hack - see fs/proc/generic.c line ~165 */
2208 - *start = (char *)((unsigned int)upto - offset);
2210 +static int exp_seq_show(struct seq_file *s, void *v)
2212 + struct ip_conntrack_expect *expect = v;
2213 + char buffer[IP_CT_PRINT_BUFLEN];
2215 + if (expect->expectant->helper->timeout)
2216 + seq_printf(s, "%lu ", timer_pending(&expect->timeout)
2217 + ? (expect->timeout.expires - jiffies)/HZ : 0);
2219 + seq_printf(s, "- ");
2221 + seq_printf(s, "use=%u proto=%u ", atomic_read(&expect->use),
2222 + expect->tuple.dst.protonum);
2224 + print_tuple(buffer, &expect->tuple,
2225 + __ip_ct_find_proto(expect->tuple.dst.protonum));
2226 + return seq_printf(s, "%s\n", buffer);
2229 +static struct seq_operations exp_seq_ops = {
2230 + .start = exp_seq_start,
2231 + .next = exp_seq_next,
2232 + .stop = exp_seq_stop,
2233 + .show = exp_seq_show
2236 +static int exp_open(struct inode *inode, struct file *file)
2238 + return seq_open(file, &exp_seq_ops);
2241 +static struct file_operations exp_file_ops = {
2242 + .owner = THIS_MODULE,
2245 + .llseek = seq_lseek,
2246 + .release = seq_release
2249 static unsigned int ip_confirm(unsigned int hooknum,
2250 struct sk_buff **pskb,
2251 const struct net_device *in,
2252 @@ -334,6 +432,11 @@
2253 /* From ip_conntrack_proto_icmp.c */
2254 extern unsigned long ip_ct_generic_timeout;
2256 +/* Log invalid packets of a given protocol */
2257 +unsigned int ip_ct_log_invalid = 0;
2258 +static int log_invalid_proto_min = 0;
2259 +static int log_invalid_proto_max = 255;
2261 static struct ctl_table_header *ip_ct_sysctl_header;
2263 static ctl_table ip_ct_sysctl_table[] = {
2264 @@ -449,6 +552,17 @@
2266 .proc_handler = &proc_dointvec_jiffies,
2269 + .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
2270 + .procname = "ip_conntrack_log_invalid",
2271 + .data = &ip_ct_log_invalid,
2272 + .maxlen = sizeof(unsigned int),
2274 + .proc_handler = &proc_dointvec_minmax,
2275 + .strategy = &sysctl_intvec,
2276 + .extra1 = &log_invalid_proto_min,
2277 + .extra2 = &log_invalid_proto_max,
2284 static int init_or_cleanup(int init)
2286 - struct proc_dir_entry *proc;
2287 + struct proc_dir_entry *proc, *proc_exp;
2290 if (!init) goto cleanup;
2291 @@ -503,14 +617,18 @@
2293 goto cleanup_nothing;
2295 - proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
2296 + proc = proc_net_create("ip_conntrack", 0440, NULL);
2297 if (!proc) goto cleanup_init;
2298 - proc->owner = THIS_MODULE;
2299 + proc->proc_fops = &ct_file_ops;
2301 + proc_exp = proc_net_create("ip_conntrack_expect", 0440, NULL);
2302 + if (!proc_exp) goto cleanup_proc;
2303 + proc_exp->proc_fops = &exp_file_ops;
2305 ret = nf_register_hook(&ip_conntrack_defrag_ops);
2307 printk("ip_conntrack: can't register pre-routing defrag hook.\n");
2308 - goto cleanup_proc;
2309 + goto cleanup_proc_exp;
2311 ret = nf_register_hook(&ip_conntrack_defrag_local_out_ops);
2314 nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
2316 nf_unregister_hook(&ip_conntrack_defrag_ops);
2318 + proc_net_remove("ip_conntrack_exp");
2320 proc_net_remove("ip_conntrack");
2323 EXPORT_SYMBOL(ip_conntrack_helper_register);
2324 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
2325 EXPORT_SYMBOL(ip_ct_selective_cleanup);
2326 -EXPORT_SYMBOL(ip_ct_refresh);
2327 +EXPORT_SYMBOL(ip_ct_refresh_acct);
2328 EXPORT_SYMBOL(ip_ct_find_proto);
2329 EXPORT_SYMBOL(__ip_ct_find_proto);
2330 EXPORT_SYMBOL(ip_ct_find_helper);
2331 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c
2332 --- linux-2.6.7.org/net/ipv4/netfilter/ip_fw_compat_masq.c 2004-09-07 12:07:46.566628480 +0200
2333 +++ linux-2.6.7/net/ipv4/netfilter/ip_fw_compat_masq.c 2004-09-07 12:32:47.925387256 +0200
2336 #include <linux/netfilter_ipv4/ip_conntrack.h>
2337 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
2338 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2339 #include <linux/netfilter_ipv4/ip_nat.h>
2340 #include <linux/netfilter_ipv4/ip_nat_core.h>
2341 #include <linux/netfilter_ipv4/listhelp.h>
2343 switch ((*pskb)->nh.iph->protocol) {
2346 - ct = icmp_error_track(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
2347 + protocol->error(*pskb, &ctinfo, NF_IP_PRE_ROUTING);
2348 + ct = (struct ip_conntrack *)(*pskb)->nfct->master;
2350 /* We only do SNAT in the compatibility layer.
2351 So we can manipulate ICMP errors from
2354 IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
2356 - if (!get_tuple((*pskb)->nh.iph, *pskb, (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
2357 + if (!ip_ct_get_tuple((*pskb)->nh.iph, *pskb,
2358 + (*pskb)->nh.iph->ihl*4, &tuple, protocol)) {
2359 if (net_ratelimit())
2360 printk("ip_fw_compat_masq: Can't get tuple\n");
2362 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.7/net/ipv4/netfilter/ip_nat_core.c
2363 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_core.c 2004-09-07 12:07:46.565628632 +0200
2364 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_core.c 2004-09-07 12:32:56.183131888 +0200
2366 static struct list_head *bysource;
2367 static struct list_head *byipsproto;
2369 -LIST_HEAD(helpers);
2371 extern struct ip_nat_protocol unknown_nat_protocol;
2373 @@ -498,13 +497,6 @@
2378 -helper_cmp(const struct ip_nat_helper *helper,
2379 - const struct ip_conntrack_tuple *tuple)
2381 - return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
2384 /* Where to manip the reply packets (will be reverse manip). */
2385 static unsigned int opposite_hook[NF_IP_NUMHOOKS]
2386 = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
2389 /* If there's a helper, assign it; based on new tuple. */
2390 if (!conntrack->master)
2391 - info->helper = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *,
2393 + info->helper = ip_nat_find_helper(&reply);
2396 info->initialized |= (1 << HOOK2MANIP(hooknum));
2397 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.7/net/ipv4/netfilter/ip_nat_helper.c
2398 --- linux-2.6.7.org/net/ipv4/netfilter/ip_nat_helper.c 2004-09-07 12:07:46.565628632 +0200
2399 +++ linux-2.6.7/net/ipv4/netfilter/ip_nat_helper.c 2004-09-07 12:32:56.184131736 +0200
2401 #define DUMP_OFFSET(x)
2404 +static LIST_HEAD(helpers);
2405 DECLARE_LOCK(ip_nat_seqofs_lock);
2407 /* Setup TCP sequence correction given this change at this sequence */
2408 @@ -419,6 +420,18 @@
2412 +struct ip_nat_helper *
2413 +ip_nat_find_helper(const struct ip_conntrack_tuple *tuple)
2415 + struct ip_nat_helper *h;
2417 + READ_LOCK(&ip_nat_lock);
2418 + h = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple);
2419 + READ_UNLOCK(&ip_nat_lock);
2425 kill_helper(const struct ip_conntrack *i, void *helper)
2427 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_queue.c linux-2.6.7/net/ipv4/netfilter/ip_queue.c
2428 --- linux-2.6.7.org/net/ipv4/netfilter/ip_queue.c 2004-09-07 12:07:46.566628480 +0200
2429 +++ linux-2.6.7/net/ipv4/netfilter/ip_queue.c 2004-09-07 12:33:00.821426760 +0200
2430 @@ -255,9 +255,10 @@
2431 entry->skb->dev->hard_header_parse(entry->skb,
2436 - memcpy(pmsg->payload, entry->skb->data, data_len);
2439 + if (skb_copy_bits(entry->skb, 0, pmsg->payload, data_len) != 0)
2440 + goto nlmsg_failure;
2442 nlh->nlmsg_len = skb->tail - old_tail;
2444 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
2445 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
2446 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-09-07 12:33:07.424422952 +0200
2449 + * Strip all IP options in the IP packet header.
2451 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
2452 + * This software is distributed under GNU GPL v2, 1991
2455 +#include <linux/module.h>
2456 +#include <linux/skbuff.h>
2457 +#include <net/ip.h>
2458 +#include <net/checksum.h>
2460 +#include <linux/netfilter_ipv4/ip_tables.h>
2462 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
2463 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
2464 +MODULE_LICENSE("GPL");
2466 +static unsigned int
2467 +target(struct sk_buff **pskb,
2468 + const struct net_device *in,
2469 + const struct net_device *out,
2470 + unsigned int hooknum,
2471 + const void *targinfo,
2474 + struct iphdr *iph;
2475 + struct sk_buff *skb;
2476 + struct ip_options *opt;
2477 + unsigned char *optiph;
2480 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
2484 + iph = (*pskb)->nh.iph;
2485 + optiph = skb->nh.raw;
2486 + l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
2488 + /* if no options in packet then nothing to clear. */
2489 + if (iph->ihl * 4 == sizeof(struct iphdr))
2490 + return IPT_CONTINUE;
2492 + /* else clear all options */
2493 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
2494 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
2495 + opt = &(IPCB(skb)->opt);
2499 + skb->nfcache |= NFC_ALTERED;
2501 + return IPT_CONTINUE;
2505 +checkentry(const char *tablename,
2506 + const struct ipt_entry *e,
2508 + unsigned int targinfosize,
2509 + unsigned int hook_mask)
2511 + if (strcmp(tablename, "mangle")) {
2512 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
2515 + /* nothing else to check because no parameters */
2519 +static struct ipt_target ipt_ipv4optsstrip_reg = {
2520 + .name = "IPV4OPTSSTRIP",
2522 + .checkentry = checkentry,
2523 + .me = THIS_MODULE };
2525 +static int __init init(void)
2527 + return ipt_register_target(&ipt_ipv4optsstrip_reg);
2530 +static void __exit fini(void)
2532 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
2537 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_LOG.c linux-2.6.7/net/ipv4/netfilter/ipt_LOG.c
2538 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_LOG.c 2004-09-07 12:07:46.566628480 +0200
2539 +++ linux-2.6.7/net/ipv4/netfilter/ipt_LOG.c 2004-09-07 12:32:38.740783528 +0200
2541 printk("FRAG:%u ", ntohs(iph.frag_off) & IP_OFFSET);
2543 if ((info->logflags & IPT_LOG_IPOPT)
2544 - && iph.ihl * 4 != sizeof(struct iphdr)) {
2545 + && iph.ihl * 4 > sizeof(struct iphdr)) {
2546 unsigned char opt[4 * 15 - sizeof(struct iphdr)];
2547 unsigned int i, optsize;
2550 printk("URGP=%u ", ntohs(tcph.urg_ptr));
2552 if ((info->logflags & IPT_LOG_TCPOPT)
2553 - && tcph.doff * 4 != sizeof(struct tcphdr)) {
2554 + && tcph.doff * 4 > sizeof(struct tcphdr)) {
2555 unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
2556 unsigned int i, optsize;
2558 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c
2559 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
2560 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c 2004-09-07 12:33:09.041177168 +0200
2562 +/* TTL modification target for IP tables
2563 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
2565 + * Version: $Revision$
2567 + * This software is distributed under the terms of GNU GPL
2570 +#include <linux/module.h>
2571 +#include <linux/skbuff.h>
2572 +#include <linux/ip.h>
2573 +#include <net/checksum.h>
2575 +#include <linux/netfilter_ipv4/ip_tables.h>
2576 +#include <linux/netfilter_ipv4/ipt_TTL.h>
2578 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
2579 +MODULE_DESCRIPTION("IP tables TTL modification module");
2580 +MODULE_LICENSE("GPL");
2582 +static unsigned int
2583 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in,
2584 + const struct net_device *out, unsigned int hooknum,
2585 + const void *targinfo, void *userinfo)
2587 + struct iphdr *iph;
2588 + const struct ipt_TTL_info *info = targinfo;
2589 + u_int16_t diffs[2];
2592 + if (!skb_ip_make_writable(pskb, (*pskb)->len))
2595 + iph = (*pskb)->nh.iph;
2597 + switch (info->mode) {
2599 + new_ttl = info->ttl;
2602 + new_ttl = iph->ttl + info->ttl;
2603 + if (new_ttl > 255)
2607 + new_ttl = iph->ttl - info->ttl;
2612 + new_ttl = iph->ttl;
2616 + if (new_ttl != iph->ttl) {
2617 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
2618 + iph->ttl = new_ttl;
2619 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
2620 + iph->check = csum_fold(csum_partial((char *)diffs,
2622 + iph->check^0xFFFF));
2623 + (*pskb)->nfcache |= NFC_ALTERED;
2626 + return IPT_CONTINUE;
2629 +static int ipt_ttl_checkentry(const char *tablename,
2630 + const struct ipt_entry *e,
2632 + unsigned int targinfosize,
2633 + unsigned int hook_mask)
2635 + struct ipt_TTL_info *info = targinfo;
2637 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
2638 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
2640 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
2644 + if (strcmp(tablename, "mangle")) {
2645 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
2649 + if (info->mode > IPT_TTL_MAXMODE) {
2650 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
2655 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
2656 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
2663 +static struct ipt_target ipt_TTL = {
2665 + .target = ipt_ttl_target,
2666 + .checkentry = ipt_ttl_checkentry,
2670 +static int __init init(void)
2672 + return ipt_register_target(&ipt_TTL);
2675 +static void __exit fini(void)
2677 + ipt_unregister_target(&ipt_TTL);
2682 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_connlimit.c
2683 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
2684 +++ linux-2.6.7/net/ipv4/netfilter/ipt_connlimit.c 2004-09-07 12:33:10.091017568 +0200
2687 + * netfilter module to limit the number of parallel tcp
2688 + * connections per IP address.
2689 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
2690 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
2691 + * only ignore TIME_WAIT or gone connections
2695 + * Kernel module to match connection tracking information.
2696 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
2698 +#include <linux/module.h>
2699 +#include <linux/skbuff.h>
2700 +#include <linux/list.h>
2701 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2702 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2703 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
2704 +#include <linux/netfilter_ipv4/ip_tables.h>
2705 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
2709 +MODULE_LICENSE("GPL");
2711 +/* we'll save the tuples of all connections we care about */
2712 +struct ipt_connlimit_conn
2714 + struct list_head list;
2715 + struct ip_conntrack_tuple tuple;
2718 +struct ipt_connlimit_data {
2720 + struct list_head iphash[256];
2723 +static int ipt_iphash(u_int32_t addr)
2727 + hash = addr & 0xff;
2728 + hash ^= (addr >> 8) & 0xff;
2729 + hash ^= (addr >> 16) & 0xff;
2730 + hash ^= (addr >> 24) & 0xff;
2734 +static int count_them(struct ipt_connlimit_data *data,
2735 + u_int32_t addr, u_int32_t mask,
2736 + struct ip_conntrack *ct)
2739 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
2740 + "fin_wait", "time_wait", "close", "close_wait",
2741 + "last_ack", "listen" };
2743 + int addit = 1, matches = 0;
2744 + struct ip_conntrack_tuple tuple;
2745 + struct ip_conntrack_tuple_hash *found;
2746 + struct ipt_connlimit_conn *conn;
2747 + struct list_head *hash,*lh;
2749 + spin_lock(&data->lock);
2750 + tuple = ct->tuplehash[0].tuple;
2751 + hash = &data->iphash[ipt_iphash(addr & mask)];
2753 + /* check the saved connections */
2754 + for (lh = hash->next; lh != hash; lh = lh->next) {
2755 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
2756 + found = ip_conntrack_find_get(&conn->tuple,ct);
2757 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
2759 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
2760 + /* Just to be sure we have it only once in the list.
2761 + We should'nt see tuples twice unless someone hooks this
2762 + into a table without "-p tcp --syn" */
2766 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
2767 + ipt_iphash(addr & mask),
2768 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
2769 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
2770 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
2772 + if (NULL == found) {
2773 + /* this one is gone */
2775 + list_del(lh->next);
2779 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
2780 + /* we don't care about connections which are
2781 + closed already -> ditch it */
2783 + list_del(lh->next);
2785 + nf_conntrack_put(&found->ctrack->infos[0]);
2788 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
2789 + /* same source IP address -> be counted! */
2792 + nf_conntrack_put(&found->ctrack->infos[0]);
2795 + /* save the new connection in our list */
2797 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
2798 + ipt_iphash(addr & mask),
2799 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
2800 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
2802 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
2805 + memset(conn,0,sizeof(*conn));
2806 + INIT_LIST_HEAD(&conn->list);
2807 + conn->tuple = tuple;
2808 + list_add(&conn->list,hash);
2811 + spin_unlock(&data->lock);
2816 +match(const struct sk_buff *skb,
2817 + const struct net_device *in,
2818 + const struct net_device *out,
2819 + const void *matchinfo,
2823 + const struct ipt_connlimit_info *info = matchinfo;
2824 + int connections, match;
2825 + struct ip_conntrack *ct;
2826 + enum ip_conntrack_info ctinfo;
2828 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2830 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
2834 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
2835 + if (-1 == connections) {
2836 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
2837 + *hotdrop = 1; /* let's free some memory :-) */
2840 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
2842 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
2843 + "connections=%d limit=%d match=%s\n",
2844 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
2845 + connections, info->limit, match ? "yes" : "no");
2851 +static int check(const char *tablename,
2852 + const struct ipt_ip *ip,
2854 + unsigned int matchsize,
2855 + unsigned int hook_mask)
2857 + struct ipt_connlimit_info *info = matchinfo;
2861 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
2864 + /* refuse anything but tcp */
2865 + if (ip->proto != IPPROTO_TCP)
2868 + /* init private data */
2869 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
2870 + spin_lock_init(&(info->data->lock));
2871 + for (i = 0; i < 256; i++)
2872 + INIT_LIST_HEAD(&(info->data->iphash[i]));
2877 +static void destroy(void *matchinfo, unsigned int matchinfosize)
2879 + struct ipt_connlimit_info *info = matchinfo;
2880 + struct ipt_connlimit_conn *conn;
2881 + struct list_head *hash;
2885 + for (i = 0; i < 256; i++) {
2886 + hash = &(info->data->iphash[i]);
2887 + while (hash != hash->next) {
2888 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
2889 + list_del(hash->next);
2893 + kfree(info->data);
2896 +static struct ipt_match connlimit_match = {
2897 + .name = "connlimit",
2899 + .checkentry = &check,
2900 + .destroy = &destroy,
2904 +static int __init init(void)
2906 + return ipt_register_match(&connlimit_match);
2909 +static void __exit fini(void)
2911 + ipt_unregister_match(&connlimit_match);
2916 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c
2917 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
2918 +++ linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c 2004-09-07 12:33:11.098864352 +0200
2920 +/* iptables match extension to limit the number of packets per second
2921 + * seperately for each destination.
2923 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2927 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2929 + * based on ipt_limit.c by:
2930 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
2931 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
2932 + * Rusty Russell <rusty@rustcorp.com.au>
2934 + * The general idea is to create a hash table for every dstip and have a
2935 + * seperate limit counter per tuple. This way you can do something like 'limit
2936 + * the number of syn packets for each of my internal addresses.
2938 + * Ideally this would just be implemented as a general 'hash' match, which would
2939 + * allow us to attach any iptables target to it's hash buckets. But this is
2940 + * not possible in the current iptables architecture. As always, pkttables for
2941 + * 2.7.x will help ;)
2943 +#include <linux/module.h>
2944 +#include <linux/skbuff.h>
2945 +#include <linux/spinlock.h>
2946 +#include <linux/random.h>
2947 +#include <linux/jhash.h>
2948 +#include <linux/slab.h>
2949 +#include <linux/vmalloc.h>
2950 +#include <linux/tcp.h>
2951 +#include <linux/udp.h>
2952 +#include <linux/proc_fs.h>
2953 +#include <linux/seq_file.h>
2955 +#define ASSERT_READ_LOCK(x)
2956 +#define ASSERT_WRITE_LOCK(x)
2957 +#include <linux/netfilter_ipv4/lockhelp.h>
2958 +#include <linux/netfilter_ipv4/listhelp.h>
2960 +#include <linux/netfilter_ipv4/ip_tables.h>
2961 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2963 +/* FIXME: this is just for IP_NF_ASSERRT */
2964 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2966 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2968 +MODULE_LICENSE("GPL");
2969 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2970 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2972 +/* need to declare this at the top */
2973 +static struct proc_dir_entry *dstlimit_procdir;
2974 +static struct file_operations dl_file_ops;
2976 +/* hash table crap */
2978 +struct dsthash_dst {
2984 +struct dsthash_ent {
2985 + /* static / read-only parts in the beginning */
2986 + struct list_head list;
2987 + struct dsthash_dst dst;
2989 + /* modified structure members in the end */
2990 + unsigned long expires; /* precalculated expiry time */
2992 + unsigned long prev; /* last modification */
2994 + u_int32_t credit_cap, cost;
2998 +struct ipt_dstlimit_htable {
2999 + struct list_head list; /* global list of all htables */
3002 + struct dstlimit_cfg cfg; /* config */
3004 + /* used internally */
3005 + spinlock_t lock; /* lock for list_head */
3006 + u_int32_t rnd; /* random seed for hash */
3007 + struct timer_list timer; /* timer for gc */
3008 + atomic_t count; /* number entries in table */
3010 + /* seq_file stuff */
3011 + struct proc_dir_entry *pde;
3013 + struct list_head hash[0]; /* hashtable itself */
3016 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
3017 +static LIST_HEAD(dstlimit_htables);
3018 +static kmem_cache_t *dstlimit_cachep;
3020 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
3022 + return (ent->dst.dst_ip == b->dst_ip
3023 + && ent->dst.port == b->port
3024 + && ent->dst.src_ip == b->src_ip);
3027 +static inline u_int32_t
3028 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
3030 + return (jhash_3words(dst->dst_ip, dst->port,
3031 + dst->src_ip, ht->rnd) % ht->cfg.size);
3034 +static inline struct dsthash_ent *
3035 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
3037 + struct dsthash_ent *ent;
3038 + u_int32_t hash = hash_dst(ht, dst);
3039 + MUST_BE_LOCKED(&ht->lock);
3040 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
3044 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
3045 +static struct dsthash_ent *
3046 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
3048 + struct dsthash_ent *ent;
3050 + /* initialize hash with random val at the time we allocate
3051 + * the first hashtable entry */
3053 + get_random_bytes(&ht->rnd, 4);
3055 + if (ht->cfg.max &&
3056 + atomic_read(&ht->count) >= ht->cfg.max) {
3057 + /* FIXME: do something. question is what.. */
3058 + if (net_ratelimit())
3059 + printk(KERN_WARNING
3060 + "ipt_dstlimit: max count of %u reached\n",
3065 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
3067 + if (net_ratelimit())
3069 + "ipt_dstlimit: can't allocate dsthash_ent\n");
3073 + atomic_inc(&ht->count);
3075 + ent->dst.dst_ip = dst->dst_ip;
3076 + ent->dst.port = dst->port;
3077 + ent->dst.src_ip = dst->src_ip;
3079 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
3085 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
3087 + MUST_BE_LOCKED(&ht->lock);
3089 + list_del(&ent->list);
3090 + kmem_cache_free(dstlimit_cachep, ent);
3091 + atomic_dec(&ht->count);
3093 +static void htable_gc(unsigned long htlong);
3095 +static int htable_create(struct ipt_dstlimit_info *minfo)
3098 + unsigned int size;
3099 + struct ipt_dstlimit_htable *hinfo;
3101 + if (minfo->cfg.size)
3102 + size = minfo->cfg.size;
3104 + size = (((num_physpages << PAGE_SHIFT) / 16384)
3105 + / sizeof(struct list_head));
3106 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
3111 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
3112 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
3113 + + (sizeof(struct list_head) * size));
3115 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
3118 + minfo->hinfo = hinfo;
3120 + /* copy match config into hashtable config */
3121 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
3122 + hinfo->cfg.size = size;
3123 + if (!hinfo->cfg.max)
3124 + hinfo->cfg.max = 8 * hinfo->cfg.size;
3125 + else if (hinfo->cfg.max < hinfo->cfg.size)
3126 + hinfo->cfg.max = hinfo->cfg.size;
3128 + for (i = 0; i < hinfo->cfg.size; i++)
3129 + INIT_LIST_HEAD(&hinfo->hash[i]);
3131 + atomic_set(&hinfo->count, 0);
3132 + atomic_set(&hinfo->use, 1);
3134 + hinfo->lock = SPIN_LOCK_UNLOCKED;
3135 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
3136 + if (!hinfo->pde) {
3140 + hinfo->pde->proc_fops = &dl_file_ops;
3141 + hinfo->pde->data = hinfo;
3143 + init_timer(&hinfo->timer);
3144 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
3145 + hinfo->timer.data = (unsigned long )hinfo;
3146 + hinfo->timer.function = htable_gc;
3147 + add_timer(&hinfo->timer);
3149 + WRITE_LOCK(&dstlimit_lock);
3150 + list_add(&hinfo->list, &dstlimit_htables);
3151 + WRITE_UNLOCK(&dstlimit_lock);
3156 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
3161 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
3163 + return (jiffies >= he->expires);
3166 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
3167 + int (*select)(struct ipt_dstlimit_htable *ht,
3168 + struct dsthash_ent *he))
3172 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
3174 + /* lock hash table and iterate over it */
3175 + LOCK_BH(&ht->lock);
3176 + for (i = 0; i < ht->cfg.size; i++) {
3177 + struct dsthash_ent *dh, *n;
3178 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
3179 + if ((*select)(ht, dh))
3180 + __dsthash_free(ht, dh);
3183 + UNLOCK_BH(&ht->lock);
3186 +/* hash table garbage collector, run by timer */
3187 +static void htable_gc(unsigned long htlong)
3189 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
3191 + htable_selective_cleanup(ht, select_gc);
3193 + /* re-add the timer accordingly */
3194 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
3195 + add_timer(&ht->timer);
3198 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
3200 + /* remove timer, if it is pending */
3201 + if (timer_pending(&hinfo->timer))
3202 + del_timer(&hinfo->timer);
3204 + /* remove proc entry */
3205 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
3207 + htable_selective_cleanup(hinfo, select_all);
3211 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
3213 + struct ipt_dstlimit_htable *hinfo;
3215 + READ_LOCK(&dstlimit_lock);
3216 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
3217 + if (!strcmp(name, hinfo->pde->name)) {
3218 + atomic_inc(&hinfo->use);
3219 + READ_UNLOCK(&dstlimit_lock);
3223 + READ_UNLOCK(&dstlimit_lock);
3228 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
3230 + if (atomic_dec_and_test(&hinfo->use)) {
3231 + WRITE_LOCK(&dstlimit_lock);
3232 + list_del(&hinfo->list);
3233 + WRITE_UNLOCK(&dstlimit_lock);
3234 + htable_destroy(hinfo);
3239 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
3240 + * see net/sched/sch_tbf.c in the linux source tree
3243 +/* Rusty: This is my (non-mathematically-inclined) understanding of
3244 + this algorithm. The `average rate' in jiffies becomes your initial
3245 + amount of credit `credit' and the most credit you can ever have
3246 + `credit_cap'. The `peak rate' becomes the cost of passing the
3249 + `prev' tracks the last packet hit: you gain one credit per jiffy.
3250 + If you get credit balance more than this, the extra credit is
3251 + discarded. Every time the match passes, you lose `cost' credits;
3252 + if you don't have that many, the test fails.
3254 + See Alexey's formal explanation in net/sched/sch_tbf.c.
3256 + To get the maximum range, we multiply by this factor (ie. you get N
3257 + credits per jiffy). We want to allow a rate as low as 1 per day
3258 + (slowest userspace tool allows), which means
3259 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
3261 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
3263 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
3264 + * us the power of 2 below the theoretical max, so GCC simply does a
3266 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
3267 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
3268 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
3269 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
3270 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
3271 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
3273 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
3275 +/* Precision saver. */
3276 +static inline u_int32_t
3277 +user2credits(u_int32_t user)
3279 + /* If multiplying would overflow... */
3280 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
3281 + /* Divide first. */
3282 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
3284 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
3287 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
3289 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
3290 + * CREDITS_PER_JIFFY;
3291 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
3292 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
3296 +dstlimit_match(const struct sk_buff *skb,
3297 + const struct net_device *in,
3298 + const struct net_device *out,
3299 + const void *matchinfo,
3303 + struct ipt_dstlimit_info *r =
3304 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
3305 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
3306 + unsigned long now = jiffies;
3307 + struct dsthash_ent *dh;
3308 + struct dsthash_dst dst;
3310 + memset(&dst, 0, sizeof(dst));
3312 + /* dest ip is always in hash */
3313 + dst.dst_ip = skb->nh.iph->daddr;
3315 + /* source ip only if respective hashmode, otherwise set to
3317 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
3318 + dst.src_ip = skb->nh.iph->saddr;
3320 + /* dest port only if respective mode */
3321 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
3324 + /* Must not be a fragment. */
3328 + /* Must be big enough to read ports (both UDP and TCP have
3329 + them at the start). */
3330 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
3331 + /* We've been asked to examine this packet, and we
3332 + can't. Hence, no choice but to drop. */
3337 + switch (skb->nh.iph->protocol) {
3338 + struct tcphdr *th;
3339 + struct udphdr *uh;
3341 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
3342 + dst.port = th->dest;
3345 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
3346 + dst.port = uh->dest;
3353 + LOCK_BH(&hinfo->lock);
3354 + dh = __dsthash_find(hinfo, &dst);
3356 + dh = __dsthash_alloc_init(hinfo, &dst);
3359 + /* enomem... don't match == DROP */
3360 + if (net_ratelimit())
3361 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
3362 + UNLOCK_BH(&hinfo->lock);
3366 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
3368 + dh->rateinfo.prev = jiffies;
3369 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
3370 + hinfo->cfg.burst);
3371 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
3372 + hinfo->cfg.burst);
3373 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
3375 + UNLOCK_BH(&hinfo->lock);
3379 + /* update expiration timeout */
3380 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
3382 + rateinfo_recalc(dh, now);
3383 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
3384 + /* We're underlimit. */
3385 + dh->rateinfo.credit -= dh->rateinfo.cost;
3386 + UNLOCK_BH(&hinfo->lock);
3390 + UNLOCK_BH(&hinfo->lock);
3392 + /* default case: we're overlimit, thus don't match */
3397 +dstlimit_checkentry(const char *tablename,
3398 + const struct ipt_ip *ip,
3400 + unsigned int matchsize,
3401 + unsigned int hook_mask)
3403 + struct ipt_dstlimit_info *r = matchinfo;
3405 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
3408 + /* Check for overflow. */
3409 + if (r->cfg.burst == 0
3410 + || user2credits(r->cfg.avg * r->cfg.burst) <
3411 + user2credits(r->cfg.avg)) {
3412 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
3413 + r->cfg.avg, r->cfg.burst);
3417 + if (r->cfg.mode == 0
3418 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
3419 + |IPT_DSTLIMIT_HASH_DIP
3420 + |IPT_DSTLIMIT_HASH_SIP))
3423 + if (!r->cfg.gc_interval)
3426 + if (!r->cfg.expire)
3429 + r->hinfo = htable_find_get(r->name);
3430 + if (!r->hinfo && (htable_create(r) != 0)) {
3434 + /* Ugly hack: For SMP, we only want to use one set */
3441 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
3443 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
3445 + htable_put(r->hinfo);
3448 +static struct ipt_match ipt_dstlimit = {
3449 + .list = { .prev = NULL, .next = NULL },
3450 + .name = "dstlimit",
3451 + .match = dstlimit_match,
3452 + .checkentry = dstlimit_checkentry,
3453 + .destroy = dstlimit_destroy,
3459 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
3461 + struct proc_dir_entry *pde = s->private;
3462 + struct ipt_dstlimit_htable *htable = pde->data;
3463 + unsigned int *bucket;
3465 + LOCK_BH(&htable->lock);
3466 + if (*pos >= htable->cfg.size)
3469 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
3471 + return ERR_PTR(-ENOMEM);
3477 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
3479 + struct proc_dir_entry *pde = s->private;
3480 + struct ipt_dstlimit_htable *htable = pde->data;
3481 + unsigned int *bucket = (unsigned int *)v;
3483 + *pos = ++(*bucket);
3484 + if (*pos >= htable->cfg.size) {
3491 +static void dl_seq_stop(struct seq_file *s, void *v)
3493 + struct proc_dir_entry *pde = s->private;
3494 + struct ipt_dstlimit_htable *htable = pde->data;
3495 + unsigned int *bucket = (unsigned int *)v;
3499 + UNLOCK_BH(&htable->lock);
3502 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
3504 + /* recalculate to show accurate numbers */
3505 + rateinfo_recalc(ent, jiffies);
3507 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
3508 + (ent->expires - jiffies)/HZ,
3509 + NIPQUAD(ent->dst.src_ip),
3510 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
3511 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
3512 + ent->rateinfo.cost);
3515 +static int dl_seq_show(struct seq_file *s, void *v)
3517 + struct proc_dir_entry *pde = s->private;
3518 + struct ipt_dstlimit_htable *htable = pde->data;
3519 + unsigned int *bucket = (unsigned int *)v;
3521 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
3522 + struct dsthash_ent *, s)) {
3523 + /* buffer was filled and unable to print that tuple */
3529 +static struct seq_operations dl_seq_ops = {
3530 + .start = dl_seq_start,
3531 + .next = dl_seq_next,
3532 + .stop = dl_seq_stop,
3533 + .show = dl_seq_show
3536 +static int dl_proc_open(struct inode *inode, struct file *file)
3538 + int ret = seq_open(file, &dl_seq_ops);
3541 + struct seq_file *sf = file->private_data;
3542 + sf->private = PDE(inode);
3547 +static struct file_operations dl_file_ops = {
3548 + .owner = THIS_MODULE,
3549 + .open = dl_proc_open,
3551 + .llseek = seq_lseek,
3552 + .release = seq_release
3555 +static int init_or_fini(int fini)
3562 + if (ipt_register_match(&ipt_dstlimit)) {
3564 + goto cleanup_nothing;
3567 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
3568 + * quite small ? */
3569 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
3570 + sizeof(struct dsthash_ent), 0,
3571 + SLAB_HWCACHE_ALIGN, NULL, NULL);
3572 + if (!dstlimit_cachep) {
3573 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
3575 + goto cleanup_unreg_match;
3578 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
3579 + if (!dstlimit_procdir) {
3580 + printk(KERN_ERR "Unable to create proc dir entry\n");
3582 + goto cleanup_free_slab;
3588 + remove_proc_entry("ipt_dstlimit", proc_net);
3590 + kmem_cache_destroy(dstlimit_cachep);
3591 +cleanup_unreg_match:
3592 + ipt_unregister_match(&ipt_dstlimit);
3598 +static int __init init(void)
3600 + return init_or_fini(0);
3603 +static void __exit fini(void)
3610 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c
3611 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
3612 +++ linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c 2004-09-07 12:33:12.080715088 +0200
3615 + * This module implements a simple TSK FLC
3616 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
3617 + * to limit , in an adaptive and flexible way , the packet rate crossing
3618 + * a given stream . It serves as an initial and very simple (but effective)
3619 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
3620 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
3621 + * into our code in a precise , adaptive and efficient manner.
3622 + * The goal is very similar to that of "limit" match , but using techniques of
3623 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
3624 + * avoiding over and undershoots - and stuff like that .
3627 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
3628 + * 2002-08-17 : Changed to eliminate floating point operations .
3629 + * 2002-08-23 : Coding style changes .
3632 +#include <linux/module.h>
3633 +#include <linux/skbuff.h>
3634 +#include <linux/ip.h>
3635 +#include <linux/random.h>
3636 +#include <net/tcp.h>
3637 +#include <linux/spinlock.h>
3638 +#include <linux/netfilter_ipv4/ip_tables.h>
3639 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
3642 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
3643 + Expressed in percentage
3646 +#define PAR_LOW 1/100
3649 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
3651 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
3652 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
3653 +MODULE_LICENSE("GPL");
3655 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3663 + return ( (100*(tx-mini)) / (maxi-mini) );
3666 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3674 + return ( (100*( maxi - tx )) / ( maxi - mini ) );
3678 +ipt_fuzzy_match(const struct sk_buff *pskb,
3679 + const struct net_device *in,
3680 + const struct net_device *out,
3681 + const void *matchinfo,
3685 + /* From userspace */
3687 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
3689 + u_int8_t random_number;
3690 + unsigned long amount;
3691 + u_int8_t howhigh, howlow;
3694 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
3696 + info->bytes_total += pskb->len;
3697 + info->packets_total++;
3699 + info->present_time = jiffies;
3701 + if (info->present_time >= info->previous_time)
3702 + amount = info->present_time - info->previous_time;
3704 + /* There was a transition : I choose to re-sample
3705 + and keep the old acceptance rate...
3709 + info->previous_time = info->present_time;
3710 + info->bytes_total = info->packets_total = 0;
3713 + if (amount > HZ/10) /* More than 100 ms elapsed ... */
3716 + info->mean_rate = (u_int32_t) ((HZ*info->packets_total) \
3719 + info->previous_time = info->present_time;
3720 + info->bytes_total = info->packets_total = 0;
3722 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
3723 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
3725 + info->acceptance_rate = (u_int8_t) \
3726 + (howhigh*PAR_LOW + PAR_HIGH*howlow);
3728 + /* In fact , the above defuzzification would require a denominator
3729 + proportional to (howhigh+howlow) but , in this particular case ,
3730 + that expression is constant .
3731 + An imediate consequence is that it isn't necessary to call
3732 + both mf_high and mf_low - but to keep things understandable ,
3737 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
3740 + if ( info->acceptance_rate < 100 )
3742 + get_random_bytes((void *)(&random_number), 1);
3744 + /* If within the acceptance , it can pass => don't match */
3745 + if (random_number <= (255 * info->acceptance_rate) / 100)
3748 + return 1; /* It can't pass ( It matches ) */
3751 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
3756 +ipt_fuzzy_checkentry(const char *tablename,
3757 + const struct ipt_ip *e,
3759 + unsigned int matchsize,
3760 + unsigned int hook_mask)
3763 + const struct ipt_fuzzy_info *info = matchinfo;
3765 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
3766 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
3767 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
3771 + if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
3772 + || (info->minimum_rate >= info->maximum_rate )) {
3773 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
3780 +static struct ipt_match ipt_fuzzy_reg = {
3782 + .match = ipt_fuzzy_match,
3783 + .checkentry = ipt_fuzzy_checkentry,
3787 +static int __init init(void)
3789 + return ipt_register_match(&ipt_fuzzy_reg);
3792 +static void __exit fini(void)
3794 + ipt_unregister_match(&ipt_fuzzy_reg);
3799 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c
3800 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
3801 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c 2004-09-07 12:33:15.334220480 +0200
3804 + This is a module which is used to match ipv4 options.
3805 + This file is distributed under the terms of the GNU General Public
3806 + License (GPL). Copies of the GPL can be obtained from:
3807 + ftp://prep.ai.mit.edu/pub/gnu/GPL
3809 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
3810 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
3811 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
3812 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
3813 + 19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
3816 +#include <linux/module.h>
3817 +#include <linux/skbuff.h>
3818 +#include <net/ip.h>
3820 +#include <linux/netfilter_ipv4/ip_tables.h>
3821 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
3823 +MODULE_LICENSE("GPL");
3824 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3827 +match(const struct sk_buff *skb,
3828 + const struct net_device *in,
3829 + const struct net_device *out,
3830 + const void *matchinfo,
3834 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
3835 + const struct iphdr *iph = skb->nh.iph;
3836 + const struct ip_options *opt;
3838 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
3839 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
3841 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
3842 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3843 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3844 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3845 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3846 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
3851 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
3852 + /* there are options, and we don't need to care which one */
3855 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
3856 + /* there are options but we don't want any ! */
3861 + opt = &(IPCB(skb)->opt);
3863 + /* source routing */
3864 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
3865 + if (!((opt->srr) & (opt->is_strictroute)))
3868 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
3869 + if (!((opt->srr) & (!opt->is_strictroute)))
3872 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
3876 + /* record route */
3877 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
3881 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
3886 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
3890 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3894 + /* router-alert option */
3895 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3896 + if (!opt->router_alert)
3899 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3900 + if (opt->router_alert)
3909 +checkentry(const char *tablename,
3910 + const struct ipt_ip *ip,
3912 + unsigned int matchsize,
3913 + unsigned int hook_mask)
3915 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
3916 + /* Check the size */
3917 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
3919 + /* Now check the coherence of the data ... */
3920 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
3921 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
3922 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
3923 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
3924 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
3925 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
3926 + return 0; /* opposites */
3927 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
3928 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3929 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3930 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3931 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3932 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
3933 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
3934 + return 0; /* opposites */
3935 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
3936 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
3937 + return 0; /* cannot match in the same time loose and strict source routing */
3938 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3939 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
3940 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
3941 + return 0; /* opposites */
3942 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
3943 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
3944 + return 0; /* opposites */
3945 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
3946 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
3947 + return 0; /* opposites */
3948 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
3949 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
3950 + return 0; /* opposites */
3952 + /* everything looks ok. */
3956 +static struct ipt_match ipv4options_match = {
3957 + .name = "ipv4options",
3959 + .checkentry = checkentry,
3963 +static int __init init(void)
3965 + return ipt_register_match(&ipv4options_match);
3968 +static void __exit fini(void)
3970 + ipt_unregister_match(&ipv4options_match);
3975 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.7/net/ipv4/netfilter/ipt_mport.c
3976 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
3977 +++ linux-2.6.7/net/ipv4/netfilter/ipt_mport.c 2004-09-07 12:33:16.384060880 +0200
3979 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
3980 + the same place so we can treat them as equal. */
3981 +#include <linux/module.h>
3982 +#include <linux/types.h>
3983 +#include <linux/udp.h>
3984 +#include <linux/skbuff.h>
3986 +#include <linux/netfilter_ipv4/ipt_mport.h>
3987 +#include <linux/netfilter_ipv4/ip_tables.h>
3989 +MODULE_LICENSE("GPL");
3992 +#define duprintf(format, args...) printk(format , ## args)
3994 +#define duprintf(format, args...)
3997 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3999 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
4003 + u_int16_t pflags = minfo->pflags;
4004 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
4008 + && minfo->ports[i] == 65535)
4011 + s = minfo->ports[i];
4014 + e = minfo->ports[++i];
4019 + if (minfo->flags & IPT_MPORT_SOURCE
4020 + && src >= s && src <= e)
4023 + if (minfo->flags & IPT_MPORT_DESTINATION
4024 + && dst >= s && dst <= e)
4032 +match(const struct sk_buff *skb,
4033 + const struct net_device *in,
4034 + const struct net_device *out,
4035 + const void *matchinfo,
4040 + const struct ipt_mport *minfo = matchinfo;
4045 + /* Must be big enough to read ports (both UDP and TCP have
4046 + them at the start). */
4047 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
4048 + /* We've been asked to examine this packet, and we
4049 + can't. Hence, no choice but to drop. */
4050 + duprintf("ipt_multiport:"
4051 + " Dropping evil offset=0 tinygram.\n");
4056 + return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
4059 +/* Called when user tries to insert an entry of this type. */
4061 +checkentry(const char *tablename,
4062 + const struct ipt_ip *ip,
4064 + unsigned int matchsize,
4065 + unsigned int hook_mask)
4067 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
4070 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
4071 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
4072 + && !(ip->invflags & IPT_INV_PROTO)
4073 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
4076 +static struct ipt_match mport_match = {
4079 + .checkentry = &checkentry,
4083 +static int __init init(void)
4085 + return ipt_register_match(&mport_match);
4088 +static void __exit fini(void)
4090 + ipt_unregister_match(&mport_match);
4095 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.7/net/ipv4/netfilter/ipt_nth.c
4096 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
4097 +++ linux-2.6.7/net/ipv4/netfilter/ipt_nth.c 2004-09-07 12:33:17.547883952 +0200
4100 + This is a module which is used for match support for every Nth packet
4101 + This file is distributed under the terms of the GNU General Public
4102 + License (GPL). Copies of the GPL can be obtained from:
4103 + ftp://prep.ai.mit.edu/pub/gnu/GPL
4105 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
4106 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
4107 + * added support for multiple counters
4108 + * added support for matching on individual packets
4109 + in the counter cycle
4110 + 2004-02-19 Harald Welte <laforge@netfilter.org>
4115 +#include <linux/module.h>
4116 +#include <linux/skbuff.h>
4117 +#include <linux/ip.h>
4118 +#include <net/tcp.h>
4119 +#include <linux/spinlock.h>
4120 +#include <linux/netfilter_ipv4/ip_tables.h>
4121 +#include <linux/netfilter_ipv4/ipt_nth.h>
4123 +MODULE_LICENSE("GPL");
4124 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
4127 + * State information.
4134 +static struct state states[IPT_NTH_NUM_COUNTERS];
4137 +ipt_nth_match(const struct sk_buff *pskb,
4138 + const struct net_device *in,
4139 + const struct net_device *out,
4140 + const void *matchinfo,
4144 + /* Parameters from userspace */
4145 + const struct ipt_nth_info *info = matchinfo;
4146 + unsigned counter = info->counter;
4147 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
4149 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
4153 + spin_lock(&states[counter].lock);
4155 + /* Are we matching every nth packet?*/
4156 + if (info->packet == 0xFF)
4158 + /* We're matching every nth packet and only every nth packet*/
4159 + /* Do we match or invert match? */
4160 + if (info->not == 0)
4162 + if (states[counter].number == 0)
4164 + ++states[counter].number;
4167 + if (states[counter].number >= info->every)
4168 + states[counter].number = 0; /* reset the counter */
4170 + ++states[counter].number;
4175 + if (states[counter].number == 0)
4177 + ++states[counter].number;
4180 + if (states[counter].number >= info->every)
4181 + states[counter].number = 0;
4183 + ++states[counter].number;
4189 + /* We're using the --packet, so there must be a rule for every value */
4190 + if (states[counter].number == info->packet)
4192 + /* only increment the counter when a match happens */
4193 + if (states[counter].number >= info->every)
4194 + states[counter].number = 0; /* reset the counter */
4196 + ++states[counter].number;
4205 + spin_unlock(&states[counter].lock);
4209 + spin_unlock(&states[counter].lock);
4214 +ipt_nth_checkentry(const char *tablename,
4215 + const struct ipt_ip *e,
4217 + unsigned int matchsize,
4218 + unsigned int hook_mask)
4220 + /* Parameters from userspace */
4221 + const struct ipt_nth_info *info = matchinfo;
4222 + unsigned counter = info->counter;
4223 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
4225 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
4229 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
4230 + printk("nth: matchsize %u != %u\n", matchsize,
4231 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
4235 + states[counter].number = info->startat;
4240 +static struct ipt_match ipt_nth_reg = {
4242 + .match = ipt_nth_match,
4243 + .checkentry = ipt_nth_checkentry,
4247 +static int __init init(void)
4251 + memset(&states, 0, sizeof(states));
4252 + for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
4253 + spin_lock_init(&(states[counter].lock));
4255 + return ipt_register_match(&ipt_nth_reg);
4258 +static void __exit fini(void)
4260 + ipt_unregister_match(&ipt_nth_reg);
4265 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.7/net/ipv4/netfilter/ipt_osf.c
4266 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
4267 +++ linux-2.6.7/net/ipv4/netfilter/ipt_osf.c 2004-09-07 12:33:18.674712648 +0200
4272 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
4275 + * This program is free software; you can redistribute it and/or modify
4276 + * it under the terms of the GNU General Public License as published by
4277 + * the Free Software Foundation; either version 2 of the License, or
4278 + * (at your option) any later version.
4280 + * This program is distributed in the hope that it will be useful,
4281 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4282 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4283 + * GNU General Public License for more details.
4285 + * You should have received a copy of the GNU General Public License
4286 + * along with this program; if not, write to the Free Software
4287 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4291 + * OS fingerprint matching module.
4292 + * It simply compares various parameters from SYN packet with
4293 + * some hardcoded ones.
4295 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
4299 +#include <linux/config.h>
4300 +#include <linux/kernel.h>
4301 +#include <linux/types.h>
4302 +#include <linux/string.h>
4303 +#include <linux/smp.h>
4304 +#include <linux/module.h>
4305 +#include <linux/skbuff.h>
4306 +#include <linux/file.h>
4307 +#include <linux/ip.h>
4308 +#include <linux/proc_fs.h>
4309 +#include <linux/fs.h>
4310 +#include <linux/slab.h>
4311 +#include <linux/spinlock.h>
4312 +#include <linux/ctype.h>
4313 +#include <linux/list.h>
4314 +#include <linux/if.h>
4316 +#include <net/sock.h>
4317 +#include <net/ip.h>
4319 +#include <linux/netfilter_ipv4/ip_tables.h>
4321 +#include <linux/netfilter_ipv4/ipt_osf.h>
4326 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
4327 +#define loga(x...) printk(x)
4329 +#define log(x...) do {} while(0)
4330 +#define loga(x...) do {} while(0)
4333 +#define FMATCH_WRONG 0
4334 +#define FMATCH_OK 1
4335 +#define FMATCH_OPT_WRONG 2
4338 +#define OSFPDEL ':'
4339 +#define MAXOPTSTRLEN 128
4340 +#define OSFFLUSH "FLUSH"
4342 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
4343 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
4344 +static struct list_head finger_list;
4345 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
4346 + const void *, int,
4348 +static int checkentry(const char *, const struct ipt_ip *, void *,
4349 + unsigned int, unsigned int);
4351 +static unsigned long seq, ipt_osf_groups = 1;
4352 +static struct sock *nts;
4354 +static struct ipt_match osf_match =
4364 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
4366 + unsigned int size;
4367 + struct sk_buff *skb;
4368 + struct ipt_osf_nlmsg *data;
4369 + struct nlmsghdr *nlh;
4371 + size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
4373 + skb = alloc_skb(size, GFP_ATOMIC);
4376 + log("skb_alloc() failed.\n");
4380 + nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
4382 + data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
4384 + memcpy(&data->f, f, sizeof(struct osf_finger));
4385 + memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
4386 + memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
4388 + NETLINK_CB(skb).dst_groups = ipt_osf_groups;
4389 + netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
4395 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
4397 + struct iphdr *ip = skb->nh.iph;
4399 + if (flags & IPT_OSF_SMART)
4401 + struct in_device *in_dev = in_dev_get(skb->dev);
4405 + if (inet_ifa_match(ip->saddr, ifa))
4407 + in_dev_put(in_dev);
4408 + return (ip->ttl == f_ttl);
4411 + endfor_ifa(in_dev);
4413 + in_dev_put(in_dev);
4414 + return (ip->ttl <= f_ttl);
4417 + return (ip->ttl == f_ttl);
4421 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
4422 + const void *matchinfo, int offset,
4425 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
4426 + struct iphdr *ip = skb->nh.iph;
4427 + struct tcphdr *tcp;
4428 + int fmatch = FMATCH_WRONG, fcount = 0;
4429 + unsigned long totlen, optsize = 0, window;
4430 + unsigned char df, *optp = NULL, *_optp = NULL;
4431 + char check_WSS = 0;
4432 + struct list_head *ent;
4433 + struct osf_finger *f;
4438 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
4443 + totlen = ntohs(ip->tot_len);
4444 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
4445 + window = ntohs(tcp->window);
4447 + if (tcp->doff*4 > sizeof(struct tcphdr))
4449 + _optp = optp = (char *)(tcp+1);
4450 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
4453 + /* Actually we can create hash/table of all genres and search
4454 + * only in appropriate part, but here is initial variant,
4455 + * so will use slow path.
4457 + read_lock(&osf_lock);
4458 + list_for_each(ent, &finger_list)
4460 + f = list_entry(ent, struct osf_finger, flist);
4462 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
4466 + fmatch = FMATCH_WRONG;
4468 + if (totlen == f->ss && df == f->df &&
4469 + smart_dec(skb, info->flags, f->ttl))
4471 + unsigned long foptsize;
4473 + unsigned short mss = 0;
4477 + switch (f->wss.wc)
4479 + case 0: check_WSS = 0; break;
4480 + case 'S': check_WSS = 1; break;
4481 + case 'T': check_WSS = 2; break;
4482 + case '%': check_WSS = 3; break;
4483 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
4484 + f->wss.wc, f->genre, f->details);
4488 + if (check_WSS == 4)
4491 + /* Check options */
4494 + for (optnum=0; optnum<f->opt_num; ++optnum)
4495 + foptsize += f->opt[optnum].length;
4498 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
4503 + fmatch = FMATCH_OK;
4504 + loga("\tYEP : matching without options.\n");
4505 + if ((info->flags & IPT_OSF_LOG) &&
4506 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
4513 + for (optnum=0; optnum<f->opt_num; ++optnum)
4515 + if (f->opt[optnum].kind == (*optp))
4517 + unsigned char len = f->opt[optnum].length;
4518 + unsigned char *optend = optp + len;
4519 + int loop_cont = 0;
4521 + fmatch = FMATCH_OK;
4527 + mss = ntohs(*(unsigned short *)(optp+2));
4542 + /* Skip kind and length fields*/
4545 + if (f->opt[optnum].wc.val != 0)
4547 + unsigned long tmp = 0;
4549 + /* Hmmm... It looks a bit ugly. :) */
4550 + memcpy(&tmp, optp,
4551 + (len > sizeof(unsigned long)?
4552 + sizeof(unsigned long):len));
4553 + /* 2 + 2: optlen(2 bytes) +
4554 + * kind(1 byte) + length(1 byte) */
4560 + if (f->opt[optnum].wc.wc == '%')
4562 + if ((tmp % f->opt[optnum].wc.val) != 0)
4563 + fmatch = FMATCH_OPT_WRONG;
4565 + else if (tmp != f->opt[optnum].wc.val)
4566 + fmatch = FMATCH_OPT_WRONG;
4573 + fmatch = FMATCH_OPT_WRONG;
4575 + if (fmatch != FMATCH_OK)
4579 + if (fmatch != FMATCH_OPT_WRONG)
4581 + fmatch = FMATCH_WRONG;
4583 + switch (check_WSS)
4586 + if (f->wss.val == 0 || window == f->wss.val)
4587 + fmatch = FMATCH_OK;
4590 +/* Lurked in OpenBSD */
4591 +#define SMART_MSS 1460
4592 + if (window == f->wss.val*mss ||
4593 + window == f->wss.val*SMART_MSS)
4594 + fmatch = FMATCH_OK;
4597 + if (window == f->wss.val*(mss+40) ||
4598 + window == f->wss.val*(SMART_MSS+40))
4599 + fmatch = FMATCH_OK;
4602 + if ((window % f->wss.val) == 0)
4603 + fmatch = FMATCH_OK;
4609 + if (fmatch == FMATCH_OK)
4612 + log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n",
4613 + f->genre, f->version,
4614 + f->subtype, f->details,
4615 + NIPQUAD(ip->saddr), ntohs(tcp->source),
4616 + NIPQUAD(ip->daddr), ntohs(tcp->dest),
4617 + f->ttl - ip->ttl);
4618 + if (info->flags & IPT_OSF_NETLINK)
4620 + spin_lock_bh(&ipt_osf_netlink_lock);
4621 + ipt_osf_nlsend(f, skb);
4622 + spin_unlock_bh(&ipt_osf_netlink_lock);
4624 + if ((info->flags & IPT_OSF_LOG) &&
4625 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
4630 + if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
4632 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
4633 + unsigned int i, optsize;
4634 + struct osf_finger fg;
4636 + memset(&fg, 0, sizeof(fg));
4638 + if ((info->flags & IPT_OSF_LOG))
4639 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
4642 + optsize = tcp->doff * 4 - sizeof(struct tcphdr);
4643 + if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
4644 + opt, optsize) < 0)
4646 + if (info->flags & IPT_OSF_LOG)
4647 + loga("TRUNCATED");
4648 + if (info->flags & IPT_OSF_NETLINK)
4649 + strcpy(fg.details, "TRUNCATED");
4653 + for (i = 0; i < optsize; i++)
4655 + if (info->flags & IPT_OSF_LOG)
4656 + loga("%02X", opt[i]);
4658 + if (info->flags & IPT_OSF_NETLINK)
4659 + memcpy(fg.details, opt, MAXDETLEN);
4662 + if ((info->flags & IPT_OSF_LOG))
4663 + loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
4664 + NIPQUAD(ip->saddr), ntohs(tcp->source),
4665 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
4667 + if (info->flags & IPT_OSF_NETLINK)
4669 + fg.wss.val = window;
4673 + strncpy(fg.genre, "Unknown", MAXGENRELEN);
4675 + spin_lock_bh(&ipt_osf_netlink_lock);
4676 + ipt_osf_nlsend(&fg, skb);
4677 + spin_unlock_bh(&ipt_osf_netlink_lock);
4681 + read_unlock(&osf_lock);
4684 + fmatch = FMATCH_OK;
4686 + return (fmatch == FMATCH_OK)?1:0;
4690 +checkentry(const char *tablename,
4691 + const struct ipt_ip *ip,
4693 + unsigned int matchsize,
4694 + unsigned int hook_mask)
4696 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
4698 + if (ip->proto != IPPROTO_TCP)
4704 +static char * osf_strchr(char *ptr, char c)
4708 + tmp = strchr(ptr, c);
4710 + while (tmp && tmp+1 && isspace(*(tmp+1)))
4716 +static struct osf_finger * finger_alloc(void)
4718 + struct osf_finger *f;
4720 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
4722 + memset(f, 0, sizeof(struct osf_finger));
4727 +static void finger_free(struct osf_finger *f)
4729 + memset(f, 0, sizeof(struct osf_finger));
4734 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
4738 + unsigned long val;
4742 + while (ptr != NULL && i < olen)
4751 + ptr = osf_strchr(&obuf[i], OPTDEL);
4756 + i += (int)(ptr-&obuf[i]);
4763 + op = OSFOPT_SACKP;
4764 + ptr = osf_strchr(&obuf[i], OPTDEL);
4769 + i += (int)(ptr-&obuf[i]);
4777 + ptr = osf_strchr(&obuf[i], OPTDEL);
4782 + i += (int)(ptr-&obuf[i]);
4790 + ptr = osf_strchr(&obuf[i], OPTDEL);
4793 + switch (obuf[i+1])
4795 + case '%': wc = '%'; break;
4796 + case 'S': wc = 'S'; break;
4797 + case 'T': wc = 'T'; break;
4798 + default: wc = 0; break;
4804 + val = simple_strtoul(&obuf[i+2], NULL, 10);
4806 + val = simple_strtoul(&obuf[i+1], NULL, 10);
4807 + i += (int)(ptr-&obuf[i]);
4815 + ptr = osf_strchr(&obuf[i], OPTDEL);
4818 + if (obuf[i+1] == '%')
4823 + val = simple_strtoul(&obuf[i+2], NULL, 10);
4825 + val = simple_strtoul(&obuf[i+1], NULL, 10);
4826 + i += (int)(ptr-&obuf[i]);
4834 + ptr = osf_strchr(&obuf[i], OPTDEL);
4839 + i += (int)(ptr-&obuf[i]);
4846 + ptr = osf_strchr(&obuf[i], OPTDEL);
4850 + i += (int)(ptr-&obuf[i]);
4858 + opt[*optnum].kind = IANA_opts[op].kind;
4859 + opt[*optnum].length = IANA_opts[op].length;
4860 + opt[*optnum].wc.wc = wc;
4861 + opt[*optnum].wc.val = val;
4867 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
4869 + struct list_head *ent;
4870 + struct osf_finger *f = NULL;
4871 + int i, __count, err;
4877 + read_lock_bh(&osf_lock);
4878 + list_for_each(ent, &finger_list)
4880 + f = list_entry(ent, struct osf_finger, flist);
4882 + log("%s [%s]", f->genre, f->details);
4884 + err = snprintf(buf+count, __count-count, "%s - %s[%s] : %s",
4885 + f->genre, f->version,
4886 + f->subtype, f->details);
4887 + if (err == 0 || __count <= count + err)
4894 + //count += sprintf(buf+count, " OPT: ");
4895 + for (i=0; i<f->opt_num; ++i)
4897 + //count += sprintf(buf+count, "%d.%c%lu; ",
4898 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
4899 + loga("%d.%c%lu; ",
4900 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
4904 + err = snprintf(buf+count, __count-count, "\n");
4905 + if (err == 0 || __count <= count + err)
4910 + read_unlock_bh(&osf_lock);
4915 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
4919 + char obuf[MAXOPTSTRLEN];
4920 + struct osf_finger *finger;
4921 + struct list_head *ent, *n;
4923 + char *pbeg, *pend;
4925 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
4928 + write_lock_bh(&osf_lock);
4929 + list_for_each_safe(ent, n, &finger_list)
4932 + finger = list_entry(ent, struct osf_finger, flist);
4933 + list_del(&finger->flist);
4934 + finger_free(finger);
4936 + write_unlock_bh(&osf_lock);
4938 + log("Flushed %d entries.\n", i);
4945 + for (i=0; i<count && buffer[i] != '\0'; ++i)
4946 + if (buffer[i] == ':')
4949 + if (cnt != 8 || i != count)
4951 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
4956 + memset(obuf, 0, sizeof(obuf));
4958 + finger = finger_alloc();
4961 + log("Failed to allocate new fingerprint entry.\n");
4965 + pbeg = (char *)buffer;
4966 + pend = osf_strchr(pbeg, OSFPDEL);
4970 + if (pbeg[0] == 'S')
4972 + finger->wss.wc = 'S';
4973 + if (pbeg[1] == '%')
4974 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4975 + else if (pbeg[1] == '*')
4976 + finger->wss.val = 0;
4978 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4980 + else if (pbeg[0] == 'T')
4982 + finger->wss.wc = 'T';
4983 + if (pbeg[1] == '%')
4984 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4985 + else if (pbeg[1] == '*')
4986 + finger->wss.val = 0;
4988 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4990 + else if (pbeg[0] == '%')
4992 + finger->wss.wc = '%';
4993 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4995 + else if (isdigit(pbeg[0]))
4997 + finger->wss.wc = 0;
4998 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
5003 + pend = osf_strchr(pbeg, OSFPDEL);
5007 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
5010 + pend = osf_strchr(pbeg, OSFPDEL);
5014 + finger->df = simple_strtoul(pbeg, NULL, 10);
5017 + pend = osf_strchr(pbeg, OSFPDEL);
5021 + finger->ss = simple_strtoul(pbeg, NULL, 10);
5025 + pend = osf_strchr(pbeg, OSFPDEL);
5029 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
5033 + pend = osf_strchr(pbeg, OSFPDEL);
5037 + if (pbeg[0] == '@' || pbeg[0] == '*')
5038 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
5040 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
5044 + pend = osf_strchr(pbeg, OSFPDEL);
5048 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
5052 + pend = osf_strchr(pbeg, OSFPDEL);
5056 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
5060 + cnt = snprintf(finger->details,
5061 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
5064 + log("%s - %s[%s] : %s\n",
5065 + finger->genre, finger->version,
5066 + finger->subtype, finger->details);
5068 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
5071 + write_lock_bh(&osf_lock);
5072 + list_add_tail(&finger->flist, &finger_list);
5073 + write_unlock_bh(&osf_lock);
5078 +static int __init osf_init(void)
5081 + struct proc_dir_entry *p;
5083 + log("Startng OS fingerprint matching module.\n");
5085 + INIT_LIST_HEAD(&finger_list);
5087 + err = ipt_register_match(&osf_match);
5090 + log("Failed to register OS fingerprint matching module.\n");
5094 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
5097 + ipt_unregister_match(&osf_match);
5101 + p->write_proc = osf_proc_write;
5102 + p->read_proc = osf_proc_read;
5104 + nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
5107 + log("netlink_kernel_create() failed\n");
5108 + remove_proc_entry("sys/net/ipv4/osf", NULL);
5109 + ipt_unregister_match(&osf_match);
5116 +static void __exit osf_fini(void)
5118 + struct list_head *ent, *n;
5119 + struct osf_finger *f;
5121 + remove_proc_entry("sys/net/ipv4/osf", NULL);
5122 + ipt_unregister_match(&osf_match);
5123 + if (nts && nts->sk_socket)
5124 + sock_release(nts->sk_socket);
5126 + list_for_each_safe(ent, n, &finger_list)
5128 + f = list_entry(ent, struct osf_finger, flist);
5129 + list_del(&f->flist);
5133 + log("OS fingerprint matching module finished.\n");
5136 +module_init(osf_init);
5137 +module_exit(osf_fini);
5139 +MODULE_LICENSE("GPL");
5140 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
5141 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
5142 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.7/net/ipv4/netfilter/ipt_psd.c
5143 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
5144 +++ linux-2.6.7/net/ipv4/netfilter/ipt_psd.c 2004-09-07 12:33:19.724553048 +0200
5147 + This is a module which is used for PSD (portscan detection)
5148 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
5149 + and LOG target module.
5151 + Copyright (C) 2000,2001 astaro AG
5153 + This file is distributed under the terms of the GNU General Public
5154 + License (GPL). Copies of the GPL can be obtained from:
5155 + ftp://prep.ai.mit.edu/pub/gnu/GPL
5157 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
5158 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
5159 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
5160 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
5161 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
5162 + 2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
5165 +#include <linux/module.h>
5166 +#include <linux/skbuff.h>
5167 +#include <linux/ip.h>
5168 +#include <net/tcp.h>
5169 +#include <linux/spinlock.h>
5170 +#include <linux/netfilter_ipv4/ip_tables.h>
5171 +#include <linux/netfilter_ipv4/ipt_psd.h>
5174 +#define DEBUGP printk
5176 +#define DEBUGP(format, args...)
5179 +MODULE_LICENSE("GPL");
5180 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
5182 +#define HF_DADDR_CHANGING 0x01
5183 +#define HF_SPORT_CHANGING 0x02
5184 +#define HF_TOS_CHANGING 0x04
5185 +#define HF_TTL_CHANGING 0x08
5188 + * Information we keep per each target port
5191 + u_int16_t number; /* port number */
5192 + u_int8_t proto; /* protocol number */
5193 + u_int8_t and_flags; /* tcp ANDed flags */
5194 + u_int8_t or_flags; /* tcp ORed flags */
5198 + * Information we keep per each source address.
5201 + struct host *next; /* Next entry with the same hash */
5202 + clock_t timestamp; /* Last update time */
5203 + struct in_addr src_addr; /* Source address */
5204 + struct in_addr dest_addr; /* Destination address */
5205 + unsigned short src_port; /* Source port */
5206 + int count; /* Number of ports in the list */
5207 + int weight; /* Total weight of ports in the list */
5208 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
5209 + unsigned char tos; /* TOS */
5210 + unsigned char ttl; /* TTL */
5211 + unsigned char flags; /* HF_ flags bitmask */
5215 + * State information.
5219 + struct host list[LIST_SIZE]; /* List of source addresses */
5220 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
5221 + int index; /* Oldest entry to be replaced */
5225 + * Convert an IP address into a hash table index.
5227 +static inline int hashfunc(struct in_addr addr)
5229 + unsigned int value;
5232 + value = addr.s_addr;
5236 + } while ((value >>= HASH_LOG));
5238 + return hash & (HASH_SIZE - 1);
5242 +ipt_psd_match(const struct sk_buff *pskb,
5243 + const struct net_device *in,
5244 + const struct net_device *out,
5245 + const void *matchinfo,
5249 + struct iphdr *ip_hdr;
5250 + struct tcphdr *tcp_hdr;
5251 + struct in_addr addr;
5252 + u_int16_t src_port,dest_port;
5253 + u_int8_t tcp_flags, proto;
5255 + struct host *curr, *last, **head;
5256 + int hash, index, count;
5258 + /* Parameters from userspace */
5259 + const struct ipt_psd_info *psdinfo = matchinfo;
5262 + ip_hdr = pskb->nh.iph;
5264 + /* Sanity check */
5265 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
5266 + DEBUGP("PSD: sanity check failed\n");
5270 + /* TCP or UDP ? */
5271 + proto = ip_hdr->protocol;
5273 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
5274 + DEBUGP("PSD: protocol not supported\n");
5278 + /* Get the source address, source & destination ports, and TCP flags */
5280 + addr.s_addr = ip_hdr->saddr;
5282 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
5284 + /* Yep, it´s dirty */
5285 + src_port = tcp_hdr->source;
5286 + dest_port = tcp_hdr->dest;
5288 + if (proto == IPPROTO_TCP) {
5289 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
5295 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
5296 + * them spoof us. [DHCP needs this feature - HW] */
5297 + if (!addr.s_addr) {
5298 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
5302 + /* Use jiffies here not to depend on someone setting the time while we're
5303 + * running; we need to be careful with possible return value overflows. */
5306 + spin_lock(&state.lock);
5308 + /* Do we know this source address already? */
5311 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
5313 + if (curr->src_addr.s_addr == addr.s_addr) break;
5315 + if (curr->next) last = curr;
5316 + } while ((curr = curr->next));
5320 + /* We know this address, and the entry isn't too old. Update it. */
5321 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
5322 + time_after_eq(now, curr->timestamp)) {
5324 + /* Just update the appropriate list entry if we've seen this port already */
5325 + for (index = 0; index < curr->count; index++) {
5326 + if (curr->ports[index].number == dest_port) {
5327 + curr->ports[index].proto = proto;
5328 + curr->ports[index].and_flags &= tcp_flags;
5329 + curr->ports[index].or_flags |= tcp_flags;
5330 + goto out_no_match;
5334 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
5335 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
5336 + goto out_no_match;
5338 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
5339 + curr->timestamp = now;
5341 + /* Logged this scan already? Then drop the packet. */
5342 + if (curr->weight >= psdinfo->weight_threshold)
5345 + /* Specify if destination address, source port, TOS or TTL are not fixed */
5346 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
5347 + curr->flags |= HF_DADDR_CHANGING;
5348 + if (curr->src_port != src_port)
5349 + curr->flags |= HF_SPORT_CHANGING;
5350 + if (curr->tos != ip_hdr->tos)
5351 + curr->flags |= HF_TOS_CHANGING;
5352 + if (curr->ttl != ip_hdr->ttl)
5353 + curr->flags |= HF_TTL_CHANGING;
5355 + /* Update the total weight */
5356 + curr->weight += (ntohs(dest_port) < 1024) ?
5357 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
5359 + /* Got enough destination ports to decide that this is a scan? */
5360 + /* Then log it and drop the packet. */
5361 + if (curr->weight >= psdinfo->weight_threshold)
5364 + /* Remember the new port */
5365 + if (curr->count < SCAN_MAX_COUNT) {
5366 + curr->ports[curr->count].number = dest_port;
5367 + curr->ports[curr->count].proto = proto;
5368 + curr->ports[curr->count].and_flags = tcp_flags;
5369 + curr->ports[curr->count].or_flags = tcp_flags;
5373 + goto out_no_match;
5376 + /* We know this address, but the entry is outdated. Mark it unused, and
5377 + * remove from the hash table. We'll allocate a new entry instead since
5378 + * this one might get re-used too soon. */
5379 + curr->src_addr.s_addr = 0;
5381 + last->next = last->next->next;
5383 + *head = (*head)->next;
5387 + /* We don't need an ACK from a new source address */
5388 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
5389 + goto out_no_match;
5391 + /* Got too many source addresses with the same hash value? Then remove the
5392 + * oldest one from the hash table, so that they can't take too much of our
5393 + * CPU time even with carefully chosen spoofed IP addresses. */
5394 + if (count >= HASH_MAX && last) last->next = NULL;
5396 + /* We're going to re-use the oldest list entry, so remove it from the hash
5397 + * table first (if it is really already in use, and isn't removed from the
5398 + * hash table already because of the HASH_MAX check above). */
5400 + /* First, find it */
5401 + if (state.list[state.index].src_addr.s_addr)
5402 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
5406 + if ((curr = *head))
5408 + if (curr == &state.list[state.index]) break;
5410 + } while ((curr = curr->next));
5412 + /* Then, remove it */
5415 + last->next = last->next->next;
5417 + *head = (*head)->next;
5420 + /* Get our list entry */
5421 + curr = &state.list[state.index++];
5422 + if (state.index >= LIST_SIZE) state.index = 0;
5424 + /* Link it into the hash table */
5425 + head = &state.hash[hash];
5426 + curr->next = *head;
5429 + /* And fill in the fields */
5430 + curr->timestamp = now;
5431 + curr->src_addr = addr;
5432 + curr->dest_addr.s_addr = ip_hdr->daddr;
5433 + curr->src_port = src_port;
5435 + curr->weight = (ntohs(dest_port) < 1024) ?
5436 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
5437 + curr->ports[0].number = dest_port;
5438 + curr->ports[0].proto = proto;
5439 + curr->ports[0].and_flags = tcp_flags;
5440 + curr->ports[0].or_flags = tcp_flags;
5441 + curr->tos = ip_hdr->tos;
5442 + curr->ttl = ip_hdr->ttl;
5445 + spin_unlock(&state.lock);
5449 + spin_unlock(&state.lock);
5453 +static int ipt_psd_checkentry(const char *tablename,
5454 + const struct ipt_ip *e,
5456 + unsigned int matchsize,
5457 + unsigned int hook_mask)
5459 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
5461 + /* we accept TCP only */
5462 +/* if (e->ip.proto != IPPROTO_TCP) { */
5463 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
5467 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
5468 + DEBUGP("PSD: matchsize %u != %u\n",
5470 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
5477 +static struct ipt_match ipt_psd_reg = {
5479 + .match = ipt_psd_match,
5480 + .checkentry = ipt_psd_checkentry,
5481 + .me = THIS_MODULE };
5483 +static int __init init(void)
5485 + if (ipt_register_match(&ipt_psd_reg))
5488 + memset(&state, 0, sizeof(state));
5490 + spin_lock_init(&(state.lock));
5492 + printk("netfilter PSD loaded - (c) astaro AG\n");
5496 +static void __exit fini(void)
5498 + ipt_unregister_match(&ipt_psd_reg);
5499 + printk("netfilter PSD unloaded - (c) astaro AG\n");
5504 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.7/net/ipv4/netfilter/ipt_quota.c
5505 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
5506 +++ linux-2.6.7/net/ipv4/netfilter/ipt_quota.c 2004-09-07 12:33:20.690406216 +0200
5509 + * netfilter module to enforce network quotas
5511 + * Sam Johnston <samj@samj.net>
5513 +#include <linux/module.h>
5514 +#include <linux/skbuff.h>
5515 +#include <linux/spinlock.h>
5516 +#include <linux/interrupt.h>
5518 +#include <linux/netfilter_ipv4/ip_tables.h>
5519 +#include <linux/netfilter_ipv4/ipt_quota.h>
5521 +MODULE_LICENSE("GPL");
5522 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
5524 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
5527 +match(const struct sk_buff *skb,
5528 + const struct net_device *in,
5529 + const struct net_device *out,
5530 + const void *matchinfo,
5531 + int offset, int *hotdrop)
5533 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
5534 + unsigned int datalen;
5536 + if (skb->len < sizeof(struct iphdr))
5539 + datalen = skb->len - skb->nh.iph->ihl*4;
5541 + spin_lock_bh("a_lock);
5543 + if (q->quota >= datalen) {
5544 + /* we can afford this one */
5545 + q->quota -= datalen;
5546 + spin_unlock_bh("a_lock);
5548 +#ifdef DEBUG_IPT_QUOTA
5549 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
5554 + /* so we do not allow even small packets from now on */
5557 +#ifdef DEBUG_IPT_QUOTA
5558 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
5561 + spin_unlock_bh("a_lock);
5566 +checkentry(const char *tablename,
5567 + const struct ipt_ip *ip,
5568 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
5570 + /* TODO: spinlocks? sanity checks? */
5571 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
5577 +static struct ipt_match quota_match = {
5580 + .checkentry = checkentry,
5587 + return ipt_register_match("a_match);
5593 + ipt_unregister_match("a_match);
5599 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c
5600 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_sctp.c 1970-01-01 01:00:00.000000000 +0100
5601 +++ linux-2.6.7/net/ipv4/netfilter/ipt_sctp.c 2004-09-07 12:33:05.390732120 +0200
5603 +#include <linux/module.h>
5604 +#include <linux/skbuff.h>
5605 +#include <net/ip.h>
5606 +#include <linux/sctp.h>
5608 +#include <linux/netfilter_ipv4/ip_tables.h>
5609 +#include <linux/netfilter_ipv4/ipt_sctp.h>
5612 +#define duprintf(format, args...) printk(format , ## args)
5614 +#define duprintf(format, args...)
5617 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
5618 + || (!!((invflag) & (option)) ^ (cond)))
5621 +match_flags(const struct ipt_sctp_flag_info *flag_info,
5622 + const int flag_count,
5623 + u_int8_t chunktype,
5624 + u_int8_t chunkflags)
5628 + for (i = 0; i < flag_count; i++) {
5629 + if (flag_info[i].chunktype == chunktype) {
5630 + return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
5638 +match_packet(const struct sk_buff *skb,
5639 + const u_int32_t *chunkmap,
5640 + int chunk_match_type,
5641 + const struct ipt_sctp_flag_info *flag_info,
5642 + const int flag_count,
5646 + u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
5647 + sctp_chunkhdr_t sch;
5653 + if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
5654 + SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
5657 + offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
5659 + if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
5660 + duprintf("Dropping invalid SCTP packet.\n");
5665 + duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
5666 + ++i, offset, sch.type, htons(sch.length), sch.flags);
5668 + offset += (htons(sch.length) + 3) & ~3;
5670 + duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
5672 + if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
5673 + switch (chunk_match_type) {
5674 + case SCTP_CHUNK_MATCH_ANY:
5675 + if (match_flags(flag_info, flag_count,
5676 + sch.type, sch.flags)) {
5681 + case SCTP_CHUNK_MATCH_ALL:
5682 + if (match_flags(flag_info, flag_count,
5683 + sch.type, sch.flags)) {
5684 + SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
5688 + case SCTP_CHUNK_MATCH_ONLY:
5689 + if (!match_flags(flag_info, flag_count,
5690 + sch.type, sch.flags)) {
5696 + switch (chunk_match_type) {
5697 + case SCTP_CHUNK_MATCH_ONLY:
5701 + } while (offset < skb->len);
5703 + switch (chunk_match_type) {
5704 + case SCTP_CHUNK_MATCH_ALL:
5705 + return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
5706 + case SCTP_CHUNK_MATCH_ANY:
5708 + case SCTP_CHUNK_MATCH_ONLY:
5712 + /* This will never be reached, but required to stop compiler whine */
5717 +match(const struct sk_buff *skb,
5718 + const struct net_device *in,
5719 + const struct net_device *out,
5720 + const void *matchinfo,
5724 + const struct ipt_sctp_info *info;
5725 + sctp_sctphdr_t sh;
5727 + info = (const struct ipt_sctp_info *)matchinfo;
5730 + duprintf("Dropping non-first fragment.. FIXME\n");
5734 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
5735 + duprintf("Dropping evil TCP offset=0 tinygram.\n");
5739 + duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
5741 + return SCCHECK(((ntohs(sh.source) >= info->spts[0])
5742 + && (ntohs(sh.source) <= info->spts[1])),
5743 + IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
5744 + && SCCHECK(((ntohs(sh.dest) >= info->dpts[0])
5745 + && (ntohs(sh.dest) <= info->dpts[1])),
5746 + IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
5747 + && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
5748 + info->flag_info, info->flag_count,
5750 + IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
5754 +checkentry(const char *tablename,
5755 + const struct ipt_ip *ip,
5757 + unsigned int matchsize,
5758 + unsigned int hook_mask)
5760 + const struct ipt_sctp_info *info;
5762 + info = (const struct ipt_sctp_info *)matchinfo;
5764 + return ip->proto == IPPROTO_SCTP
5765 + && !(ip->invflags & IPT_INV_PROTO)
5766 + && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
5767 + && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
5768 + && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
5769 + && !(info->invflags & ~info->flags)
5770 + && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) ||
5771 + (info->chunk_match_type &
5772 + (SCTP_CHUNK_MATCH_ALL
5773 + | SCTP_CHUNK_MATCH_ANY
5774 + | SCTP_CHUNK_MATCH_ONLY)));
5777 +static struct ipt_match sctp_match =
5779 + .list = { NULL, NULL},
5782 + .checkentry = &checkentry,
5787 +static int __init init(void)
5789 + return ipt_register_match(&sctp_match);
5792 +static void __exit fini(void)
5794 + ipt_unregister_match(&sctp_match);
5800 +MODULE_LICENSE("GPL");
5801 +MODULE_AUTHOR("Kiran Kumar Immidi");
5802 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
5804 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c linux-2.6.7/net/ipv4/netfilter/ipt_time.c
5805 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
5806 +++ linux-2.6.7/net/ipv4/netfilter/ipt_time.c 2004-09-07 12:33:22.072196152 +0200
5809 + This is a module which is used for time matching
5810 + It is using some modified code from dietlibc (localtime() function)
5811 + that you can find at http://www.fefe.de/dietlibc/
5812 + This file is distributed under the terms of the GNU General Public
5813 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
5814 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
5815 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
5816 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
5817 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
5818 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
5819 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
5820 + 2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
5823 +#include <linux/module.h>
5824 +#include <linux/skbuff.h>
5825 +#include <linux/netfilter_ipv4/ip_tables.h>
5826 +#include <linux/netfilter_ipv4/ipt_time.h>
5827 +#include <linux/time.h>
5829 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5830 +MODULE_DESCRIPTION("Match arrival timestamp/date");
5831 +MODULE_LICENSE("GPL");
5835 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
5836 + int tm_min; /* Minutes. [0-59] */
5837 + int tm_hour; /* Hours. [0-23] */
5838 + int tm_mday; /* Day. [1-31] */
5839 + int tm_mon; /* Month. [0-11] */
5840 + int tm_year; /* Year - 1900. */
5841 + int tm_wday; /* Day of week. [0-6] */
5842 + int tm_yday; /* Days in year.[0-365] */
5843 + int tm_isdst; /* DST. [-1/0/1]*/
5845 + long int tm_gmtoff; /* we don't care, we count from GMT */
5846 + const char *tm_zone; /* we don't care, we count from GMT */
5850 +localtime(const time_t *timepr, struct tm *r);
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_time_info *info = matchinfo; /* match info for rule */
5863 + struct tm currenttime; /* time human readable */
5864 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
5865 + u_int16_t packet_time;
5866 + struct timeval kerneltimeval;
5867 + time_t packet_local_time;
5869 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
5870 + if (info->kerneltime)
5872 + do_gettimeofday(&kerneltimeval);
5873 + packet_local_time = kerneltimeval.tv_sec;
5876 + packet_local_time = skb->stamp.tv_sec;
5878 + /* First we make sure we are in the date start-stop boundaries */
5879 + if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
5880 + return 0; /* We are outside the date boundaries */
5882 + /* Transform the timestamp of the packet, in a human readable form */
5883 + localtime(&packet_local_time, ¤ttime);
5885 + /* check if we match this timestamp, we start by the days... */
5886 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
5887 + return 0; /* the day doesn't match */
5889 + /* ... check the time now */
5890 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
5891 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
5894 + /* here we match ! */
5899 +checkentry(const char *tablename,
5900 + const struct ipt_ip *ip,
5902 + unsigned int matchsize,
5903 + unsigned int hook_mask)
5905 + struct ipt_time_info *info = matchinfo; /* match info for rule */
5907 + /* First, check that we are in the correct hooks */
5909 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
5911 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
5914 + /* we use the kerneltime if we are in forward or output */
5915 + info->kerneltime = 1;
5916 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
5917 + /* we use the skb time */
5918 + info->kerneltime = 0;
5920 + /* Check the size */
5921 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
5923 + /* Now check the coherence of the data ... */
5924 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
5925 + (info->time_stop > 1439))
5927 + printk(KERN_WARNING "ipt_time: invalid argument\n");
5934 +static struct ipt_match time_match
5935 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
5937 +static int __init init(void)
5939 + printk("ipt_time loading\n");
5940 + return ipt_register_match(&time_match);
5943 +static void __exit fini(void)
5945 + ipt_unregister_match(&time_match);
5946 + printk("ipt_time unloaded\n");
5953 +/* The part below is borowed and modified from dietlibc */
5955 +/* seconds per day */
5956 +#define SPD 24*60*60
5959 +localtime(const time_t *timepr, struct tm *r) {
5962 + extern struct timezone sys_tz;
5963 + const unsigned int __spm[12] =
5970 + (31+28+31+30+31+30),
5971 + (31+28+31+30+31+30+31),
5972 + (31+28+31+30+31+30+31+31),
5973 + (31+28+31+30+31+30+31+31+30),
5974 + (31+28+31+30+31+30+31+31+30+31),
5975 + (31+28+31+30+31+30+31+31+30+31+30),
5977 + register time_t work;
5979 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
5981 + r->tm_sec=work%60; work/=60;
5982 + r->tm_min=work%60; r->tm_hour=work/60;
5984 + r->tm_wday=(4+work)%7;
5985 + for (i=1970; ; ++i) {
5986 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
5992 + r->tm_year=i-1900;
5993 + for (i=11; i && __spm[i]>work; --i) ;
5995 + r->tm_mday=work-__spm[i]+1;
5997 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.7/net/ipv4/netfilter/ipt_u32.c
5998 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
5999 +++ linux-2.6.7/net/ipv4/netfilter/ipt_u32.c 2004-09-07 12:38:33.377870496 +0200
6001 +/* Kernel module to match u32 packet content. */
6004 +U32 tests whether quantities of up to 4 bytes extracted from a packet
6005 +have specified values. The specification of what to extract is general
6006 +enough to find data at given offsets from tcp headers or payloads.
6009 + The argument amounts to a program in a small language described below.
6010 + tests := location = value | tests && location = value
6011 + value := range | value , range
6012 + range := number | number : number
6013 + a single number, n, is interpreted the same as n:n
6014 + n:m is interpreted as the range of numbers >=n and <=m
6015 + location := number | location operator number
6016 + operator := & | << | >> | @
6018 + The operators &, <<, >>, && mean the same as in c. The = is really a set
6019 + membership operator and the value syntax describes a set. The @ operator
6020 + is what allows moving to the next header and is described further below.
6022 + *** Until I can find out how to avoid it, there are some artificial limits
6023 + on the size of the tests:
6024 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
6025 + - no more than 10 ranges (and 9 commas) per value
6026 + - no more than 10 numbers (and 9 operators) per location
6028 + To describe the meaning of location, imagine the following machine that
6029 + interprets it. There are three registers:
6030 + A is of type char*, initially the address of the IP header
6031 + B and C are unsigned 32 bit integers, initially zero
6033 + The instructions are:
6034 + number B = number;
6035 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
6036 + &number C = C&number
6037 + <<number C = C<<number
6038 + >>number C = C>>number
6039 + @number A = A+C; then do the instruction number
6040 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
6041 + Otherwise the result of the computation is the final value of C.
6043 + Whitespace is allowed but not required in the tests.
6044 + However the characters that do occur there are likely to require
6045 + shell quoting, so it's a good idea to enclose the arguments in quotes.
6048 + match IP packets with total length >= 256
6049 + The IP header contains a total length field in bytes 2-3.
6050 + --u32 "0&0xFFFF=0x100:0xFFFF"
6052 + AND that with FFFF (giving bytes 2-3),
6053 + and test whether that's in the range [0x100:0xFFFF]
6055 +Example: (more realistic, hence more complicated)
6056 + match icmp packets with icmp type 0
6057 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
6058 + --u32 "6&0xFF=1 && ...
6059 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
6060 + Next test that it's not a fragment.
6061 + (If so it might be part of such a packet but we can't always tell.)
6062 + n.b. This test is generally needed if you want to match anything
6063 + beyond the IP header.
6064 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
6065 + packet (not a fragment). Alternatively, you can allow first fragments
6066 + by only testing the last 5 bits of byte 6.
6067 + ... 4&0x3FFF=0 && ...
6068 + Last test: the first byte past the IP header (the type) is 0
6069 + This is where we have to use the @syntax. The length of the IP header
6070 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
6072 + ... 0>>22&0x3C@0>>24=0"
6073 + The first 0 means read bytes 0-3,
6074 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
6075 + the first byte, so only 22 bits is four times that plus a few more bits.
6076 + &3C then eliminates the two extra bits on the right and the first four
6077 + bits of the first byte.
6078 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
6079 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
6080 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
6081 + @ means to use this number as a new offset into the packet, and read
6082 + four bytes starting from there. This is the first 4 bytes of the icmp
6083 + payload, of which byte 0 is the icmp type. Therefore we simply shift
6084 + the value 24 to the right to throw out all but the first byte and compare
6085 + the result with 0.
6088 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
6089 + First we test that the packet is a tcp packet (similar to icmp).
6090 + --u32 "6&0xFF=6 && ...
6091 + Next, test that it's not a fragment (same as above).
6092 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
6093 + 0>>22&3C as above computes the number of bytes in the IP header.
6094 + @ makes this the new offset into the packet, which is the start of the
6095 + tcp header. The length of the tcp header (again in 32 bit words) is
6096 + the left half of byte 12 of the tcp header. The 12>>26&3C
6097 + computes this length in bytes (similar to the IP header before).
6098 + @ makes this the new offset, which is the start of the tcp payload.
6099 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
6100 + result is any of 1, 2, 5 or 8
6103 +#include <linux/module.h>
6104 +#include <linux/skbuff.h>
6106 +#include <linux/netfilter_ipv4/ipt_u32.h>
6107 +#include <linux/netfilter_ipv4/ip_tables.h>
6109 +/* #include <asm-i386/timex.h> for timing */
6111 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
6112 +MODULE_DESCRIPTION("IP tables u32 matching module");
6113 +MODULE_LICENSE("GPL");
6116 +match(const struct sk_buff *skb,
6117 + const struct net_device *in,
6118 + const struct net_device *out,
6119 + const void *matchinfo,
6122 + u_int16_t datalen,
6125 + const struct ipt_u32 *data = matchinfo;
6127 + unsigned char* origbase = (char*)skb->nh.iph;
6128 + unsigned char* base = origbase;
6129 + unsigned char* head = skb->head;
6130 + unsigned char* end = skb->end;
6132 + u_int32_t pos, val;
6133 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
6134 + cycles1 = get_cycles(); */
6136 + for (testind=0; testind < data->ntests; testind++) {
6137 + base = origbase; /* reset for each test */
6138 + pos = data->tests[testind].location[0].number;
6139 + if (base+pos+3 > end || base+pos < head)
6141 + val = (base[pos]<<24) + (base[pos+1]<<16) +
6142 + (base[pos+2]<<8) + base[pos+3];
6143 + nnums = data->tests[testind].nnums;
6144 + for (i=1; i < nnums; i++) {
6145 + u_int32_t number = data->tests[testind].location[i].number;
6146 + switch (data->tests[testind].location[i].nextop) {
6148 + val = val & number;
6150 + case IPT_U32_LEFTSH:
6151 + val = val << number;
6153 + case IPT_U32_RIGHTSH:
6154 + val = val >> number;
6157 + base = base + val;
6159 + if (base+pos+3 > end || base+pos < head)
6161 + val = (base[pos]<<24) + (base[pos+1]<<16) +
6162 + (base[pos+2]<<8) + base[pos+3];
6166 + nvals = data->tests[testind].nvalues;
6167 + for (i=0; i < nvals; i++) {
6168 + if ((data->tests[testind].value[i].min <= val) &&
6169 + (val <= data->tests[testind].value[i].max)) {
6173 + if (i >= data->tests[testind].nvalues) {
6174 + /* cycles2 = get_cycles();
6175 + printk("failed %d in %d cycles\n", testind,
6176 + cycles2-cycles1); */
6180 + /* cycles2 = get_cycles();
6181 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
6186 +checkentry(const char *tablename,
6187 + const struct ipt_ip *ip,
6189 + unsigned int matchsize,
6190 + unsigned int hook_mask)
6192 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
6197 +static struct ipt_match u32_match
6198 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
6200 +static int __init init(void)
6202 + return ipt_register_match(&u32_match);
6205 +static void __exit fini(void)
6207 + ipt_unregister_match(&u32_match);
6212 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Kconfig linux-2.6.7/net/ipv6/netfilter/Kconfig
6213 --- linux-2.6.7.org/net/ipv6/netfilter/Kconfig 2004-09-07 12:07:46.626619360 +0200
6214 +++ linux-2.6.7/net/ipv6/netfilter/Kconfig 2004-09-07 12:33:17.553883040 +0200
6215 @@ -230,5 +230,60 @@
6216 <file:Documentation/modules.txt>. If unsure, say `N'.
6219 +config IP6_NF_TARGET_HL
6220 + tristate 'HL target support'
6221 + depends on IP6_NF_MANGLE
6223 + This option adds a `HL' target, which allows you to modify the value of
6224 + IPv6 Hop Limit field.
6226 + If you want to compile it as a module, say M here and read
6227 + <file:Documentation/modules.txt>. If unsure, say `N'.
6229 +config IP6_NF_TARGET_REJECT
6230 + tristate 'REJECT target support'
6231 + depends on IP6_NF_FILTER
6233 + The REJECT target allows a filtering rule to specify that an ICMPv6
6234 + error should be issued in response to an incoming packet, rather
6235 + than silently being dropped.
6237 + If you want to compile it as a module, say M here and read
6238 + Documentation/modules.txt. If unsure, say `N'.
6240 +config IP6_NF_MATCH_FUZZY
6241 + tristate 'Fuzzy match support'
6242 + depends on IP6_NF_FILTER
6244 + This option adds a `fuzzy' match, which allows you to match
6245 + packets according to a fuzzy logic based law.
6247 + If you want to compile it as a module, say M here and read
6248 + Documentation/modules.txt. If unsure, say `N'.
6250 +config IP6_NF_MATCH_NTH
6251 + tristate 'Nth match support'
6252 + depends on IP6_NF_IPTABLES
6254 + This option adds a `Nth' match, which allow you to make
6255 + rules that match every Nth packet. By default there are
6256 + 16 different counters.
6259 + --every Nth Match every Nth packet
6260 + [--counter] num Use counter 0-15 (default:0)
6261 + [--start] num Initialize the counter at the number 'num'
6262 + instead of 0. Must be between 0 and Nth-1
6263 + [--packet] num Match on 'num' packet. Must be between 0
6266 + If --packet is used for a counter than
6267 + there must be Nth number of --packet
6268 + rules, covering all values between 0 and
6269 + Nth-1 inclusively.
6271 + If you want to compile it as a module, say M here and read
6272 + Documentation/modules.txt. If unsure, say `N'.
6276 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Makefile linux-2.6.7/net/ipv6/netfilter/Makefile
6277 --- linux-2.6.7.org/net/ipv6/netfilter/Makefile 2004-09-07 12:07:46.626619360 +0200
6278 +++ linux-2.6.7/net/ipv6/netfilter/Makefile 2004-09-07 12:33:17.554882888 +0200
6280 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
6281 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
6282 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
6283 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
6284 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
6285 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
6286 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
6288 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
6289 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
6290 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
6292 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
6293 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
6294 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
6295 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
6296 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c
6297 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
6298 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c 2004-09-07 12:33:06.517560816 +0200
6301 + * Hop Limit modification target for ip6tables
6302 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
6303 + * Based on HW's TTL module
6305 + * This software is distributed under the terms of GNU GPL
6308 +#include <linux/module.h>
6309 +#include <linux/skbuff.h>
6310 +#include <linux/ip.h>
6312 +#include <linux/netfilter_ipv6/ip6_tables.h>
6313 +#include <linux/netfilter_ipv6/ip6t_HL.h>
6315 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
6316 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
6317 +MODULE_LICENSE("GPL");
6319 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
6320 + const struct net_device *in, const struct net_device *out,
6321 + const void *targinfo, void *userinfo)
6323 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
6324 + const struct ip6t_HL_info *info = targinfo;
6325 + u_int16_t diffs[2];
6328 + switch (info->mode) {
6330 + new_hl = info->hop_limit;
6333 + new_hl = ip6h->hop_limit + info->hop_limit;
6338 + new_hl = ip6h->hop_limit - info->hop_limit;
6343 + new_hl = ip6h->hop_limit;
6347 + if (new_hl != ip6h->hop_limit) {
6348 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
6349 + ip6h->hop_limit = new_hl;
6350 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
6353 + return IP6T_CONTINUE;
6356 +static int ip6t_hl_checkentry(const char *tablename,
6357 + const struct ip6t_entry *e,
6359 + unsigned int targinfosize,
6360 + unsigned int hook_mask)
6362 + struct ip6t_HL_info *info = targinfo;
6364 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
6365 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
6367 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
6371 + if (strcmp(tablename, "mangle")) {
6372 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6376 + if (info->mode > IP6T_HL_MAXMODE) {
6377 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
6382 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
6383 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
6390 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
6391 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
6393 +static int __init init(void)
6395 + return ip6t_register_target(&ip6t_HL);
6398 +static void __exit fini(void)
6400 + ip6t_unregister_target(&ip6t_HL);
6405 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c
6406 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
6407 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c 2004-09-07 12:33:08.255296640 +0200
6410 + * IP6 tables REJECT target module
6411 + * Linux INET6 implementation
6413 + * Copyright (C)2003 USAGI/WIDE Project
6416 + * Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
6418 + * Based on net/ipv4/netfilter/ipt_REJECT.c
6420 + * This program is free software; you can redistribute it and/or
6421 + * modify it under the terms of the GNU General Public License
6422 + * as published by the Free Software Foundation; either version
6423 + * 2 of the License, or (at your option) any later version.
6426 +#include <linux/config.h>
6427 +#include <linux/module.h>
6428 +#include <linux/skbuff.h>
6429 +#include <linux/icmpv6.h>
6430 +#include <net/ipv6.h>
6431 +#include <net/tcp.h>
6432 +#include <net/icmp.h>
6433 +#include <net/ip6_fib.h>
6434 +#include <net/ip6_route.h>
6435 +#include <net/flow.h>
6436 +#include <linux/netfilter_ipv6/ip6_tables.h>
6437 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
6439 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
6440 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
6441 +MODULE_LICENSE("GPL");
6444 +#define DEBUGP printk
6446 +#define DEBUGP(format, args...)
6450 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
6452 + void (*attach)(struct sk_buff *, struct nf_ct_info *);
6453 + if (nfct && (attach = ip6_ct_attach) != NULL) {
6455 + attach(new_skb, nfct);
6460 +static int maybe_reroute(struct sk_buff *skb)
6462 + if (skb->nfcache & NFC_ALTERED){
6463 + if (ip6_route_me_harder(skb) != 0){
6469 + return dst_output(skb);
6472 +/* Send RST reply */
6473 +static void send_reset(struct sk_buff *oldskb)
6475 + struct sk_buff *nskb;
6476 + struct tcphdr otcph, *tcph;
6477 + unsigned int otcplen, tcphoff, hh_len;
6479 + struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
6480 + struct dst_entry *dst = NULL;
6483 + proto = oip6h->nexthdr;
6486 + if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
6487 + (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
6488 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6492 + tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
6493 + &proto, oldskb->len - ((u8*)(oip6h+1)
6496 + if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
6497 + DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
6501 + otcplen = oldskb->len - tcphoff;
6503 + /* IP header checks: fragment, too short. */
6504 + if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
6505 + DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
6510 + if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
6511 + if (net_ratelimit())
6512 + printk("ip6t_REJECT: Can't copy tcp header\n");
6516 + /* No RST for RST. */
6518 + DEBUGP("ip6t_REJECT: RST is set\n");
6522 + /* Check checksum. */
6523 + if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
6524 + skb_checksum(oldskb, tcphoff, otcplen, 0))) {
6525 + DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
6529 + memset(&fl, 0, sizeof(fl));
6530 + fl.proto = IPPROTO_TCP;
6531 + ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
6532 + ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
6533 + fl.fl_ip_sport = otcph.dest;
6534 + fl.fl_ip_dport = otcph.source;
6535 + err = ip6_dst_lookup(NULL, &dst, &fl);
6537 + if (net_ratelimit())
6538 + printk("ip6t_REJECT: can't find dst. err = %d\n", err);
6542 + hh_len = (dst->dev->hard_header_len + 15)&~15;
6543 + nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
6544 + + sizeof(struct tcphdr) + dst->trailer_len,
6548 + if (net_ratelimit())
6549 + printk("ip6t_REJECT: Can't alloc skb\n");
6557 + skb_reserve(nskb, hh_len + dst->header_len);
6559 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6560 + skb_put(nskb, sizeof(struct ipv6hdr));
6561 + ip6h->version = 6;
6562 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6563 + ip6h->nexthdr = IPPROTO_TCP;
6564 + ip6h->payload_len = htons(sizeof(struct tcphdr));
6565 + ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
6566 + ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
6568 + tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
6569 + /* Truncate to length (no data) */
6570 + tcph->doff = sizeof(struct tcphdr)/4;
6571 + tcph->source = otcph.dest;
6572 + tcph->dest = otcph.source;
6576 + tcph->seq = otcph.ack_seq;
6577 + tcph->ack_seq = 0;
6580 + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
6581 + + otcplen - (otcph.doff<<2));
6586 + ((u_int8_t *)tcph)[13] = 0;
6588 + tcph->ack = needs_ack;
6590 + tcph->urg_ptr = 0;
6593 + /* Adjust TCP checksum */
6594 + tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
6595 + &nskb->nh.ipv6h->daddr,
6596 + sizeof(struct tcphdr), IPPROTO_TCP,
6597 + csum_partial((char *)tcph,
6598 + sizeof(struct tcphdr), 0));
6601 + connection_attach(nskb, oldskb->nfct);
6604 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6610 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
6612 + struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
6613 + struct icmp6hdr *icmp6h;
6614 + struct dst_entry *dst = NULL;
6615 + struct rt6_info *rt;
6618 + unsigned int len, datalen, hh_len;
6619 + int saddr_type, daddr_type;
6620 + unsigned int ptr, ip6off;
6623 + struct sk_buff *nskb;
6626 + saddr_type = ipv6_addr_type(&hdr->saddr);
6627 + daddr_type = ipv6_addr_type(&hdr->daddr);
6629 + if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
6630 + (!(daddr_type & IPV6_ADDR_UNICAST))) {
6631 + DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6635 + ip6off = skb_in->nh.raw - skb_in->data;
6636 + proto = hdr->nexthdr;
6637 + ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
6638 + skb_in->len - ip6off);
6640 + if ((ptr < 0) || (ptr > skb_in->len)) {
6641 + ptr = ip6off + sizeof(struct ipv6hdr);
6642 + proto = hdr->nexthdr;
6643 + } else if (proto == IPPROTO_ICMPV6) {
6646 + if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
6647 + icmp6_type), &type, 1)) {
6648 + DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
6652 + if (!(type & ICMPV6_INFOMSG_MASK)) {
6653 + DEBUGP("ip6t_REJECT: no reply to icmp error\n");
6656 + } else if (proto == IPPROTO_UDP) {
6657 + int plen = skb_in->len - (ptr - ip6off);
6660 + if (plen < sizeof(struct udphdr)) {
6661 + DEBUGP("ip6t_REJECT: too short\n");
6665 + if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
6667 + if (net_ratelimit())
6668 + printk("ip6t_REJECT: can't get copy from skb");
6673 + csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
6675 + skb_checksum(skb_in, ptr, plen, 0))) {
6676 + DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
6681 + memset(&fl, 0, sizeof(fl));
6682 + fl.proto = IPPROTO_ICMPV6;
6683 + ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
6684 + ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
6685 + fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
6686 + fl.fl_icmp_code = code;
6688 + if (ip6_dst_lookup(NULL, &dst, &fl)) {
6692 + rt = (struct rt6_info *)dst;
6695 + if (rt->rt6i_dst.plen < 128)
6696 + tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
6698 + if (!xrlim_allow(dst, tmo)) {
6699 + if (net_ratelimit())
6700 + printk("ip6t_REJECT: rate limitted\n");
6701 + goto dst_release_out;
6704 + len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
6706 + if (len > dst_pmtu(dst))
6707 + len = dst_pmtu(dst);
6708 + if (len > IPV6_MIN_MTU)
6709 + len = IPV6_MIN_MTU;
6711 + datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
6712 + hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
6714 + nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
6718 + if (net_ratelimit())
6719 + printk("ip6t_REJECT: can't alloc skb\n");
6720 + goto dst_release_out;
6723 + nskb->priority = 0;
6727 + skb_reserve(nskb, hh_len + dst->header_len);
6729 + ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6730 + skb_put(nskb, sizeof(struct ipv6hdr));
6731 + ip6h->version = 6;
6732 + ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6733 + ip6h->nexthdr = IPPROTO_ICMPV6;
6734 + ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
6735 + ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
6736 + ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
6738 + icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
6739 + icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
6740 + icmp6h->icmp6_code = code;
6741 + icmp6h->icmp6_cksum = 0;
6743 + data = skb_put(nskb, datalen);
6745 + csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
6746 + csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
6747 + icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
6748 + datalen + sizeof(struct icmp6hdr),
6749 + IPPROTO_ICMPV6, csum);
6752 + connection_attach(nskb, skb_in->nfct);
6754 + NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6761 +static unsigned int reject6_target(struct sk_buff **pskb,
6762 + unsigned int hooknum,
6763 + const struct net_device *in,
6764 + const struct net_device *out,
6765 + const void *targinfo,
6768 + const struct ip6t_reject_info *reject = targinfo;
6770 + DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
6771 + /* WARNING: This code causes reentry within ip6tables.
6772 + This means that the ip6tables jump stack is now crap. We
6773 + must return an absolute verdict. --RR */
6774 + switch (reject->with) {
6775 + case IP6T_ICMP6_NO_ROUTE:
6776 + send_unreach(*pskb, ICMPV6_NOROUTE);
6778 + case IP6T_ICMP6_ADM_PROHIBITED:
6779 + send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
6781 + case IP6T_ICMP6_NOT_NEIGHBOUR:
6782 + send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
6784 + case IP6T_ICMP6_ADDR_UNREACH:
6785 + send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
6787 + case IP6T_ICMP6_PORT_UNREACH:
6788 + send_unreach(*pskb, ICMPV6_PORT_UNREACH);
6790 + case IP6T_ICMP6_ECHOREPLY:
6793 + case IP6T_TCP_RESET:
6794 + send_reset(*pskb);
6797 + if (net_ratelimit())
6798 + printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
6805 +static int check(const char *tablename,
6806 + const struct ip6t_entry *e,
6808 + unsigned int targinfosize,
6809 + unsigned int hook_mask)
6811 + const struct ip6t_reject_info *rejinfo = targinfo;
6813 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
6814 + DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
6818 + /* Only allow these for packet filtering. */
6819 + if (strcmp(tablename, "filter") != 0) {
6820 + DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
6824 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
6825 + | (1 << NF_IP6_FORWARD)
6826 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
6827 + DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
6831 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
6832 + printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
6834 + } else if (rejinfo->with == IP6T_TCP_RESET) {
6835 + /* Must specify that it's a TCP packet */
6836 + if (e->ipv6.proto != IPPROTO_TCP
6837 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
6838 + DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
6846 +static struct ip6t_target ip6t_reject_reg = {
6848 + .target = reject6_target,
6849 + .checkentry = check,
6853 +static int __init init(void)
6855 + if (ip6t_register_target(&ip6t_reject_reg))
6860 +static void __exit fini(void)
6862 + ip6t_unregister_target(&ip6t_reject_reg);
6867 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c
6868 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
6869 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c 2004-09-07 12:33:12.081714936 +0200
6872 + * This module implements a simple TSK FLC
6873 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
6874 + * to limit , in an adaptive and flexible way , the packet rate crossing
6875 + * a given stream . It serves as an initial and very simple (but effective)
6876 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
6877 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
6878 + * into our code in a precise , adaptive and efficient manner.
6879 + * The goal is very similar to that of "limit" match , but using techniques of
6880 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
6881 + * avoiding over and undershoots - and stuff like that .
6884 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
6885 + * 2002-08-17 : Changed to eliminate floating point operations .
6886 + * 2002-08-23 : Coding style changes .
6887 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
6890 +#include <linux/module.h>
6891 +#include <linux/skbuff.h>
6892 +#include <linux/ipv6.h>
6893 +#include <linux/random.h>
6894 +#include <net/tcp.h>
6895 +#include <linux/spinlock.h>
6896 +#include <linux/netfilter_ipv6/ip6_tables.h>
6897 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
6900 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
6901 + Expressed in percentage
6904 +#define PAR_LOW 1/100
6907 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
6909 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
6910 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
6911 +MODULE_LICENSE("GPL");
6913 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6915 + if (tx >= maxi) return 100;
6917 + if (tx <= mini) return 0;
6919 + return ((100 * (tx-mini)) / (maxi-mini));
6922 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6924 + if (tx <= mini) return 100;
6926 + if (tx >= maxi) return 0;
6928 + return ((100 * (maxi - tx)) / (maxi - mini));
6933 +ip6t_fuzzy_match(const struct sk_buff *pskb,
6934 + const struct net_device *in,
6935 + const struct net_device *out,
6936 + const void *matchinfo,
6939 + u_int16_t datalen,
6942 + /* From userspace */
6944 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
6946 + u_int8_t random_number;
6947 + unsigned long amount;
6948 + u_int8_t howhigh, howlow;
6951 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
6953 + info->bytes_total += pskb->len;
6954 + info->packets_total++;
6956 + info->present_time = jiffies;
6958 + if (info->present_time >= info->previous_time)
6959 + amount = info->present_time - info->previous_time;
6961 + /* There was a transition : I choose to re-sample
6962 + and keep the old acceptance rate...
6966 + info->previous_time = info->present_time;
6967 + info->bytes_total = info->packets_total = 0;
6970 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
6972 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
6975 + info->previous_time = info->present_time;
6976 + info->bytes_total = info->packets_total = 0;
6978 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
6979 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
6981 + info->acceptance_rate = (u_int8_t) \
6982 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
6984 + /* In fact, the above defuzzification would require a denominator
6985 + * proportional to (howhigh+howlow) but, in this particular case,
6986 + * that expression is constant.
6987 + * An imediate consequence is that it is not necessary to call
6988 + * both mf_high and mf_low - but to keep things understandable,
6994 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
6997 + if (info->acceptance_rate < 100)
6999 + get_random_bytes((void *)(&random_number), 1);
7001 + /* If within the acceptance , it can pass => don't match */
7002 + if (random_number <= (255 * info->acceptance_rate) / 100)
7005 + return 1; /* It can't pass (It matches) */
7008 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
7013 +ip6t_fuzzy_checkentry(const char *tablename,
7014 + const struct ip6t_ip6 *ip,
7016 + unsigned int matchsize,
7017 + unsigned int hook_mask)
7020 + const struct ip6t_fuzzy_info *info = matchinfo;
7022 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
7023 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
7024 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
7028 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
7029 + || (info->minimum_rate >= info->maximum_rate)) {
7030 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
7037 +static struct ip6t_match ip6t_fuzzy_reg = {
7041 + ip6t_fuzzy_checkentry,
7045 +static int __init init(void)
7047 + if (ip6t_register_match(&ip6t_fuzzy_reg))
7053 +static void __exit fini(void)
7055 + ip6t_unregister_match(&ip6t_fuzzy_reg);
7060 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c
7061 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
7062 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c 2004-09-07 12:33:17.548883800 +0200
7065 + This is a module which is used for match support for every Nth packet
7066 + This file is distributed under the terms of the GNU General Public
7067 + License (GPL). Copies of the GPL can be obtained from:
7068 + ftp://prep.ai.mit.edu/pub/gnu/GPL
7070 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
7071 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
7072 + * added support for multiple counters
7073 + * added support for matching on individual packets
7074 + in the counter cycle
7075 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
7079 +#include <linux/module.h>
7080 +#include <linux/skbuff.h>
7081 +#include <linux/ip.h>
7082 +#include <net/tcp.h>
7083 +#include <linux/spinlock.h>
7084 +#include <linux/netfilter_ipv6/ip6_tables.h>
7085 +#include <linux/netfilter_ipv6/ip6t_nth.h>
7087 +MODULE_LICENSE("GPL");
7090 + * State information.
7097 +static struct state states[IP6T_NTH_NUM_COUNTERS];
7100 +ip6t_nth_match(const struct sk_buff *pskb,
7101 + const struct net_device *in,
7102 + const struct net_device *out,
7103 + const void *matchinfo,
7106 + u_int16_t datalen,
7109 + /* Parameters from userspace */
7110 + const struct ip6t_nth_info *info = matchinfo;
7111 + unsigned counter = info->counter;
7112 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
7114 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
7118 + spin_lock(&states[counter].lock);
7120 + /* Are we matching every nth packet?*/
7121 + if (info->packet == 0xFF)
7123 + /* We're matching every nth packet and only every nth packet*/
7124 + /* Do we match or invert match? */
7125 + if (info->not == 0)
7127 + if (states[counter].number == 0)
7129 + ++states[counter].number;
7132 + if (states[counter].number >= info->every)
7133 + states[counter].number = 0; /* reset the counter */
7135 + ++states[counter].number;
7140 + if (states[counter].number == 0)
7142 + ++states[counter].number;
7145 + if (states[counter].number >= info->every)
7146 + states[counter].number = 0;
7148 + ++states[counter].number;
7154 + /* We're using the --packet, so there must be a rule for every value */
7155 + if (states[counter].number == info->packet)
7157 + /* only increment the counter when a match happens */
7158 + if (states[counter].number >= info->every)
7159 + states[counter].number = 0; /* reset the counter */
7161 + ++states[counter].number;
7170 + spin_unlock(&states[counter].lock);
7174 + spin_unlock(&states[counter].lock);
7179 +ip6t_nth_checkentry(const char *tablename,
7180 + const struct ip6t_ip6 *e,
7182 + unsigned int matchsize,
7183 + unsigned int hook_mask)
7185 + /* Parameters from userspace */
7186 + const struct ip6t_nth_info *info = matchinfo;
7187 + unsigned counter = info->counter;
7188 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
7190 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
7194 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
7195 + printk("nth: matchsize %u != %u\n", matchsize,
7196 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
7200 + states[counter].number = info->startat;
7205 +static struct ip6t_match ip6t_nth_reg = {
7209 + ip6t_nth_checkentry,
7213 +static int __init init(void)
7216 + memset(&states, 0, sizeof(states));
7217 + if (ip6t_register_match(&ip6t_nth_reg))
7220 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
7222 + spin_lock_init(&(states[counter].lock));
7225 + printk("ip6t_nth match loaded\n");
7229 +static void __exit fini(void)
7231 + ip6t_unregister_match(&ip6t_nth_reg);
7232 + printk("ip6t_nth match unloaded\n");