]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.1-NF-20040114.patch
- obsolete
[packages/kernel.git] / 2.6.1-NF-20040114.patch
1 diff -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
26 diff -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 */
42 diff -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 */
176 diff -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*/
220 diff -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*/
235 diff -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__ */
252 diff -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*/
296 diff -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  
479 diff -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
526 diff -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);
647 diff -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);
881 diff -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 +
1615 diff -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 +       /* Yep, it´s dirty */
1759 +       src_port = tcp_hdr->source;
1760 +       dest_port = tcp_hdr->dest;
1761 +
1762 +       if (proto == IPPROTO_TCP) {
1763 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
1764 +       }
1765 +       else {
1766 +               tcp_flags = 0x00;
1767 +       }
1768 +
1769 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
1770 +        * them spoof us. [DHCP needs this feature - HW] */
1771 +       if (!addr.s_addr) {
1772 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
1773 +               return 0;
1774 +       }
1775 +
1776 +       /* Use jiffies here not to depend on someone setting the time while we're
1777 +        * running; we need to be careful with possible return value overflows. */
1778 +       now = jiffies;
1779 +
1780 +       spin_lock(&state.lock);
1781 +
1782 +       /* Do we know this source address already? */
1783 +       count = 0;
1784 +       last = NULL;
1785 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
1786 +               do {
1787 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
1788 +                       count++;
1789 +                       if (curr->next) last = curr;
1790 +               } while ((curr = curr->next));
1791 +
1792 +       if (curr) {
1793 +
1794 +               /* We know this address, and the entry isn't too old. Update it. */
1795 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
1796 +                   time_after_eq(now, curr->timestamp)) {
1797 +
1798 +                       /* Just update the appropriate list entry if we've seen this port already */
1799 +                       for (index = 0; index < curr->count; index++) {
1800 +                               if (curr->ports[index].number == dest_port) {
1801 +                                       curr->ports[index].proto = proto;
1802 +                                       curr->ports[index].and_flags &= tcp_flags;
1803 +                                       curr->ports[index].or_flags |= tcp_flags;
1804 +                                       goto out_no_match;
1805 +                               }
1806 +                       }
1807 +
1808 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
1809 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
1810 +                               goto out_no_match;
1811 +
1812 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
1813 +                       curr->timestamp = now;
1814 +
1815 +                       /* Logged this scan already? Then drop the packet. */
1816 +                       if (curr->weight >= psdinfo->weight_threshold)
1817 +                               goto out_match;
1818 +
1819 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
1820 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
1821 +                               curr->flags |= HF_DADDR_CHANGING;
1822 +                       if (curr->src_port != src_port)
1823 +                               curr->flags |= HF_SPORT_CHANGING;
1824 +                       if (curr->tos != ip_hdr->tos)
1825 +                               curr->flags |= HF_TOS_CHANGING;
1826 +                       if (curr->ttl != ip_hdr->ttl)
1827 +                               curr->flags |= HF_TTL_CHANGING;
1828 +
1829 +                       /* Update the total weight */
1830 +                       curr->weight += (ntohs(dest_port) < 1024) ?
1831 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
1832 +
1833 +                       /* Got enough destination ports to decide that this is a scan? */
1834 +                       /* Then log it and drop the packet. */
1835 +                       if (curr->weight >= psdinfo->weight_threshold)
1836 +                               goto out_match;
1837 +
1838 +                       /* Remember the new port */
1839 +                       if (curr->count < SCAN_MAX_COUNT) {
1840 +                               curr->ports[curr->count].number = dest_port;
1841 +                               curr->ports[curr->count].proto = proto;
1842 +                               curr->ports[curr->count].and_flags = tcp_flags;
1843 +                               curr->ports[curr->count].or_flags = tcp_flags;
1844 +                               curr->count++;
1845 +                       }
1846 +
1847 +                       goto out_no_match;
1848 +               }
1849 +
1850 +               /* We know this address, but the entry is outdated. Mark it unused, and
1851 +                * remove from the hash table. We'll allocate a new entry instead since
1852 +                * this one might get re-used too soon. */
1853 +               curr->src_addr.s_addr = 0;
1854 +               if (last)
1855 +                       last->next = last->next->next;
1856 +               else if (*head)
1857 +                       *head = (*head)->next;
1858 +               last = NULL;
1859 +       }
1860 +
1861 +       /* We don't need an ACK from a new source address */
1862 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
1863 +               goto out_no_match;
1864 +
1865 +       /* Got too many source addresses with the same hash value? Then remove the
1866 +        * oldest one from the hash table, so that they can't take too much of our
1867 +        * CPU time even with carefully chosen spoofed IP addresses. */
1868 +       if (count >= HASH_MAX && last) last->next = NULL;
1869 +
1870 +       /* We're going to re-use the oldest list entry, so remove it from the hash
1871 +        * table first (if it is really already in use, and isn't removed from the
1872 +        * hash table already because of the HASH_MAX check above). */
1873 +
1874 +       /* First, find it */
1875 +       if (state.list[state.index].src_addr.s_addr)
1876 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
1877 +       else
1878 +               head = &last;
1879 +       last = NULL;
1880 +       if ((curr = *head))
1881 +       do {
1882 +               if (curr == &state.list[state.index]) break;
1883 +               last = curr;
1884 +       } while ((curr = curr->next));
1885 +
1886 +       /* Then, remove it */
1887 +       if (curr) {
1888 +               if (last)
1889 +                       last->next = last->next->next;
1890 +               else if (*head)
1891 +                       *head = (*head)->next;
1892 +       }
1893 +
1894 +       /* Get our list entry */
1895 +       curr = &state.list[state.index++];
1896 +       if (state.index >= LIST_SIZE) state.index = 0;
1897 +
1898 +       /* Link it into the hash table */
1899 +       head = &state.hash[hash];
1900 +       curr->next = *head;
1901 +       *head = curr;
1902 +
1903 +       /* And fill in the fields */
1904 +       curr->timestamp = now;
1905 +       curr->src_addr = addr;
1906 +       curr->dest_addr.s_addr = ip_hdr->daddr;
1907 +       curr->src_port = src_port;
1908 +       curr->count = 1;
1909 +       curr->weight = (ntohs(dest_port) < 1024) ?
1910 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
1911 +       curr->ports[0].number = dest_port;
1912 +       curr->ports[0].proto = proto;
1913 +       curr->ports[0].and_flags = tcp_flags;
1914 +       curr->ports[0].or_flags = tcp_flags;
1915 +       curr->tos = ip_hdr->tos;
1916 +       curr->ttl = ip_hdr->ttl;
1917 +
1918 +out_no_match:
1919 +       spin_unlock(&state.lock);
1920 +       return 0;
1921 +
1922 +out_match:
1923 +       spin_unlock(&state.lock);
1924 +       return 1;
1925 +}
1926 +
1927 +static int ipt_psd_checkentry(const char *tablename,
1928 +                             const struct ipt_ip *e,
1929 +                             void *matchinfo,
1930 +                             unsigned int matchsize,
1931 +                             unsigned int hook_mask)
1932 +{
1933 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
1934 +
1935 +       /* we accept TCP only */
1936 +/*     if (e->ip.proto != IPPROTO_TCP) { */
1937 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
1938 +/*             return 0; */
1939 +/*     } */
1940 +
1941 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
1942 +               DEBUGP("PSD: matchsize %u != %u\n",
1943 +                      matchsize,
1944 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
1945 +               return 0;
1946 +       }
1947 +
1948 +       return 1;
1949 +}
1950 +
1951 +static struct ipt_match ipt_psd_reg = { 
1952 +       .name           = "psd",
1953 +       .match          = ipt_psd_match,
1954 +       .checkentry     = ipt_psd_checkentry,
1955 +       .me             = THIS_MODULE,
1956 +};
1957 +
1958 +static int __init init(void)
1959 +{
1960 +       if (ipt_register_match(&ipt_psd_reg))
1961 +               return -EINVAL;
1962 +
1963 +       memset(&state, 0, sizeof(state));
1964 +
1965 +       spin_lock_init(&(state.lock));
1966 +
1967 +       printk("netfilter PSD loaded - (c) astaro AG\n");
1968 +       return 0;
1969 +}
1970 +
1971 +static void __exit fini(void)
1972 +{
1973 +       ipt_unregister_match(&ipt_psd_reg);
1974 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
1975 +}
1976 +
1977 +module_init(init);
1978 +module_exit(fini);
1979 diff -Nur linux-2.6.1.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.1/net/ipv4/netfilter/ipt_quota.c
1980 --- linux-2.6.1.org/net/ipv4/netfilter/ipt_quota.c      1970-01-01 01:00:00.000000000 +0100
1981 +++ linux-2.6.1/net/ipv4/netfilter/ipt_quota.c  2004-01-14 14:04:22.000000000 +0100
1982 @@ -0,0 +1,85 @@
1983 +/* 
1984 + * netfilter module to enforce network quotas
1985 + *
1986 + * Sam Johnston <samj@samj.net>
1987 + */
1988 +#include <linux/module.h>
1989 +#include <linux/skbuff.h>
1990 +#include <linux/spinlock.h>
1991 +#include <linux/interrupt.h>
1992 +
1993 +#include <linux/netfilter_ipv4/ip_tables.h>
1994 +#include <linux/netfilter_ipv4/ipt_quota.h>
1995 +
1996 +MODULE_LICENSE("GPL");
1997 +
1998 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
1999 +
2000 +static int
2001 +match(const struct sk_buff *skb,
2002 +      const struct net_device *in,
2003 +      const struct net_device *out,
2004 +      const void *matchinfo,
2005 +      int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
2006 +{
2007 +
2008 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
2009 +
2010 +        spin_lock_bh(&quota_lock);
2011 +
2012 +        if (q->quota >= datalen) {
2013 +                /* we can afford this one */
2014 +                q->quota -= datalen;
2015 +                spin_unlock_bh(&quota_lock);
2016 +
2017 +#ifdef DEBUG_IPT_QUOTA
2018 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
2019 +#endif
2020 +                return 1;
2021 +        }
2022 +
2023 +        /* so we do not allow even small packets from now on */
2024 +        q->quota = 0;
2025 +
2026 +#ifdef DEBUG_IPT_QUOTA
2027 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
2028 +#endif
2029 +
2030 +        spin_unlock_bh(&quota_lock);
2031 +        return 0;
2032 +}
2033 +
2034 +static int
2035 +checkentry(const char *tablename,
2036 +           const struct ipt_ip *ip,
2037 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
2038 +{
2039 +        /* TODO: spinlocks? sanity checks? */
2040 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
2041 +                return 0;
2042 +
2043 +        return 1;
2044 +}
2045 +
2046 +static struct ipt_match quota_match = {
2047 +       .name           = "quota",
2048 +       .match          = &match,
2049 +       .checkentry     = &checkentry,
2050 +       .me             = THIS_MODULE,
2051 +};
2052 +
2053 +static int __init
2054 +init(void)
2055 +{
2056 +        return ipt_register_match(&quota_match);
2057 +}
2058 +
2059 +static void __exit
2060 +fini(void)
2061 +{
2062 +        ipt_unregister_match(&quota_match);
2063 +}
2064 +
2065 +module_init(init);
2066 +module_exit(fini);
2067 +
2068 diff -Nur linux-2.6.1.org/net/ipv4/netfilter/ipt_time.c linux-2.6.1/net/ipv4/netfilter/ipt_time.c
2069 --- linux-2.6.1.org/net/ipv4/netfilter/ipt_time.c       1970-01-01 01:00:00.000000000 +0100
2070 +++ linux-2.6.1/net/ipv4/netfilter/ipt_time.c   2004-01-14 14:05:44.000000000 +0100
2071 @@ -0,0 +1,189 @@
2072 +/*
2073 +  This is a module which is used for time matching
2074 +  It is using some modified code from dietlibc (localtime() function)
2075 +  that you can find at http://www.fefe.de/dietlibc/
2076 +  This file is distributed under the terms of the GNU General Public
2077 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
2078 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
2079 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
2080 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
2081 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
2082 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
2083 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
2084 +*/
2085 +
2086 +#include <linux/module.h>
2087 +#include <linux/skbuff.h>
2088 +#include <linux/netfilter_ipv4/ip_tables.h>
2089 +#include <linux/netfilter_ipv4/ipt_time.h>
2090 +#include <linux/time.h>
2091 +
2092 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
2093 +MODULE_DESCRIPTION("Match arrival timestamp");
2094 +MODULE_LICENSE("GPL");
2095 +
2096 +struct tm
2097 +{
2098 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
2099 +       int tm_min;                   /* Minutes.     [0-59] */
2100 +       int tm_hour;                  /* Hours.       [0-23] */
2101 +       int tm_mday;                  /* Day.         [1-31] */
2102 +       int tm_mon;                   /* Month.       [0-11] */
2103 +       int tm_year;                  /* Year - 1900.  */
2104 +       int tm_wday;                  /* Day of week. [0-6] */
2105 +       int tm_yday;                  /* Days in year.[0-365] */
2106 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
2107 +
2108 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
2109 +       const char *tm_zone;          /* we don't care, we count from GMT */
2110 +};
2111 +
2112 +void
2113 +localtime(const time_t *timepr, struct tm *r);
2114 +
2115 +static int
2116 +match(const struct sk_buff *skb,
2117 +      const struct net_device *in,
2118 +      const struct net_device *out,
2119 +      const void *matchinfo,
2120 +      int offset,
2121 +      const void *hdr,
2122 +      u_int16_t datalen,
2123 +      int *hotdrop)
2124 +{
2125 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
2126 +       struct tm currenttime;                          /* time human readable */
2127 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
2128 +       u_int16_t packet_time;
2129 +       struct timeval kerneltimeval;
2130 +       time_t packet_local_time;
2131 +
2132 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
2133 +       if (info->kerneltime)
2134 +       {
2135 +               do_gettimeofday(&kerneltimeval);
2136 +               packet_local_time = kerneltimeval.tv_sec;
2137 +       }
2138 +       else
2139 +               packet_local_time = skb->stamp.tv_sec;
2140 +
2141 +       /* Transform the timestamp of the packet, in a human readable form */
2142 +       localtime(&packet_local_time, &currenttime);
2143 +
2144 +       /* check if we match this timestamp, we start by the days... */
2145 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
2146 +               return 0; /* the day doesn't match */
2147 +
2148 +       /* ... check the time now */
2149 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
2150 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
2151 +               return 0;
2152 +
2153 +       /* here we match ! */
2154 +       return 1;
2155 +}
2156 +
2157 +static int
2158 +checkentry(const char *tablename,
2159 +           const struct ipt_ip *ip,
2160 +           void *matchinfo,
2161 +           unsigned int matchsize,
2162 +           unsigned int hook_mask)
2163 +{
2164 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
2165 +
2166 +       /* First, check that we are in the correct hook */
2167 +       /* PRE_ROUTING, LOCAL_IN or FROWARD */
2168 +       if (hook_mask
2169 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
2170 +       {
2171 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
2172 +               return 0;
2173 +       }
2174 +       /* we use the kerneltime if we are in forward or output */
2175 +       info->kerneltime = 1;
2176 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
2177 +               /* if not, we use the skb time */
2178 +               info->kerneltime = 0;
2179 +
2180 +       /* Check the size */
2181 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
2182 +               return 0;
2183 +       /* Now check the coherence of the data ... */
2184 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
2185 +           (info->time_stop  > 1439))
2186 +       {
2187 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
2188 +               return 0;
2189 +       }
2190 +
2191 +       return 1;
2192 +}
2193 +
2194 +static struct ipt_match time_match = {
2195 +       .name           = "time",
2196 +       .match          = &match,
2197 +       .checkentry     = &checkentry,
2198 +       .me             = THIS_MODULE,
2199 + };
2200 +
2201 +static int __init init(void)
2202 +{
2203 +       printk("ipt_time loading\n");
2204 +       return ipt_register_match(&time_match);
2205 +}
2206 +
2207 +static void __exit fini(void)
2208 +{
2209 +       ipt_unregister_match(&time_match);
2210 +       printk("ipt_time unloaded\n");
2211 +}
2212 +
2213 +module_init(init);
2214 +module_exit(fini);
2215 +
2216 +
2217 +/* The part below is borowed and modified from dietlibc */
2218 +
2219 +/* seconds per day */
2220 +#define SPD 24*60*60
2221 +
2222 +void
2223 +localtime(const time_t *timepr, struct tm *r) {
2224 +       time_t i;
2225 +       time_t timep;
2226 +       extern struct timezone sys_tz;
2227 +       const unsigned int __spm[12] =
2228 +               { 0,
2229 +                 (31),
2230 +                 (31+28),
2231 +                 (31+28+31),
2232 +                 (31+28+31+30),
2233 +                 (31+28+31+30+31),
2234 +                 (31+28+31+30+31+30),
2235 +                 (31+28+31+30+31+30+31),
2236 +                 (31+28+31+30+31+30+31+31),
2237 +                 (31+28+31+30+31+30+31+31+30),
2238 +                 (31+28+31+30+31+30+31+31+30+31),
2239 +                 (31+28+31+30+31+30+31+31+30+31+30),
2240 +               };
2241 +       register time_t work;
2242 +
2243 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
2244 +       work=timep%(SPD);
2245 +       r->tm_sec=work%60; work/=60;
2246 +       r->tm_min=work%60; r->tm_hour=work/60;
2247 +       work=timep/(SPD);
2248 +       r->tm_wday=(4+work)%7;
2249 +       for (i=1970; ; ++i) {
2250 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
2251 +               if (work>k)
2252 +                       work-=k;
2253 +               else
2254 +                       break;
2255 +       }
2256 +       r->tm_year=i-1900;
2257 +       for (i=11; i && __spm[i]>work; --i) ;
2258 +       r->tm_mon=i;
2259 +       r->tm_mday=work-__spm[i]+1;
2260 +}
2261 diff -Nur linux-2.6.1.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.1/net/ipv4/netfilter/ipt_u32.c
2262 --- linux-2.6.1.org/net/ipv4/netfilter/ipt_u32.c        1970-01-01 01:00:00.000000000 +0100
2263 +++ linux-2.6.1/net/ipv4/netfilter/ipt_u32.c    2004-01-14 14:05:13.000000000 +0100
2264 @@ -0,0 +1,215 @@
2265 +/* Kernel module to match u32 packet content. */
2266 +
2267 +/* 
2268 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
2269 +have specified values.  The specification of what to extract is general 
2270 +enough to find data at given offsets from tcp headers or payloads.
2271 +
2272 + --u32 tests
2273 + The argument amounts to a program in a small language described below.
2274 + tests := location = value |  tests && location = value
2275 + value := range | value , range
2276 + range := number | number : number
2277 +  a single number, n, is interpreted the same as n:n
2278 +  n:m is interpreted as the range of numbers >=n and <=m
2279 + location := number | location operator number
2280 + operator := & | << | >> | @
2281 +
2282 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
2283 + membership operator and the value syntax describes a set.  The @ operator
2284 + is what allows moving to the next header and is described further below.
2285 +
2286 + *** Until I can find out how to avoid it, there are some artificial limits
2287 + on the size of the tests:
2288 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
2289 + - no more than 10 ranges (and 9 commas) per value
2290 + - no more than 10 numbers (and 9 operators) per location
2291 +
2292 + To describe the meaning of location, imagine the following machine that
2293 + interprets it.  There are three registers:
2294 +  A is of type char*, initially the address of the IP header
2295 +  B and C are unsigned 32 bit integers, initially zero
2296 +
2297 +  The instructions are:
2298 +   number      B = number;
2299 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
2300 +   &number     C = C&number
2301 +   <<number    C = C<<number
2302 +   >>number    C = C>>number
2303 +   @number     A = A+C; then do the instruction number
2304 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
2305 +  Otherwise the result of the computation is the final value of C.
2306 +
2307 + Whitespace is allowed but not required in the tests.
2308 + However the characters that do occur there are likely to require
2309 + shell quoting, so it's a good idea to enclose the arguments in quotes.
2310 +
2311 +Example:
2312 + match IP packets with total length >= 256
2313 + The IP header contains a total length field in bytes 2-3.
2314 + --u32 "0&0xFFFF=0x100:0xFFFF" 
2315 + read bytes 0-3
2316 + AND that with FFFF (giving bytes 2-3),
2317 + and test whether that's in the range [0x100:0xFFFF]
2318 +
2319 +Example: (more realistic, hence more complicated)
2320 + match icmp packets with icmp type 0
2321 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
2322 + --u32 "6&0xFF=1 && ...
2323 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
2324 + Next test that it's not a fragment.
2325 +  (If so it might be part of such a packet but we can't always tell.)
2326 +  n.b. This test is generally needed if you want to match anything
2327 +  beyond the IP header.
2328 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
2329 + packet (not a fragment).  Alternatively, you can allow first fragments
2330 + by only testing the last 5 bits of byte 6.
2331 + ... 4&0x3FFF=0 && ...
2332 + Last test: the first byte past the IP header (the type) is 0
2333 + This is where we have to use the @syntax.  The length of the IP header
2334 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
2335 + IP header itself.
2336 + ... 0>>22&0x3C@0>>24=0"
2337 + The first 0 means read bytes 0-3,
2338 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
2339 +   the first byte, so only 22 bits is four times that plus a few more bits.
2340 + &3C then eliminates the two extra bits on the right and the first four 
2341 + bits of the first byte.
2342 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
2343 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
2344 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
2345 + @ means to use this number as a new offset into the packet, and read
2346 + four bytes starting from there.  This is the first 4 bytes of the icmp
2347 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
2348 + the value 24 to the right to throw out all but the first byte and compare
2349 + the result with 0.
2350 +
2351 +Example: 
2352 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
2353 + First we test that the packet is a tcp packet (similar to icmp).
2354 + --u32 "6&0xFF=6 && ...
2355 + Next, test that it's not a fragment (same as above).
2356 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
2357 + 0>>22&3C as above computes the number of bytes in the IP header.
2358 + @ makes this the new offset into the packet, which is the start of the
2359 + tcp header.  The length of the tcp header (again in 32 bit words) is
2360 + the left half of byte 12 of the tcp header.  The 12>>26&3C
2361 + computes this length in bytes (similar to the IP header before).
2362 + @ makes this the new offset, which is the start of the tcp payload.
2363 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
2364 + result is any of 1, 2, 5 or 8
2365 +*/
2366 +
2367 +#include <linux/module.h>
2368 +#include <linux/skbuff.h>
2369 +
2370 +#include <linux/netfilter_ipv4/ipt_u32.h>
2371 +#include <linux/netfilter_ipv4/ip_tables.h>
2372 +
2373 +/* #include <asm-i386/timex.h> for timing */
2374 +
2375 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
2376 +MODULE_DESCRIPTION("IP tables u32 matching module");
2377 +MODULE_LICENSE("GPL");
2378 +
2379 +static int
2380 +match(const struct sk_buff *skb,
2381 +      const struct net_device *in,
2382 +      const struct net_device *out,
2383 +      const void *matchinfo,
2384 +      int offset,
2385 +      const void *hdr,
2386 +      u_int16_t datalen,
2387 +      int *hotdrop)
2388 +{
2389 +       const struct ipt_u32 *data = matchinfo;
2390 +       int testind, i;
2391 +       unsigned char* origbase = (char*)skb->nh.iph;
2392 +       unsigned char* base = origbase;
2393 +       unsigned char* head = skb->head;
2394 +       unsigned char* end = skb->end;
2395 +       int nnums, nvals;
2396 +       u_int32_t pos, val;
2397 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
2398 +          cycles1 = get_cycles(); */
2399 +
2400 +       for (testind=0; testind < data->ntests; testind++) {
2401 +               base = origbase; /* reset for each test */
2402 +               pos = data->tests[testind].location[0].number;
2403 +               if (base+pos+3 > end || base+pos < head) 
2404 +                       return 0;
2405 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
2406 +                       (base[pos+2]<<8) + base[pos+3];
2407 +               nnums = data->tests[testind].nnums;
2408 +               for (i=1; i < nnums; i++) {
2409 +                       u_int32_t number = data->tests[testind].location[i].number;
2410 +                       switch (data->tests[testind].location[i].nextop) {
2411 +                       case IPT_U32_AND: 
2412 +                               val = val & number; 
2413 +                               break;
2414 +                       case IPT_U32_LEFTSH: 
2415 +                               val = val << number;
2416 +                               break;
2417 +                       case IPT_U32_RIGHTSH: 
2418 +                               val = val >> number; 
2419 +                               break;
2420 +                       case IPT_U32_AT:
2421 +                               base = base + val;
2422 +                               pos = number;
2423 +                               if (base+pos+3 > end || base+pos < head) 
2424 +                                       return 0;
2425 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
2426 +                                       (base[pos+2]<<8) + base[pos+3];
2427 +                               break;
2428 +                       }
2429 +               }
2430 +               nvals = data->tests[testind].nvalues;
2431 +               for (i=0; i < nvals; i++) {
2432 +                       if ((data->tests[testind].value[i].min <= val) &&
2433 +                           (val <= data->tests[testind].value[i].max)) {
2434 +                               break;
2435 +                       }
2436 +               }
2437 +               if (i >= data->tests[testind].nvalues) {
2438 +                       /* cycles2 = get_cycles(); 
2439 +                          printk("failed %d in %d cycles\n", testind, 
2440 +                                 cycles2-cycles1); */
2441 +                       return 0;
2442 +               }
2443 +       }
2444 +       /* cycles2 = get_cycles();
2445 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
2446 +       return 1;
2447 +}
2448 +
2449 +static int
2450 +checkentry(const char *tablename,
2451 +           const struct ipt_ip *ip,
2452 +           void *matchinfo,
2453 +           unsigned int matchsize,
2454 +           unsigned int hook_mask)
2455 +{
2456 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
2457 +               return 0;
2458 +       return 1;
2459 +}
2460 +
2461 +static struct ipt_match u32_match = {
2462 +       .name           = "u32",
2463 +       .match          = &match,
2464 +       .checkenrty     = &checkentry,
2465 +       .me             = THIS_MODULE,
2466 + };
2467 +
2468 +static int __init init(void)
2469 +{
2470 +       return ipt_register_match(&u32_match);
2471 +}
2472 +
2473 +static void __exit fini(void)
2474 +{
2475 +       ipt_unregister_match(&u32_match);
2476 +}
2477 +
2478 +module_init(init);
2479 +module_exit(fini);
This page took 0.307114 seconds and 3 git commands to generate.