]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.1-NF-20040114.patch
- moving config-* fixed.
[packages/kernel.git] / 2.6.1-NF-20040114.patch
CommitLineData
9e5a6bf4 1diff -Nur linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.1/include/linux/netfilter_ipv4/ipt_TTL.h
2--- linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
3+++ linux-2.6.1/include/linux/netfilter_ipv4/ipt_TTL.h 2004-01-14 14:06:00.000000000 +0100
4@@ -0,0 +1,21 @@
5+/* TTL modification module for IP tables
6+ * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
7+
8+#ifndef _IPT_TTL_H
9+#define _IPT_TTL_H
10+
11+enum {
12+ IPT_TTL_SET = 0,
13+ IPT_TTL_INC,
14+ IPT_TTL_DEC
15+};
16+
17+#define IPT_TTL_MAXMODE IPT_TTL_DEC
18+
19+struct ipt_TTL_info {
20+ u_int8_t mode;
21+ u_int8_t ttl;
22+};
23+
24+
25+#endif
26diff -Nur linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.1/include/linux/netfilter_ipv4/ipt_connlimit.h
27--- linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
28+++ linux-2.6.1/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-01-14 14:04:43.000000000 +0100
29@@ -0,0 +1,12 @@
30+#ifndef _IPT_CONNLIMIT_H
31+#define _IPT_CONNLIMIT_H
32+
33+struct ipt_connlimit_data;
34+
35+struct ipt_connlimit_info {
36+ int limit;
37+ int inverse;
38+ u_int32_t mask;
39+ struct ipt_connlimit_data *data;
40+};
41+#endif /* _IPT_CONNLIMIT_H */
42diff -Nur linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.1/include/linux/netfilter_ipv4/ipt_osf.h
43--- linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
44+++ linux-2.6.1/include/linux/netfilter_ipv4/ipt_osf.h 2004-01-14 14:04:31.000000000 +0100
45@@ -0,0 +1,130 @@
46+/*
47+ * ipt_osf.h
48+ *
49+ * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
50+ *
51+ *
52+ * This program is free software; you can redistribute it and/or modify
53+ * it under the terms of the GNU General Public License as published by
54+ * the Free Software Foundation; either version 2 of the License, or
55+ * (at your option) any later version.
56+ *
57+ * This program is distributed in the hope that it will be useful,
58+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
59+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60+ * GNU General Public License for more details.
61+ *
62+ * You should have received a copy of the GNU General Public License
63+ * along with this program; if not, write to the Free Software
64+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65+ */
66+
67+#ifndef _IPT_OSF_H
68+#define _IPT_OSF_H
69+
70+#define MAXGENRELEN 32
71+#define MAXDETLEN 64
72+
73+#define IPT_OSF_GENRE 1
74+#define IPT_OSF_SMART 2
75+#define IPT_OSF_LOG 4
76+
77+#define IPT_OSF_LOGLEVEL_ALL 0
78+#define IPT_OSF_LOGLEVEL_FIRST 1
79+
80+#include <linux/list.h>
81+
82+struct ipt_osf_info
83+{
84+ char genre[MAXGENRELEN];
85+ int len;
86+ unsigned long flags;
87+ int loglevel;
88+ int invert; /* UNSUPPORTED */
89+};
90+
91+struct osf_wc
92+{
93+ char wc;
94+ unsigned long val;
95+};
96+
97+/* This struct represents IANA options
98+ * http://www.iana.org/assignments/tcp-parameters
99+ */
100+struct osf_opt
101+{
102+ unsigned char kind;
103+ unsigned char length;
104+ struct osf_wc wc;
105+};
106+
107+#ifdef __KERNEL__
108+
109+struct osf_finger
110+{
111+ struct list_head flist;
112+ struct osf_wc wss;
113+ unsigned char ttl;
114+ unsigned char df;
115+ unsigned long ss;
116+ char genre[MAXGENRELEN];
117+ char version[MAXGENRELEN], subtype[MAXGENRELEN];
118+
119+ /* Not needed, but for consistency with original table from Michal Zalewski */
120+ char details[MAXDETLEN];
121+
122+ int opt_num;
123+ struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
124+
125+};
126+
127+/* Defines for IANA option kinds */
128+
129+#define OSFOPT_EOL 0 /* End of options */
130+#define OSFOPT_NOP 1 /* NOP */
131+#define OSFOPT_MSS 2 /* Maximum segment size */
132+#define OSFOPT_WSO 3 /* Window scale option */
133+#define OSFOPT_SACKP 4 /* SACK permitted */
134+#define OSFOPT_SACK 5 /* SACK */
135+#define OSFOPT_ECHO 6
136+#define OSFOPT_ECHOREPLY 7
137+#define OSFOPT_TS 8 /* Timestamp option */
138+#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
139+#define OSFOPT_POSP 10 /* Partial Order Service Profile */
140+/* Others are not used in current OSF */
141+
142+static struct osf_opt IANA_opts[] =
143+{
144+ {0, 1,},
145+ {1, 1,},
146+ {2, 4,},
147+ {3, 3,},
148+ {4, 2,},
149+ {5, 1 ,}, /* SACK length is not defined */
150+ {6, 6,},
151+ {7, 6,},
152+ {8, 10,},
153+ {9, 2,},
154+ {10, 3,},
155+ {11, 1,}, /* CC: Suppose 1 */
156+ {12, 1,}, /* the same */
157+ {13, 1,}, /* and here too */
158+ {14, 3,},
159+ {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
160+ {16, 1,},
161+ {17, 1,},
162+ {18, 3,},
163+ {19, 18,},
164+ {20, 1,},
165+ {21, 1,},
166+ {22, 1,},
167+ {23, 1,},
168+ {24, 1,},
169+ {25, 1,},
170+ {26, 1,},
171+};
172+
173+#endif /* __KERNEL__ */
174+
175+#endif /* _IPT_OSF_H */
176diff -Nur linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.1/include/linux/netfilter_ipv4/ipt_psd.h
177--- linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
178+++ linux-2.6.1/include/linux/netfilter_ipv4/ipt_psd.h 2004-01-14 14:04:53.000000000 +0100
179@@ -0,0 +1,40 @@
180+#ifndef _IPT_PSD_H
181+#define _IPT_PSD_H
182+
183+#include <linux/param.h>
184+#include <linux/types.h>
185+
186+/*
187+ * High port numbers have a lower weight to reduce the frequency of false
188+ * positives, such as from passive mode FTP transfers.
189+ */
190+#define PORT_WEIGHT_PRIV 3
191+#define PORT_WEIGHT_HIGH 1
192+
193+/*
194+ * Port scan detection thresholds: at least COUNT ports need to be scanned
195+ * from the same source, with no longer than DELAY ticks between ports.
196+ */
197+#define SCAN_MIN_COUNT 7
198+#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
199+#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
200+#define SCAN_DELAY_THRESHOLD (HZ * 3)
201+
202+/*
203+ * Keep track of up to LIST_SIZE source addresses, using a hash table of
204+ * HASH_SIZE entries for faster lookups, but limiting hash collisions to
205+ * HASH_MAX source addresses per the same hash value.
206+ */
207+#define LIST_SIZE 0x100
208+#define HASH_LOG 9
209+#define HASH_SIZE (1 << HASH_LOG)
210+#define HASH_MAX 0x10
211+
212+struct ipt_psd_info {
213+ unsigned int weight_threshold;
214+ unsigned int delay_threshold;
215+ unsigned short lo_ports_weight;
216+ unsigned short hi_ports_weight;
217+};
218+
219+#endif /*_IPT_PSD_H*/
220diff -Nur linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.1/include/linux/netfilter_ipv4/ipt_quota.h
221--- linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
222+++ linux-2.6.1/include/linux/netfilter_ipv4/ipt_quota.h 2004-01-14 14:04:22.000000000 +0100
223@@ -0,0 +1,11 @@
224+#ifndef _IPT_QUOTA_H
225+#define _IPT_QUOTA_H
226+
227+/* print debug info in both kernel/netfilter module & iptable library */
228+//#define DEBUG_IPT_QUOTA
229+
230+struct ipt_quota_info {
231+ u_int64_t quota;
232+};
233+
234+#endif /*_IPT_QUOTA_H*/
235diff -Nur linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.1/include/linux/netfilter_ipv4/ipt_time.h
236--- linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
237+++ linux-2.6.1/include/linux/netfilter_ipv4/ipt_time.h 2004-01-14 14:05:44.000000000 +0100
238@@ -0,0 +1,13 @@
239+#ifndef __ipt_time_h_included__
240+#define __ipt_time_h_included__
241+
242+
243+struct ipt_time_info {
244+ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
245+ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
246+ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
247+ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
248+};
249+
250+
251+#endif /* __ipt_time_h_included__ */
252diff -Nur linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.1/include/linux/netfilter_ipv4/ipt_u32.h
253--- linux-2.6.1.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
254+++ linux-2.6.1/include/linux/netfilter_ipv4/ipt_u32.h 2004-01-14 14:05:13.000000000 +0100
255@@ -0,0 +1,40 @@
256+#ifndef _IPT_U32_H
257+#define _IPT_U32_H
258+#include <linux/netfilter_ipv4/ip_tables.h>
259+
260+enum ipt_u32_ops
261+{
262+ IPT_U32_AND,
263+ IPT_U32_LEFTSH,
264+ IPT_U32_RIGHTSH,
265+ IPT_U32_AT
266+};
267+
268+struct ipt_u32_location_element
269+{
270+ u_int32_t number;
271+ u_int8_t nextop;
272+};
273+struct ipt_u32_value_element
274+{
275+ u_int32_t min;
276+ u_int32_t max;
277+};
278+/* *** any way to allow for an arbitrary number of elements?
279+ for now I settle for a limit of 10 of each */
280+#define U32MAXSIZE 10
281+struct ipt_u32_test
282+{
283+ u_int8_t nnums;
284+ struct ipt_u32_location_element location[U32MAXSIZE+1];
285+ u_int8_t nvalues;
286+ struct ipt_u32_value_element value[U32MAXSIZE+1];
287+};
288+
289+struct ipt_u32
290+{
291+ u_int8_t ntests;
292+ struct ipt_u32_test tests[U32MAXSIZE+1];
293+};
294+
295+#endif /*_IPT_U32_H*/
296diff -Nur linux-2.6.1.org/net/ipv4/netfilter/Kconfig linux-2.6.1/net/ipv4/netfilter/Kconfig
297--- linux-2.6.1.org/net/ipv4/netfilter/Kconfig 2004-01-09 07:59:56.000000000 +0100
298+++ linux-2.6.1/net/ipv4/netfilter/Kconfig 2004-01-14 14:06:00.000000000 +0100
299@@ -466,6 +466,16 @@
300
301 To compile it as a module, choose M here. If unsure, say N.
302
303+config IP_NF_TARGET_TTL
304+ tristate 'TTL target support'
305+ depends on IP_NF_MANGLE
306+ help
307+ This adds an iptables TTL manipulation target, which enables the user
308+ to set the TTL value of an IP packet or to increment / decrement it
309+ by a given value.
310+
311+ To compile it as a module, choose M here. If unsure, say N.
312+
313 config IP_NF_TARGET_CLASSIFY
314 tristate "CLASSIFY target support"
315 depends on IP_NF_MANGLE
316@@ -566,5 +576,162 @@
317
318 To compile it as a module, choose M here. If unsure, say N.
319
320+config IP_NF_MATCH_QUOTA
321+ tristate 'quota match support'
322+ depends on IP_NF_IPTABLES
323+ help
324+ This option adds CONFIG_IP_NF_MATCH_QUOTA, which implements network
325+ quotas by decrementing a byte counter with each packet.
326+
327+ Supported options are:
328+ --quota <bytes>
329+ The quota in bytes.
330+
331+ KNOWN BUGS: this does not work on SMP systems.
332+
333+
334+config IP_NF_MATCH_OSF
335+ tristate 'OSF match support'
336+ depends on IP_NF_IPTABLES
337+ help
338+ The idea of passive OS fingerprint matching exists for quite a long time,
339+ but was created as extension fo OpenBSD pf only some weeks ago.
340+ Original idea was lurked in some OpenBSD mailing list (thanks
341+ grange@open...) and than adopted for Linux netfilter in form of this code.
342+
343+ Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
344+ his excellent p0f and than changed a bit for more convenience.
345+
346+ This module compares some data(WS, MSS, options and it's order, ttl,
347+ df and others) from first SYN packet (actually from packets with SYN
348+ bit set) with hardcoded in fingers[] table ones.
349+
350+ Example: (Of course this only an example, do not get inspired by this)
351+
352+ # iptables -N LINUX
353+ # iptables -A LINUX -j LOG --log-prefix "Linux"
354+
355+ # iptables -A INPUT -p tcp -m osf --genre Linux -j LINUX
356+ # iptables -A INPUT -p tcp -m osf --genre FreeBSD -j REJECT
357+
358+ NOTE: -p tcp is obviously required as it is a TCP match.
359+
360+ OSF also has:
361+ --log 1/0.
362+ If present, OSF will log determined genres even if they don't match
363+ desired one.
364+ 0 - log all determined entries,
365+ 1 - only first one.
366+
367+ Example:
368+ #iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 1 --smart
369+
370+ In syslog you find something like this:
371+ ipt_osf: Windows [Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
372+ ipt_osf: Unknown: 16384:106:1:48:020405B401010402 44.33.22.11:1239 -> 11.22.33.44:80
373+
374+ --smart
375+ if present, OSF will use some smartness to determine remote OS.
376+ Now only not use TTL( with it far remote machines can be determined).
377+
378+ Fingerprints can be loaded through /proc/sys/net/ipv4/osf file.
379+ Only one fingerprint per open/close.
380+
381+ Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
382+
383+config IP_NF_MATCH_CONNLIMIT
384+ tristate 'Connections/IP limit match support'
385+ depends on IP_NF_IPTABLES
386+ help
387+ This adds an iptables match which allows you to restrict the
388+ number of parallel TCP connections to a server per client IP address
389+ (or address block).
390+
391+ Examples:
392+
393+ # allow 2 telnet connections per client host
394+ iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
395+
396+ # you can also match the other way around:
397+ iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
398+
399+ # limit the nr of parallel http requests to 16 per class C sized
400+ # network (24 bit netmask)
401+ iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 \
402+ --connlimit-mask 24 -j REJECT
403+
404+config IP_NF_MATCH_PSD
405+ tristate 'psd match support'
406+ depends on IP_NF_IPTABLES
407+ help
408+ This option adds a `psd' match, which supplies portscan
409+ detection match (psd). This match will attempt to detect TCP and UDP
410+ port scans. This match was derived from Solar Designer's scanlogd.
411+
412+ Suppported options are:
413+
414+ --psd-weight-threshold <threshold>
415+
416+ Total weight of the latest TCP/UDP packets with different
417+ destination ports coming from the same host to be treated as port
418+ scan sequence.
419+
420+ --psd-delay-threshold <delay>
421+
422+ Delay (in hundredths of second) for the packets with different
423+ destination ports coming from the same host to be treated as
424+ possible port scan subsequence.
425+
426+ --psd-lo-ports-weight <weight>
427+
428+ Weight of the packet with privileged (<=1024) destination port.
429+
430+ --psd-hi-ports-weight <weight>
431+
432+ Weight of the packet with non-priviliged destination port.
433+
434+config IP_NF_MATCH_U32
435+ tristate 'U32 match support'
436+ depends on IP_NF_IPTABLES
437+ help
438+
439+ U32 allows you to extract quantities of up to 4 bytes from a packet,
440+ AND them with specified masks, shift them by specified amounts and
441+ test whether the results are in any of a set of specified ranges.
442+ The specification of what to extract is general enough to skip over
443+ headers with lengths stored in the packet, as in IP or TCP header
444+ lengths.
445+ Details and examples are in the kernel module source.
446+
447+config IP_NF_MATCH_TIME
448+ tristate 'TIME match support'
449+ depends on IP_NF_IPTABLES
450+ help
451+
452+ This option adds CONFIG_IP_NF_MATCH_TIME, which supplies a time match module.
453+ This match allows you to filter based on the packet arrival time
454+ (arrival time at the machine which the netfilter is running on) or
455+ departure time (for locally generated packets).
456+
457+ Supported options are:
458+ --timestart HH:MM
459+ The starting point of the time match frame.
460+
461+ --timestop HH:MM
462+ The stopping point of the time match frame
463+
464+ --days Tue,Mon...
465+ Days of the week to match separated by a coma, no space
466+ (one of Sun,Mon,Tue,Wed,Thu,Fri,Sat)
467+
468+ Example:
469+ -A INPUT -m time --timestart 8:00 --timestop 18:00 --days Mon,Tue,Wed,Thu,Fri
470+ will match packets that have an arrival timestamp in the range 8:00->18:00 from Monday
471+ to Friday.
472+
473+ -A OUTPUT -m time --timestart 8:00 --timestop 18:00 --Days Mon
474+ will match the packets (locally generated) that have a departure timestamp
475+ in the range 8:00->18:00 on Monday only.
476+
477 endmenu
478
479diff -Nur linux-2.6.1.org/net/ipv4/netfilter/Makefile linux-2.6.1/net/ipv4/netfilter/Makefile
480--- linux-2.6.1.org/net/ipv4/netfilter/Makefile 2004-01-09 07:59:18.000000000 +0100
481+++ linux-2.6.1/net/ipv4/netfilter/Makefile 2004-01-14 14:06:00.000000000 +0100
482@@ -42,6 +42,7 @@
483 # matches
484 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
485 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
486+obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
487 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
488 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
489 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
490@@ -51,6 +52,14 @@
491 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
492 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
493
494+obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
495+
496+
497+obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
498+
499+obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
500+
501+
502 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
503
504 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
505@@ -59,8 +68,12 @@
506
507 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
508
509+obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
510+
511+
512 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
513 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
514+obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
515 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
516 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
517
518@@ -72,6 +85,7 @@
519 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
520 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
521 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
522+obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
523 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
524 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
525 obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
526diff -Nur linux-2.6.1.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.1/net/ipv4/netfilter/ipt_TTL.c
527--- linux-2.6.1.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
528+++ linux-2.6.1/net/ipv4/netfilter/ipt_TTL.c 2004-01-14 14:06:00.000000000 +0100
529@@ -0,0 +1,117 @@
530+/* TTL modification target for IP tables
531+ * (C) 2000 by Harald Welte <laforge@gnumonks.org>
532+ *
533+ * Version: 1.8
534+ *
535+ * This software is distributed under the terms of GNU GPL
536+ */
537+
538+#include <linux/module.h>
539+#include <linux/skbuff.h>
540+#include <linux/ip.h>
541+#include <net/checksum.h>
542+
543+#include <linux/netfilter_ipv4/ip_tables.h>
544+#include <linux/netfilter_ipv4/ipt_TTL.h>
545+
546+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
547+MODULE_DESCRIPTION("IP tables TTL modification module");
548+MODULE_LICENSE("GPL");
549+
550+static unsigned int ipt_ttl_target(struct sk_buff **pskb,
551+ const struct net_device *in,
552+ const struct net_device *out,
553+ unsigned int hooknum,
554+ const void *targinfo,
555+ void *userinfo)
556+{
557+ struct iphdr *iph = (*pskb)->nh.iph;
558+ const struct ipt_TTL_info *info = targinfo;
559+ u_int16_t diffs[2];
560+ int new_ttl;
561+
562+ switch (info->mode) {
563+ case IPT_TTL_SET:
564+ new_ttl = info->ttl;
565+ break;
566+ case IPT_TTL_INC:
567+ new_ttl = iph->ttl + info->ttl;
568+ if (new_ttl > 255)
569+ new_ttl = 255;
570+ break;
571+ case IPT_TTL_DEC:
572+ new_ttl = iph->ttl + info->ttl;
573+ if (new_ttl < 0)
574+ new_ttl = 0;
575+ break;
576+ default:
577+ new_ttl = iph->ttl;
578+ break;
579+ }
580+
581+ if (new_ttl != iph->ttl) {
582+ diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
583+ iph->ttl = new_ttl;
584+ diffs[1] = htons(((unsigned)iph->ttl) << 8);
585+ iph->check = csum_fold(csum_partial((char *)diffs,
586+ sizeof(diffs),
587+ iph->check^0xFFFF));
588+ (*pskb)->nfcache |= NFC_ALTERED;
589+ }
590+
591+ return IPT_CONTINUE;
592+}
593+
594+static int ipt_ttl_checkentry(const char *tablename,
595+ const struct ipt_entry *e,
596+ void *targinfo,
597+ unsigned int targinfosize,
598+ unsigned int hook_mask)
599+{
600+ struct ipt_TTL_info *info = targinfo;
601+
602+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
603+ printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
604+ targinfosize,
605+ IPT_ALIGN(sizeof(struct ipt_TTL_info)));
606+ return 0;
607+ }
608+
609+ if (strcmp(tablename, "mangle")) {
610+ printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
611+ return 0;
612+ }
613+
614+ if (info->mode > IPT_TTL_MAXMODE) {
615+ printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
616+ info->mode);
617+ return 0;
618+ }
619+
620+ if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
621+ printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
622+ return 0;
623+ }
624+
625+ return 1;
626+}
627+
628+static struct ipt_target ipt_TTL = {
629+ .name = "TTL",
630+ .target = ipt_ttl_target,
631+ .checkentry = ipt_ttl_checkentry,
632+ .me = THIS_MODULE,
633+};
634+
635+static int __init init(void)
636+{
637+ return ipt_register_target(&ipt_TTL);
638+}
639+
640+static void __exit fini(void)
641+{
642+ ipt_unregister_target(&ipt_TTL);
643+}
644+
645+module_init(init);
646+module_exit(fini);
647diff -Nur linux-2.6.1.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.1/net/ipv4/netfilter/ipt_connlimit.c
648--- linux-2.6.1.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
649+++ linux-2.6.1/net/ipv4/netfilter/ipt_connlimit.c 2004-01-14 14:04:43.000000000 +0100
650@@ -0,0 +1,230 @@
651+/*
652+ * netfilter module to limit the number of parallel tcp
653+ * connections per IP address.
654+ * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
655+ * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
656+ * only ignore TIME_WAIT or gone connections
657+ *
658+ * based on ...
659+ *
660+ * Kernel module to match connection tracking information.
661+ * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
662+ */
663+#include <linux/module.h>
664+#include <linux/skbuff.h>
665+#include <linux/list.h>
666+#include <linux/netfilter_ipv4/ip_conntrack.h>
667+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
668+#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
669+#include <linux/netfilter_ipv4/ip_tables.h>
670+#include <linux/netfilter_ipv4/ipt_connlimit.h>
671+
672+#define DEBUG 0
673+
674+MODULE_LICENSE("GPL");
675+
676+/* we'll save the tuples of all connections we care about */
677+struct ipt_connlimit_conn
678+{
679+ struct list_head list;
680+ struct ip_conntrack_tuple tuple;
681+};
682+
683+struct ipt_connlimit_data {
684+ spinlock_t lock;
685+ struct list_head iphash[256];
686+};
687+
688+static int ipt_iphash(u_int32_t addr)
689+{
690+ int hash;
691+
692+ hash = addr & 0xff;
693+ hash ^= (addr >> 8) & 0xff;
694+ hash ^= (addr >> 16) & 0xff;
695+ hash ^= (addr >> 24) & 0xff;
696+ return hash;
697+}
698+
699+static int count_them(struct ipt_connlimit_data *data,
700+ u_int32_t addr, u_int32_t mask,
701+ struct ip_conntrack *ct)
702+{
703+#if DEBUG
704+ const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
705+ "fin_wait", "time_wait", "close", "close_wait",
706+ "last_ack", "listen" };
707+#endif
708+ int addit = 1, matches = 0;
709+ struct ip_conntrack_tuple tuple;
710+ struct ip_conntrack_tuple_hash *found;
711+ struct ipt_connlimit_conn *conn;
712+ struct list_head *hash,*lh;
713+
714+ spin_lock(&data->lock);
715+ tuple = ct->tuplehash[0].tuple;
716+ hash = &data->iphash[ipt_iphash(addr & mask)];
717+
718+ /* check the saved connections */
719+ for (lh = hash->next; lh != hash; lh = lh->next) {
720+ conn = list_entry(lh,struct ipt_connlimit_conn,list);
721+ found = ip_conntrack_find_get(&conn->tuple,ct);
722+ if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
723+ found != NULL &&
724+ found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
725+ /* Just to be sure we have it only once in the list.
726+ We should'nt see tuples twice unless someone hooks this
727+ into a table without "-p tcp --syn" */
728+ addit = 0;
729+ }
730+#if DEBUG
731+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
732+ ipt_iphash(addr & mask),
733+ NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
734+ NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
735+ (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
736+#endif
737+ if (NULL == found) {
738+ /* this one is gone */
739+ lh = lh->prev;
740+ list_del(lh->next);
741+ kfree(conn);
742+ continue;
743+ }
744+ if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
745+ /* we don't care about connections which are
746+ closed already -> ditch it */
747+ lh = lh->prev;
748+ list_del(lh->next);
749+ kfree(conn);
750+ nf_conntrack_put(&found->ctrack->infos[0]);
751+ continue;
752+ }
753+ if ((addr & mask) == (conn->tuple.src.ip & mask)) {
754+ /* same source IP address -> be counted! */
755+ matches++;
756+ }
757+ nf_conntrack_put(&found->ctrack->infos[0]);
758+ }
759+ if (addit) {
760+ /* save the new connection in our list */
761+#if DEBUG
762+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
763+ ipt_iphash(addr & mask),
764+ NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
765+ NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
766+#endif
767+ conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
768+ if (NULL == conn)
769+ return -1;
770+ memset(conn,0,sizeof(*conn));
771+ INIT_LIST_HEAD(&conn->list);
772+ conn->tuple = tuple;
773+ list_add(&conn->list,hash);
774+ matches++;
775+ }
776+ spin_unlock(&data->lock);
777+ return matches;
778+}
779+
780+static int
781+match(const struct sk_buff *skb,
782+ const struct net_device *in,
783+ const struct net_device *out,
784+ const void *matchinfo,
785+ int offset,
786+ const void *hdr,
787+ u_int16_t datalen,
788+ int *hotdrop)
789+{
790+ const struct ipt_connlimit_info *info = matchinfo;
791+ int connections, match;
792+ struct ip_conntrack *ct;
793+ enum ip_conntrack_info ctinfo;
794+
795+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
796+ if (NULL == ct) {
797+ printk("ipt_connlimit: Oops: invalid ct state ?\n");
798+ *hotdrop = 1;
799+ return 0;
800+ }
801+ connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
802+ if (-1 == connections) {
803+ printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
804+ *hotdrop = 1; /* let's free some memory :-) */
805+ return 0;
806+ }
807+ match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
808+#if DEBUG
809+ printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
810+ "connections=%d limit=%d match=%s\n",
811+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
812+ connections, info->limit, match ? "yes" : "no");
813+#endif
814+
815+ return match;
816+}
817+
818+static int check(const char *tablename,
819+ const struct ipt_ip *ip,
820+ void *matchinfo,
821+ unsigned int matchsize,
822+ unsigned int hook_mask)
823+{
824+ struct ipt_connlimit_info *info = matchinfo;
825+ int i;
826+
827+ /* verify size */
828+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
829+ return 0;
830+
831+ /* refuse anything but tcp */
832+ if (ip->proto != IPPROTO_TCP)
833+ return 0;
834+
835+ /* init private data */
836+ info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
837+ spin_lock_init(&(info->data->lock));
838+ for (i = 0; i < 256; i++)
839+ INIT_LIST_HEAD(&(info->data->iphash[i]));
840+
841+ return 1;
842+}
843+
844+static void destroy(void *matchinfo, unsigned int matchinfosize)
845+{
846+ struct ipt_connlimit_info *info = matchinfo;
847+ struct ipt_connlimit_conn *conn;
848+ struct list_head *hash;
849+ int i;
850+
851+ /* cleanup */
852+ for (i = 0; i < 256; i++) {
853+ hash = &(info->data->iphash[i]);
854+ while (hash != hash->next) {
855+ conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
856+ list_del(hash->next);
857+ kfree(conn);
858+ }
859+ }
860+ kfree(info->data);
861+}
862+
863+static struct ipt_match connlimit_match = {
864+ .name = "connlimit",
865+ .match = &match,
866+ .checkentry = &check,
867+ .me = THIS_MODULE };
868+
869+static int __init init(void)
870+{
871+ return ipt_register_match(&connlimit_match);
872+}
873+
874+static void __exit fini(void)
875+{
876+ ipt_unregister_match(&connlimit_match);
877+}
878+
879+module_init(init);
880+module_exit(fini);
881diff -Nur linux-2.6.1.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.1/net/ipv4/netfilter/ipt_osf.c
882--- linux-2.6.1.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
883+++ linux-2.6.1/net/ipv4/netfilter/ipt_osf.c 2004-01-14 14:04:31.000000000 +0100
884@@ -0,0 +1,730 @@
885+/*
886+ * ipt_osf.c
887+ *
888+ * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
889+ *
890+ *
891+ * This program is free software; you can redistribute it and/or modify
892+ * it under the terms of the GNU General Public License as published by
893+ * the Free Software Foundation; either version 2 of the License, or
894+ * (at your option) any later version.
895+ *
896+ * This program is distributed in the hope that it will be useful,
897+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
898+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
899+ * GNU General Public License for more details.
900+ *
901+ * You should have received a copy of the GNU General Public License
902+ * along with this program; if not, write to the Free Software
903+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
904+ */
905+
906+/*
907+ * OS fingerprint matching module.
908+ * It simply compares various parameters from SYN packet with
909+ * some hardcoded ones.
910+ *
911+ * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
912+ * for his p0f.
913+ */
914+
915+#include <linux/config.h>
916+#include <linux/kernel.h>
917+#include <linux/smp.h>
918+#include <linux/module.h>
919+#include <linux/skbuff.h>
920+#include <linux/file.h>
921+#include <linux/ip.h>
922+#include <linux/proc_fs.h>
923+#include <linux/fs.h>
924+#include <linux/slab.h>
925+#include <linux/spinlock.h>
926+#include <linux/ctype.h>
927+#include <linux/list.h>
928+
929+#include <net/sock.h>
930+#include <net/ip.h>
931+
932+#include <linux/netfilter_ipv4/ip_tables.h>
933+
934+#include <linux/netfilter_ipv4/ipt_osf.h>
935+
936+#define OSF_DEBUG
937+
938+#ifdef OSF_DEBUG
939+#define log(x...) printk(KERN_INFO "ipt_osf: " x)
940+#define loga(x...) printk(x)
941+#else
942+#define log(x...) do {} while(0)
943+#define loga(x...) do {} while(0)
944+#endif
945+
946+#define FMATCH_WRONG 0
947+#define FMATCH_OK 1
948+#define FMATCH_OPT_WRONG 2
949+
950+#define OPTDEL ','
951+#define OSFPDEL ':'
952+#define MAXOPTSTRLEN 128
953+#define OSFFLUSH "FLUSH"
954+
955+static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
956+static struct list_head finger_list;
957+
958+static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
959+ const void *, int, const void *, u_int16_t, int *);
960+static int checkentry(const char *, const struct ipt_ip *, void *,
961+ unsigned int, unsigned int);
962+
963+static struct ipt_match osf_match = {
964+ .name = "osf",
965+ .match = &match,
966+ .checkentry = &checkentry,
967+ .me = THIS_MODULE,
968+};
969+
970+static inline int smart_dec(unsigned long flags, unsigned char ip_ttl, unsigned char f_ttl)
971+{
972+ if (flags & IPT_OSF_SMART)
973+ return 1;
974+ else
975+ return (ip_ttl == f_ttl);
976+}
977+
978+static int
979+match(const struct sk_buff *skb,
980+ const struct net_device *in,
981+ const struct net_device *out,
982+ const void *matchinfo,
983+ int offset,
984+ const void *hdr,
985+ u_int16_t datalen,
986+ int *hotdrop)
987+{
988+ struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
989+ struct iphdr *ip = skb->nh.iph;
990+ struct tcphdr *tcp;
991+ int fmatch = FMATCH_WRONG, fcount = 0;
992+ unsigned long totlen, optsize = 0, window;
993+ unsigned char df, *optp = NULL, *_optp = NULL;
994+ char check_WSS = 0;
995+ struct list_head *ent;
996+ struct osf_finger *f;
997+
998+ if (!ip || !info)
999+ return 0;
1000+
1001+ tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
1002+
1003+ if (!tcp->syn)
1004+ return 0;
1005+ else if (tcp->ack)
1006+ return 0;
1007+
1008+ totlen = ntohs(ip->tot_len);
1009+ df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
1010+ window = ntohs(tcp->window);
1011+
1012+ if (tcp->doff*4 > sizeof(struct tcphdr))
1013+ {
1014+ _optp = optp = (char *)(tcp+1);
1015+ optsize = tcp->doff*4 - sizeof(struct tcphdr);
1016+ }
1017+
1018+
1019+ /* Actually we can create hash/table of all genres and search
1020+ * only in appropriate part, but here is initial variant,
1021+ * so will use slow path.
1022+ */
1023+ read_lock(&osf_lock);
1024+ list_for_each(ent, &finger_list)
1025+ {
1026+ f = list_entry(ent, struct osf_finger, flist);
1027+
1028+ if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
1029+ continue;
1030+
1031+ optp = _optp;
1032+ fmatch = FMATCH_WRONG;
1033+
1034+ if (totlen == f->ss && df == f->df &&
1035+ smart_dec(info->flags, ip->ttl, f->ttl))
1036+ {
1037+ unsigned long foptsize;
1038+ int optnum;
1039+ unsigned short mss = 0;
1040+
1041+ check_WSS = 0;
1042+
1043+ switch (f->wss.wc)
1044+ {
1045+ case 0: check_WSS = 0; break;
1046+ case 'S': check_WSS = 1; break;
1047+ case 'T': check_WSS = 2; break;
1048+ case '%': check_WSS = 3; break;
1049+ default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
1050+ f->wss.wc, f->genre, f->details);
1051+ check_WSS = 4;
1052+ break;
1053+ }
1054+ if (check_WSS == 4)
1055+ continue;
1056+
1057+ /* Check options */
1058+
1059+ foptsize = 0;
1060+ for (optnum=0; optnum<f->opt_num; ++optnum)
1061+ foptsize += f->opt[optnum].length;
1062+
1063+
1064+ if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
1065+ continue;
1066+
1067+ if (!optp)
1068+ {
1069+ fmatch = FMATCH_OK;
1070+ loga("\tYEP : matching without options.\n");
1071+ if ((info->flags & IPT_OSF_LOG) &&
1072+ info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
1073+ break;
1074+ else
1075+ continue;
1076+ }
1077+
1078+
1079+ for (optnum=0; optnum<f->opt_num; ++optnum)
1080+ {
1081+ if (f->opt[optnum].kind == (*optp))
1082+ {
1083+ unsigned char len = f->opt[optnum].length;
1084+ unsigned char *optend = optp + len;
1085+
1086+ fmatch = FMATCH_OK;
1087+
1088+ if (*optp == OSFOPT_MSS) /* MSS */
1089+ mss = ntohs(*(unsigned short *)(optp+2));
1090+
1091+ if (len != 1)
1092+ {
1093+ /* Skip kind and length fields*/
1094+ optp += 2;
1095+
1096+ if (f->opt[optnum].wc.wc != 0)
1097+ {
1098+ unsigned long tmp = 0;
1099+
1100+ /* Hmmm... It looks a bit ugly. :) */
1101+ memcpy(&tmp, &f->opt[optnum].wc.val,
1102+ (len > sizeof(unsigned long)?
1103+ sizeof(unsigned long):len));
1104+
1105+ tmp = ntohl(tmp);
1106+ if (tmp != f->opt[optnum].wc.val)
1107+ fmatch = FMATCH_OPT_WRONG;
1108+ }
1109+ }
1110+
1111+ optp = optend;
1112+ }
1113+ else
1114+ fmatch = FMATCH_OPT_WRONG;
1115+
1116+ if (fmatch != FMATCH_OK)
1117+ break;
1118+ }
1119+
1120+ if (fmatch != FMATCH_OPT_WRONG)
1121+ {
1122+ fmatch = FMATCH_WRONG;
1123+
1124+ switch (check_WSS)
1125+ {
1126+ case 0:
1127+ if (window == f->wss.val)
1128+ fmatch = FMATCH_OK;
1129+ break;
1130+ case 1: /* MSS */
1131+ if (window == f->wss.val*mss)
1132+ fmatch = FMATCH_OK;
1133+ break;
1134+ case 2: /* MTU */
1135+ if (window == f->wss.val*(mss+40))
1136+ fmatch = FMATCH_OK;
1137+ break;
1138+ case 3: /* MOD */
1139+ if (window % f->wss.val == 0)
1140+ fmatch = FMATCH_OK;
1141+ break;
1142+ }
1143+ }
1144+
1145+
1146+ if (fmatch == FMATCH_OK)
1147+ {
1148+ fcount++;
1149+ log("%s [%s]: %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
1150+ f->genre, f->details,
1151+ NIPQUAD(ip->saddr), ntohs(tcp->source),
1152+ NIPQUAD(ip->daddr), ntohs(tcp->dest));
1153+ if ((info->flags & IPT_OSF_LOG) &&
1154+ info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
1155+ break;
1156+ }
1157+ }
1158+ }
1159+ if (!fcount && (info->flags & IPT_OSF_LOG))
1160+ {
1161+ log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
1162+ if (optp)
1163+ {
1164+ unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
1165+ unsigned int i, optsize;
1166+
1167+ optsize = tcp->doff * 4 - sizeof(struct tcphdr);
1168+ if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
1169+ opt, optsize) < 0)
1170+ loga("TRUNCATED");
1171+ else
1172+ for (i = 0; i < optsize; i++)
1173+ loga("%02X", opt[i]);
1174+
1175+ }
1176+ loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
1177+ NIPQUAD(ip->saddr), ntohs(tcp->source),
1178+ NIPQUAD(ip->daddr), ntohs(tcp->dest));
1179+ }
1180+ read_unlock(&osf_lock);
1181+
1182+ return (fmatch == FMATCH_OK)?1:0;
1183+}
1184+
1185+static int
1186+checkentry(const char *tablename,
1187+ const struct ipt_ip *ip,
1188+ void *matchinfo,
1189+ unsigned int matchsize,
1190+ unsigned int hook_mask)
1191+{
1192+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
1193+ return 0;
1194+ if (ip->proto != IPPROTO_TCP)
1195+ return 0;
1196+
1197+ return 1;
1198+}
1199+
1200+static char * osf_strchr(char *ptr, char c)
1201+{
1202+ char *tmp;
1203+
1204+ tmp = strchr(ptr, c);
1205+
1206+ while (tmp && tmp+1 && isspace(*(tmp+1)))
1207+ tmp++;
1208+
1209+ return tmp;
1210+}
1211+
1212+static struct osf_finger * finger_alloc(void)
1213+{
1214+ struct osf_finger *f;
1215+
1216+ f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
1217+ if (f)
1218+ memset(f, 0, sizeof(struct osf_finger));
1219+
1220+ return f;
1221+}
1222+
1223+static void finger_free(struct osf_finger *f)
1224+{
1225+ memset(f, 0, sizeof(struct osf_finger));
1226+ kfree(f);
1227+}
1228+
1229+
1230+static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
1231+{
1232+ int i, op;
1233+ char *ptr, wc;
1234+ unsigned long val;
1235+
1236+ ptr = &obuf[0];
1237+ i = 0;
1238+ while (ptr != NULL && i < olen)
1239+ {
1240+ val = 0;
1241+ op = 0;
1242+ wc = 0;
1243+ switch (obuf[i])
1244+ {
1245+ case 'N':
1246+ op = OSFOPT_NOP;
1247+ ptr = osf_strchr(&obuf[i], OPTDEL);
1248+ if (ptr)
1249+ {
1250+ *ptr = '\0';
1251+ ptr++;
1252+ i += (int)(ptr-&obuf[i]);
1253+
1254+ }
1255+ else
1256+ i++;
1257+ break;
1258+ case 'S':
1259+ op = OSFOPT_SACKP;
1260+ ptr = osf_strchr(&obuf[i], OPTDEL);
1261+ if (ptr)
1262+ {
1263+ *ptr = '\0';
1264+ ptr++;
1265+ i += (int)(ptr-&obuf[i]);
1266+
1267+ }
1268+ else
1269+ i++;
1270+ break;
1271+ case 'T':
1272+ op = OSFOPT_TS;
1273+ ptr = osf_strchr(&obuf[i], OPTDEL);
1274+ if (ptr)
1275+ {
1276+ *ptr = '\0';
1277+ ptr++;
1278+ i += (int)(ptr-&obuf[i]);
1279+
1280+ }
1281+ else
1282+ i++;
1283+ break;
1284+ case 'W':
1285+ op = OSFOPT_WSO;
1286+ ptr = osf_strchr(&obuf[i], OPTDEL);
1287+ if (ptr)
1288+ {
1289+ switch (obuf[i+1])
1290+ {
1291+ case '%': wc = '%'; break;
1292+ case 'S': wc = 'S'; break;
1293+ case 'T': wc = 'T'; break;
1294+ default: wc = 0; break;
1295+ }
1296+
1297+ *ptr = '\0';
1298+ ptr++;
1299+ if (wc)
1300+ val = simple_strtoul(&obuf[i+2], NULL, 10);
1301+ else
1302+ val = simple_strtoul(&obuf[i+1], NULL, 10);
1303+ i += (int)(ptr-&obuf[i]);
1304+
1305+ }
1306+ else
1307+ i++;
1308+ break;
1309+ case 'M':
1310+ op = OSFOPT_MSS;
1311+ ptr = osf_strchr(&obuf[i], OPTDEL);
1312+ if (ptr)
1313+ {
1314+ if (obuf[i+1] == '%')
1315+ wc = '%';
1316+ *ptr = '\0';
1317+ ptr++;
1318+ if (wc)
1319+ val = simple_strtoul(&obuf[i+2], NULL, 10);
1320+ else
1321+ val = simple_strtoul(&obuf[i+1], NULL, 10);
1322+ i += (int)(ptr-&obuf[i]);
1323+
1324+ }
1325+ else
1326+ i++;
1327+ break;
1328+ case 'E':
1329+ op = OSFOPT_EOL;
1330+ ptr = osf_strchr(&obuf[i], OPTDEL);
1331+ if (ptr)
1332+ {
1333+ *ptr = '\0';
1334+ ptr++;
1335+ i += (int)(ptr-&obuf[i]);
1336+
1337+ }
1338+ else
1339+ i++;
1340+ break;
1341+ default:
1342+ ptr = osf_strchr(&obuf[i], OPTDEL);
1343+ if (ptr)
1344+ {
1345+ ptr++;
1346+ i += (int)(ptr-&obuf[i]);
1347+
1348+ }
1349+ else
1350+ i++;
1351+ break;
1352+ }
1353+
1354+ opt[*optnum].kind = IANA_opts[op].kind;
1355+ opt[*optnum].length = IANA_opts[op].length;
1356+ opt[*optnum].wc.wc = wc;
1357+ opt[*optnum].wc.val = val;
1358+
1359+ (*optnum)++;
1360+ }
1361+}
1362+
1363+static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
1364+{
1365+ struct list_head *ent;
1366+ struct osf_finger *f = NULL;
1367+ int i;
1368+
1369+ *eof = 1;
1370+ count = 0;
1371+
1372+ read_lock_bh(&osf_lock);
1373+ list_for_each(ent, &finger_list)
1374+ {
1375+ f = list_entry(ent, struct osf_finger, flist);
1376+
1377+ log("%s [%s]", f->genre, f->details);
1378+
1379+ count += sprintf(buf+count, "%s - %s[%s] : %s",
1380+ f->genre, f->version,
1381+ f->subtype, f->details);
1382+
1383+ if (f->opt_num)
1384+ {
1385+ loga(" OPT: ");
1386+ //count += sprintf(buf+count, " OPT: ");
1387+ for (i=0; i<f->opt_num; ++i)
1388+ {
1389+ //count += sprintf(buf+count, "%d.%c%lu; ",
1390+ // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
1391+ loga("%d.%c%lu; ",
1392+ f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
1393+ }
1394+ }
1395+ loga("\n");
1396+ count += sprintf(buf+count, "\n");
1397+ }
1398+ read_unlock_bh(&osf_lock);
1399+
1400+ return count;
1401+}
1402+
1403+static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
1404+{
1405+ int cnt;
1406+ unsigned long i;
1407+ char obuf[MAXOPTSTRLEN];
1408+ struct osf_finger *finger;
1409+ struct list_head *ent, *n;
1410+
1411+ char *pbeg, *pend;
1412+
1413+ if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
1414+ {
1415+ int i = 0;
1416+ write_lock_bh(&osf_lock);
1417+ list_for_each_safe(ent, n, &finger_list)
1418+ {
1419+ i++;
1420+ finger = list_entry(ent, struct osf_finger, flist);
1421+ list_del(&finger->flist);
1422+ finger_free(finger);
1423+ }
1424+ write_unlock_bh(&osf_lock);
1425+
1426+ log("Flushed %d entries.\n", i);
1427+
1428+ return count;
1429+ }
1430+
1431+
1432+ cnt = 0;
1433+ for (i=0; i<count && buffer[i] != '\0'; ++i)
1434+ if (buffer[i] == ':')
1435+ cnt++;
1436+
1437+ if (cnt != 8 || i != count)
1438+ {
1439+ log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
1440+ cnt, i, count);
1441+ return count;
1442+ }
1443+
1444+ memset(obuf, 0, sizeof(obuf));
1445+
1446+ finger = finger_alloc();
1447+ if (!finger)
1448+ {
1449+ log("Failed to allocate new fingerprint entry.\n");
1450+ return -ENOMEM;
1451+ }
1452+
1453+ pbeg = (char *)buffer;
1454+ pend = osf_strchr(pbeg, OSFPDEL);
1455+ if (pend)
1456+ {
1457+ *pend = '\0';
1458+ if (pbeg[0] == 'S')
1459+ {
1460+ finger->wss.wc = 'S';
1461+ if (pbeg[1] == '%')
1462+ finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
1463+ else if (pbeg[1] == '*')
1464+ finger->wss.val = 0;
1465+ else
1466+ finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
1467+ }
1468+ else if (pbeg[0] == 'T')
1469+ {
1470+ finger->wss.wc = 'T';
1471+ if (pbeg[1] == '%')
1472+ finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
1473+ else if (pbeg[1] == '*')
1474+ finger->wss.val = 0;
1475+ else
1476+ finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
1477+ }
1478+ if (isdigit(pbeg[0]))
1479+ {
1480+ finger->wss.wc = 0;
1481+ finger->wss.val = simple_strtoul(pbeg, NULL, 10);
1482+ }
1483+
1484+ pbeg = pend+1;
1485+ }
1486+ pend = osf_strchr(pbeg, OSFPDEL);
1487+ if (pend)
1488+ {
1489+ *pend = '\0';
1490+ finger->ttl = simple_strtoul(pbeg, NULL, 10);
1491+ pbeg = pend+1;
1492+ }
1493+ pend = osf_strchr(pbeg, OSFPDEL);
1494+ if (pend)
1495+ {
1496+ *pend = '\0';
1497+ finger->df = simple_strtoul(pbeg, NULL, 10);
1498+ pbeg = pend+1;
1499+ }
1500+ pend = osf_strchr(pbeg, OSFPDEL);
1501+ if (pend)
1502+ {
1503+ *pend = '\0';
1504+ finger->ss = simple_strtoul(pbeg, NULL, 10);
1505+ pbeg = pend+1;
1506+ }
1507+
1508+ pend = osf_strchr(pbeg, OSFPDEL);
1509+ if (pend)
1510+ {
1511+ *pend = '\0';
1512+ cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
1513+ pbeg = pend+1;
1514+ }
1515+
1516+ pend = osf_strchr(pbeg, OSFPDEL);
1517+ if (pend)
1518+ {
1519+ *pend = '\0';
1520+ if (pbeg[0] == '@' || pbeg[0] == '*')
1521+ cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
1522+ else
1523+ cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
1524+ pbeg = pend+1;
1525+ }
1526+
1527+ pend = osf_strchr(pbeg, OSFPDEL);
1528+ if (pend)
1529+ {
1530+ *pend = '\0';
1531+ cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
1532+ pbeg = pend+1;
1533+ }
1534+
1535+ pend = osf_strchr(pbeg, OSFPDEL);
1536+ if (pend)
1537+ {
1538+ *pend = '\0';
1539+ cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
1540+ pbeg = pend+1;
1541+ }
1542+
1543+ cnt = snprintf(finger->details,
1544+ ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
1545+ "%s", pbeg);
1546+
1547+ log("%s - %s[%s] : %s\n",
1548+ finger->genre, finger->version,
1549+ finger->subtype, finger->details);
1550+
1551+ osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
1552+
1553+
1554+ write_lock_bh(&osf_lock);
1555+ list_add_tail(&finger->flist, &finger_list);
1556+ write_unlock_bh(&osf_lock);
1557+
1558+ return count;
1559+}
1560+
1561+static int __init osf_init(void)
1562+{
1563+ int err;
1564+ struct proc_dir_entry *p;
1565+
1566+ log("Startng OS fingerprint matching module.\n");
1567+
1568+ INIT_LIST_HEAD(&finger_list);
1569+
1570+ err = ipt_register_match(&osf_match);
1571+ if (err)
1572+ {
1573+ log("Failed to register OS fingerprint matching module.\n");
1574+ return -ENXIO;
1575+ }
1576+
1577+ p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
1578+ if (!p)
1579+ {
1580+ ipt_unregister_match(&osf_match);
1581+ return -ENXIO;
1582+ }
1583+
1584+ p->write_proc = osf_proc_write;
1585+ p->read_proc = osf_proc_read;
1586+
1587+ return 0;
1588+}
1589+
1590+static void __exit osf_fini(void)
1591+{
1592+ struct list_head *ent, *n;
1593+ struct osf_finger *f;
1594+
1595+ remove_proc_entry("sys/net/ipv4/osf", NULL);
1596+ ipt_unregister_match(&osf_match);
1597+
1598+ list_for_each_safe(ent, n, &finger_list)
1599+ {
1600+ f = list_entry(ent, struct osf_finger, flist);
1601+ list_del(&f->flist);
1602+ finger_free(f);
1603+ }
1604+
1605+ log("OS fingerprint matching module finished.\n");
1606+}
1607+
1608+module_init(osf_init);
1609+module_exit(osf_fini);
1610+
1611+MODULE_LICENSE("GPL");
1612+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
1613+MODULE_DESCRIPTION("Passive OS fingerprint matching.");
1614+
1615diff -Nur linux-2.6.1.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.1/net/ipv4/netfilter/ipt_psd.c
1616--- linux-2.6.1.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
1617+++ linux-2.6.1/net/ipv4/netfilter/ipt_psd.c 2004-01-14 14:04:53.000000000 +0100
1618@@ -0,0 +1,360 @@
1619+/*
1620+ This is a module which is used for PSD (portscan detection)
1621+ Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
1622+ and LOG target module.
1623+
1624+ Copyright (C) 2000,2001 astaro AG
1625+
1626+ This file is distributed under the terms of the GNU General Public
1627+ License (GPL). Copies of the GPL can be obtained from:
1628+ ftp://prep.ai.mit.edu/pub/gnu/GPL
1629+
1630+ 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
1631+ 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
1632+ 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
1633+ 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
1634+ 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
1635+*/
1636+
1637+#include <linux/module.h>
1638+#include <linux/skbuff.h>
1639+#include <linux/ip.h>
1640+#include <net/tcp.h>
1641+#include <linux/spinlock.h>
1642+#include <linux/netfilter_ipv4/ip_tables.h>
1643+#include <linux/netfilter_ipv4/ipt_psd.h>
1644+
1645+#if 0
1646+#define DEBUGP printk
1647+#else
1648+#define DEBUGP(format, args...)
1649+#endif
1650+
1651+MODULE_LICENSE("GPL");
1652+MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
1653+
1654+#define HF_DADDR_CHANGING 0x01
1655+#define HF_SPORT_CHANGING 0x02
1656+#define HF_TOS_CHANGING 0x04
1657+#define HF_TTL_CHANGING 0x08
1658+
1659+/*
1660+ * Information we keep per each target port
1661+ */
1662+struct port {
1663+ u_int16_t number; /* port number */
1664+ u_int8_t proto; /* protocol number */
1665+ u_int8_t and_flags; /* tcp ANDed flags */
1666+ u_int8_t or_flags; /* tcp ORed flags */
1667+};
1668+
1669+/*
1670+ * Information we keep per each source address.
1671+ */
1672+struct host {
1673+ struct host *next; /* Next entry with the same hash */
1674+ clock_t timestamp; /* Last update time */
1675+ struct in_addr src_addr; /* Source address */
1676+ struct in_addr dest_addr; /* Destination address */
1677+ unsigned short src_port; /* Source port */
1678+ int count; /* Number of ports in the list */
1679+ int weight; /* Total weight of ports in the list */
1680+ struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
1681+ unsigned char tos; /* TOS */
1682+ unsigned char ttl; /* TTL */
1683+ unsigned char flags; /* HF_ flags bitmask */
1684+};
1685+
1686+/*
1687+ * State information.
1688+ */
1689+static struct {
1690+ spinlock_t lock;
1691+ struct host list[LIST_SIZE]; /* List of source addresses */
1692+ struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
1693+ int index; /* Oldest entry to be replaced */
1694+} state;
1695+
1696+/*
1697+ * Convert an IP address into a hash table index.
1698+ */
1699+static inline int hashfunc(struct in_addr addr)
1700+{
1701+ unsigned int value;
1702+ int hash;
1703+
1704+ value = addr.s_addr;
1705+ hash = 0;
1706+ do {
1707+ hash ^= value;
1708+ } while ((value >>= HASH_LOG));
1709+
1710+ return hash & (HASH_SIZE - 1);
1711+}
1712+
1713+static int
1714+ipt_psd_match(const struct sk_buff *pskb,
1715+ const struct net_device *in,
1716+ const struct net_device *out,
1717+ const void *matchinfo,
1718+ int offset,
1719+ const void *hdr,
1720+ u_int16_t datalen,
1721+ int *hotdrop)
1722+{
1723+ struct iphdr *ip_hdr;
1724+ struct tcphdr *tcp_hdr;
1725+ struct in_addr addr;
1726+ u_int16_t src_port,dest_port;
1727+ u_int8_t tcp_flags, proto;
1728+ clock_t now;
1729+ struct host *curr, *last, **head;
1730+ int hash, index, count;
1731+
1732+ /* Parameters from userspace */
1733+ const struct ipt_psd_info *psdinfo = matchinfo;
1734+
1735+ /* IP header */
1736+ ip_hdr = pskb->nh.iph;
1737+
1738+ /* Sanity check */
1739+ if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
1740+ DEBUGP("PSD: sanity check failed\n");
1741+ return 0;
1742+ }
1743+
1744+ /* TCP or UDP ? */
1745+ proto = ip_hdr->protocol;
1746+
1747+ if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
1748+ DEBUGP("PSD: protocol not supported\n");
1749+ return 0;
1750+ }
1751+
1752+ /* Get the source address, source & destination ports, and TCP flags */
1753+
1754+ addr.s_addr = ip_hdr->saddr;
1755+
1756+ tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
1757+
1758