]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.6-rc1-patch-o-matic-ng-extra-20040419.patch
- replaced by linux-2.4-sfq.patch
[packages/kernel.git] / 2.6.6-rc1-patch-o-matic-ng-extra-20040419.patch
CommitLineData
1a035623 1diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack.h
2--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-19 10:38:50.000000000 +0200
3+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-19 10:44:16.000000000 +0200
4@@ -207,6 +207,10 @@
5 } nat;
6 #endif /* CONFIG_IP_NF_NAT_NEEDED */
7
8+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
9+ unsigned long mark;
10+#endif
11+
12 };
13
14 /* get master conntrack via master expectation */
15diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
16--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-15 03:35:20.000000000 +0200
17+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ip_conntrack_tuple.h 2004-04-19 10:46:18.000000000 +0200
18@@ -25,6 +25,9 @@
19 struct {
20 u_int16_t id;
21 } icmp;
22+ struct {
23+ u_int16_t port;
24+ } sctp;
25 };
26
27 /* The manipulable part of the tuple. */
28@@ -55,6 +58,9 @@
29 struct {
30 u_int8_t type, code;
31 } icmp;
32+ struct {
33+ u_int16_t port;
34+ } sctp;
35 } u;
36
37 /* The protocol. */
38diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h
39--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
40+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-19 10:44:16.000000000 +0200
41@@ -0,0 +1,25 @@
42+#ifndef _IPT_CONNMARK_H_target
43+#define _IPT_CONNMARK_H_target
44+
45+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
46+ * by Henrik Nordstrom <hno@marasystems.com>
47+ *
48+ * This program is free software; you can redistribute it and/or modify
49+ * it under the terms of the GNU General Public License as published by
50+ * the Free Software Foundation; either version 2 of the License, or
51+ * (at your option) any later version.
52+ */
53+
54+enum {
55+ IPT_CONNMARK_SET = 0,
56+ IPT_CONNMARK_SAVE,
57+ IPT_CONNMARK_RESTORE
58+};
59+
60+struct ipt_connmark_target_info {
61+ unsigned long mark;
62+ unsigned long mask;
63+ u_int8_t mode;
64+};
65+
66+#endif /*_IPT_CONNMARK_H_target*/
67diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h
68--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_IPMARK.h 1970-01-01 01:00:00.000000000 +0100
69+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_IPMARK.h 2004-04-19 10:44:26.000000000 +0200
70@@ -0,0 +1,13 @@
71+#ifndef _IPT_IPMARK_H_target
72+#define _IPT_IPMARK_H_target
73+
74+struct ipt_ipmark_target_info {
75+ unsigned long andmask;
76+ unsigned long ormask;
77+ unsigned int addr;
78+};
79+
80+#define IPT_IPMARK_SRC 0
81+#define IPT_IPMARK_DST 1
82+
83+#endif /*_IPT_IPMARK_H_target*/
84diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_XOR.h
85--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_XOR.h 1970-01-01 01:00:00.000000000 +0100
86+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_XOR.h 2004-04-19 10:44:34.000000000 +0200
87@@ -0,0 +1,9 @@
88+#ifndef _IPT_XOR_H
89+#define _IPT_XOR_H
90+
91+struct ipt_XOR_info {
92+ char key[30];
93+ u_int8_t block_size;
94+};
95+
96+#endif /* _IPT_XOR_H */
97diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h
98--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_addrtype.h 1970-01-01 01:00:00.000000000 +0100
99+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-19 10:44:36.000000000 +0200
100@@ -0,0 +1,11 @@
101+#ifndef _IPT_ADDRTYPE_H
102+#define _IPT_ADDRTYPE_H
103+
104+struct ipt_addrtype_info {
105+ u_int16_t source; /* source-type mask */
106+ u_int16_t dest; /* dest-type mask */
107+ int invert_source;
108+ int invert_dest;
109+};
110+
111+#endif
112diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_connmark.h
113--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
114+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-19 10:44:16.000000000 +0200
115@@ -0,0 +1,18 @@
116+#ifndef _IPT_CONNMARK_H
117+#define _IPT_CONNMARK_H
118+
119+/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
120+ * by Henrik Nordstrom <hno@marasystems.com>
121+ *
122+ * This program is free software; you can redistribute it and/or modify
123+ * it under the terms of the GNU General Public License as published by
124+ * the Free Software Foundation; either version 2 of the License, or
125+ * (at your option) any later version.
126+ */
127+
128+struct ipt_connmark_info {
129+ unsigned long mark, mask;
130+ u_int8_t invert;
131+};
132+
133+#endif /*_IPT_CONNMARK_H*/
134diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_policy.h
135--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_policy.h 1970-01-01 01:00:00.000000000 +0100
136+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_policy.h 2004-04-19 10:46:16.000000000 +0200
137@@ -0,0 +1,52 @@
138+#ifndef _IPT_POLICY_H
139+#define _IPT_POLICY_H
140+
141+#define POLICY_MAX_ELEM 4
142+
143+enum ipt_policy_flags
144+{
145+ POLICY_MATCH_IN = 0x1,
146+ POLICY_MATCH_OUT = 0x2,
147+ POLICY_MATCH_NONE = 0x4,
148+ POLICY_MATCH_STRICT = 0x8,
149+};
150+
151+enum ipt_policy_modes
152+{
153+ POLICY_MODE_TRANSPORT,
154+ POLICY_MODE_TUNNEL
155+};
156+
157+struct ipt_policy_spec
158+{
159+ u_int8_t saddr:1,
160+ daddr:1,
161+ proto:1,
162+ mode:1,
163+ spi:1,
164+ reqid:1;
165+};
166+
167+struct ipt_policy_elem
168+{
169+ u_int32_t saddr;
170+ u_int32_t smask;
171+ u_int32_t daddr;
172+ u_int32_t dmask;
173+ u_int32_t spi;
174+ u_int32_t reqid;
175+ u_int8_t proto;
176+ u_int8_t mode;
177+
178+ struct ipt_policy_spec match;
179+ struct ipt_policy_spec invert;
180+};
181+
182+struct ipt_policy_info
183+{
184+ struct ipt_policy_elem pol[POLICY_MAX_ELEM];
185+ u_int16_t flags;
186+ u_int16_t len;
187+};
188+
189+#endif /* _IPT_POLICY_H */
190diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_string.h
191--- linux-2.6.6-rc1.org/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
192+++ linux-2.6.6-rc1/include/linux/netfilter_ipv4/ipt_string.h 2004-04-19 10:47:23.000000000 +0200
193@@ -0,0 +1,21 @@
194+#ifndef _IPT_STRING_H
195+#define _IPT_STRING_H
196+
197+/* *** PERFORMANCE TWEAK ***
198+ * Packet size and search string threshold,
199+ * above which sublinear searches is used. */
200+#define IPT_STRING_HAYSTACK_THRESH 100
201+#define IPT_STRING_NEEDLE_THRESH 20
202+
203+#define BM_MAX_NLEN 256
204+#define BM_MAX_HLEN 1024
205+
206+typedef char *(*proc_ipt_search) (char *, char *, int, int);
207+
208+struct ipt_string_info {
209+ char string[BM_MAX_NLEN];
210+ u_int16_t invert;
211+ u_int16_t len;
212+};
213+
214+#endif /* _IPT_STRING_H */
215diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/tcp.h linux-2.6.6-rc1/include/net/tcp.h
216--- linux-2.6.6-rc1.org/include/net/tcp.h 2004-04-15 03:33:55.000000000 +0200
217+++ linux-2.6.6-rc1/include/net/tcp.h 2004-04-19 10:46:08.000000000 +0200
218@@ -162,6 +162,7 @@
219 extern void tcp_bucket_unlock(struct sock *sk);
220 extern int tcp_port_rover;
221 extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
222+extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
223
224 /* These are AF independent. */
225 static __inline__ int tcp_bhashfn(__u16 lport)
226diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/include/net/udp.h linux-2.6.6-rc1/include/net/udp.h
227--- linux-2.6.6-rc1.org/include/net/udp.h 2004-04-15 03:35:20.000000000 +0200
228+++ linux-2.6.6-rc1/include/net/udp.h 2004-04-19 10:46:08.000000000 +0200
229@@ -74,6 +74,8 @@
230 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
231 extern int udp_disconnect(struct sock *sk, int flags);
232
233+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
234+
235 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
236 #define UDP_INC_STATS(field) SNMP_INC_STATS(udp_statistics, field)
237 #define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
238diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/linux-2.6.4/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc1/linux-2.6.4/net/ipv4/netfilter/ipt_unclean.c
239--- linux-2.6.6-rc1.org/linux-2.6.4/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
240+++ linux-2.6.6-rc1/linux-2.6.4/net/ipv4/netfilter/ipt_unclean.c 2004-04-19 10:47:06.000000000 +0200
241@@ -0,0 +1,604 @@
242+/* Kernel module to match suspect packets. */
243+#include <linux/module.h>
244+#include <linux/skbuff.h>
245+#include <linux/ip.h>
246+#include <linux/udp.h>
247+#include <linux/tcp.h>
248+#include <linux/icmp.h>
249+#include <net/checksum.h>
250+
251+#include <linux/netfilter_ipv4/ip_tables.h>
252+
253+#define limpk(format, args...) \
254+do { \
255+ if (net_ratelimit()) \
256+ printk("ipt_unclean: %s" format, \
257+ embedded ? "(embedded packet) " : "" , ## args); \
258+} while(0)
259+
260+enum icmp_error_status
261+{
262+ ICMP_MAY_BE_ERROR,
263+ ICMP_IS_ERROR,
264+ ICMP_NOT_ERROR
265+};
266+
267+struct icmp_info
268+{
269+ size_t min_len, max_len;
270+ enum icmp_error_status err;
271+ u_int8_t min_code, max_code;
272+};
273+
274+static int
275+check_ip(struct iphdr *iph, size_t length, int embedded);
276+
277+/* ICMP-specific checks. */
278+static int
279+check_icmp(const struct icmphdr *icmph,
280+ u_int16_t datalen,
281+ unsigned int offset,
282+ int more_frags,
283+ int embedded)
284+{
285+ static struct icmp_info info[]
286+ = { [ICMP_ECHOREPLY]
287+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
288+ [ICMP_DEST_UNREACH]
289+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
290+ [ICMP_SOURCE_QUENCH]
291+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
292+ [ICMP_REDIRECT]
293+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
294+ [ICMP_ECHO]
295+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
296+ /* Router advertisement. */
297+ [9]
298+ = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
299+ /* Router solicitation. */
300+ [10]
301+ = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
302+ [ICMP_TIME_EXCEEDED]
303+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
304+ [ICMP_PARAMETERPROB]
305+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
306+ [ICMP_TIMESTAMP]
307+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
308+ [ICMP_TIMESTAMPREPLY]
309+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
310+ [ICMP_INFO_REQUEST]
311+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
312+ [ICMP_INFO_REPLY]
313+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
314+ [ICMP_ADDRESS]
315+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
316+ [ICMP_ADDRESSREPLY]
317+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
318+
319+ /* Can't do anything if it's a fragment. */
320+ if (offset)
321+ return 1;
322+
323+ /* Must cover type and code. */
324+ if (datalen < 2) {
325+ limpk("ICMP len=%u too short\n", datalen);
326+ return 0;
327+ }
328+
329+ /* If not embedded. */
330+ if (!embedded) {
331+ /* Bad checksum? Don't print, just ignore. */
332+ if (!more_frags
333+ && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
334+ return 0;
335+
336+ /* CHECK: Truncated ICMP (even if first fragment). */
337+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
338+ && info[icmph->type].min_len != 0
339+ && datalen < info[icmph->type].min_len) {
340+ limpk("ICMP type %u len %u too short\n",
341+ icmph->type, datalen);
342+ return 0;
343+ }
344+
345+ /* CHECK: Check within known error ICMPs. */
346+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
347+ && info[icmph->type].err == ICMP_IS_ERROR) {
348+ /* CHECK: Embedded packet must be at least
349+ length of iph + 8 bytes. */
350+ struct iphdr *inner = (void *)icmph + 8;
351+
352+ /* datalen > 8 since all ICMP_IS_ERROR types
353+ have min length > 8 */
354+ if (datalen - 8 < sizeof(struct iphdr)) {
355+ limpk("ICMP error internal way too short\n");
356+ return 0;
357+ }
358+ if (datalen - 8 < inner->ihl*4 + 8) {
359+ limpk("ICMP error internal too short\n");
360+ return 0;
361+ }
362+ if (!check_ip(inner, datalen - 8, 1))
363+ return 0;
364+ }
365+ } else {
366+ /* CHECK: Can't embed ICMP unless known non-error. */
367+ if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
368+ || info[icmph->type].err != ICMP_NOT_ERROR) {
369+ limpk("ICMP type %u not embeddable\n",
370+ icmph->type);
371+ return 0;
372+ }
373+ }
374+
375+ /* CHECK: Invalid ICMP codes. */
376+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
377+ && (icmph->code < info[icmph->type].min_code
378+ || icmph->code > info[icmph->type].max_code)) {
379+ limpk("ICMP type=%u code=%u\n",
380+ icmph->type, icmph->code);
381+ return 0;
382+ }
383+
384+ /* CHECK: Above maximum length. */
385+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
386+ && info[icmph->type].max_len != 0
387+ && datalen > info[icmph->type].max_len) {
388+ limpk("ICMP type=%u too long: %u bytes\n",
389+ icmph->type, datalen);
390+ return 0;
391+ }
392+
393+ switch (icmph->type) {
394+ case ICMP_PARAMETERPROB: {
395+ /* CHECK: Problem param must be within error packet's
396+ * IP header. */
397+ struct iphdr *iph = (void *)icmph + 8;
398+ u_int32_t arg = ntohl(icmph->un.gateway);
399+
400+ if (icmph->code == 0) {
401+ /* Code 0 means that upper 8 bits is pointer
402+ to problem. */
403+ if ((arg >> 24) >= iph->ihl*4) {
404+ limpk("ICMP PARAMETERPROB ptr = %u\n",
405+ ntohl(icmph->un.gateway) >> 24);
406+ return 0;
407+ }
408+ arg &= 0x00FFFFFF;
409+ }
410+
411+ /* CHECK: Rest must be zero. */
412+ if (arg) {
413+ limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
414+ arg);
415+ return 0;
416+ }
417+ break;
418+ }
419+
420+ case ICMP_TIME_EXCEEDED:
421+ case ICMP_SOURCE_QUENCH:
422+ /* CHECK: Unused must be zero. */
423+ if (icmph->un.gateway != 0) {
424+ limpk("ICMP type=%u unused = %u\n",
425+ icmph->type, ntohl(icmph->un.gateway));
426+ return 0;
427+ }
428+ break;
429+ }
430+
431+ return 1;
432+}
433+
434+/* UDP-specific checks. */
435+static int
436+check_udp(const struct iphdr *iph,
437+ const struct udphdr *udph,
438+ u_int16_t datalen,
439+ unsigned int offset,
440+ int more_frags,
441+ int embedded)
442+{
443+ /* Can't do anything if it's a fragment. */
444+ if (offset)
445+ return 1;
446+
447+ /* CHECK: Must cover UDP header. */
448+ if (datalen < sizeof(struct udphdr)) {
449+ limpk("UDP len=%u too short\n", datalen);
450+ return 0;
451+ }
452+
453+ /* Bad checksum? Don't print, just say it's unclean. */
454+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
455+ if (!more_frags && !embedded && udph->check
456+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
457+ csum_partial((char *)udph, datalen, 0)) != 0)
458+ return 0;
459+
460+ /* CHECK: Destination port can't be zero. */
461+ if (!udph->dest) {
462+ limpk("UDP zero destination port\n");
463+ return 0;
464+ }
465+
466+ if (!more_frags) {
467+ if (!embedded) {
468+ /* CHECK: UDP length must match. */
469+ if (ntohs(udph->len) != datalen) {
470+ limpk("UDP len too short %u vs %u\n",
471+ ntohs(udph->len), datalen);
472+ return 0;
473+ }
474+ } else {
475+ /* CHECK: UDP length be >= this truncated pkt. */
476+ if (ntohs(udph->len) < datalen) {
477+ limpk("UDP len too long %u vs %u\n",
478+ ntohs(udph->len), datalen);
479+ return 0;
480+ }
481+ }
482+ } else {
483+ /* CHECK: UDP length must be > this frag's length. */
484+ if (ntohs(udph->len) <= datalen) {
485+ limpk("UDP fragment len too short %u vs %u\n",
486+ ntohs(udph->len), datalen);
487+ return 0;
488+ }
489+ }
490+
491+ return 1;
492+}
493+
494+#define TH_FIN 0x01
495+#define TH_SYN 0x02
496+#define TH_RST 0x04
497+#define TH_PUSH 0x08
498+#define TH_ACK 0x10
499+#define TH_URG 0x20
500+#define TH_ECE 0x40
501+#define TH_CWR 0x80
502+
503+/* table of valid flag combinations - ECE and CWR are always valid */
504+static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
505+{
506+ [TH_SYN] = 1,
507+ [TH_SYN|TH_ACK] = 1,
508+ [TH_RST] = 1,
509+ [TH_RST|TH_ACK] = 1,
510+ [TH_RST|TH_ACK|TH_PUSH] = 1,
511+ [TH_FIN|TH_ACK] = 1,
512+ [TH_ACK] = 1,
513+ [TH_ACK|TH_PUSH] = 1,
514+ [TH_ACK|TH_URG] = 1,
515+ [TH_ACK|TH_URG|TH_PUSH] = 1,
516+ [TH_FIN|TH_ACK|TH_PUSH] = 1,
517+ [TH_FIN|TH_ACK|TH_URG] = 1,
518+ [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
519+};
520+
521+/* TCP-specific checks. */
522+static int
523+check_tcp(const struct iphdr *iph,
524+ const struct tcphdr *tcph,
525+ u_int16_t datalen,
526+ unsigned int offset,
527+ int more_frags,
528+ int embedded)
529+{
530+ u_int8_t *opt = (u_int8_t *)tcph;
531+ u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
532+ u_int8_t tcpflags;
533+ int end_of_options = 0;
534+ size_t i;
535+
536+ /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
537+ /* In fact, this is caught below (offset < 516). */
538+
539+ /* Can't do anything if it's a fragment. */
540+ if (offset)
541+ return 1;
542+
543+ /* CHECK: Smaller than minimal TCP hdr. */
544+ if (datalen < sizeof(struct tcphdr)) {
545+ if (!embedded) {
546+ limpk("Packet length %u < TCP header.\n", datalen);
547+ return 0;
548+ }
549+ /* Must have ports available (datalen >= 8), from
550+ check_icmp which set embedded = 1 */
551+ /* CHECK: TCP ports inside ICMP error */
552+ if (!tcph->source || !tcph->dest) {
553+ limpk("Zero TCP ports %u/%u.\n",
554+ htons(tcph->source), htons(tcph->dest));
555+ return 0;
556+ }
557+ return 1;
558+ }
559+
560+ /* CHECK: Smaller than actual TCP hdr. */
561+ if (datalen < tcph->doff * 4) {
562+ if (!embedded) {
563+ limpk("Packet length %u < actual TCP header.\n",
564+ datalen);
565+ return 0;
566+ } else
567+ return 1;
568+ }
569+
570+ /* Bad checksum? Don't print, just say it's unclean. */
571+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
572+ if (!more_frags && !embedded
573+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
574+ csum_partial((char *)tcph, datalen, 0)) != 0)
575+ return 0;
576+
577+ /* CHECK: TCP ports non-zero */
578+ if (!tcph->source || !tcph->dest) {
579+ limpk("Zero TCP ports %u/%u.\n",
580+ htons(tcph->source), htons(tcph->dest));
581+ return 0;
582+ }
583+
584+ /* CHECK: TCP reserved bits zero. */
585+ if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
586+ limpk("TCP reserved bits not zero\n");
587+ return 0;
588+ }
589+
590+ /* CHECK: TCP flags. */
591+ tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
592+ if (!tcp_valid_flags[tcpflags]) {
593+ limpk("TCP flags bad: %u\n", tcpflags);
594+ return 0;
595+ }
596+
597+ for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
598+ switch (opt[i]) {
599+ case 0:
600+ end_of_options = 1;
601+ i++;
602+ break;
603+ case 1:
604+ i++;
605+ break;
606+ default:
607+ /* CHECK: options after EOO. */
608+ if (end_of_options) {
609+ limpk("TCP option %u after end\n",
610+ opt[i]);
611+ return 0;
612+ }
613+ /* CHECK: options at tail. */
614+ else if (i+1 >= tcph->doff * 4) {
615+ limpk("TCP option %u at tail\n",
616+ opt[i]);
617+ return 0;
618+ }
619+ /* CHECK: zero-length options. */
620+ else if (opt[i+1] == 0) {
621+ limpk("TCP option %u 0 len\n",
622+ opt[i]);
623+ return 0;
624+ }
625+ /* CHECK: oversize options. */
626+ else if (&opt[i] + opt[i+1] > endhdr) {
627+ limpk("TCP option %u at %Zu too long\n",
628+ (unsigned int) opt[i], i);
629+ return 0;
630+ }
631+ /* Move to next option */
632+ i += opt[i+1];
633+ }
634+ }
635+
636+ return 1;
637+}
638+
639+/* Returns 1 if ok */
640+/* Standard IP checks. */
641+static int
642+check_ip(struct iphdr *iph, size_t length, int embedded)
643+{
644+ u_int8_t *opt = (u_int8_t *)iph;
645+ u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
646+ int end_of_options = 0;
647+ void *protoh;
648+ size_t datalen;
649+ unsigned int i;
650+ unsigned int offset;
651+
652+ /* Should only happen for local outgoing raw-socket packets. */
653+ /* CHECK: length >= ip header. */
654+ if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
655+ limpk("Packet length %Zu < IP header.\n", length);
656+ return 0;
657+ }
658+
659+ offset = ntohs(iph->frag_off) & IP_OFFSET;
660+ protoh = (void *)iph + iph->ihl * 4;
661+ datalen = length - iph->ihl * 4;
662+
663+ /* CHECK: Embedded fragment. */
664+ if (embedded && offset) {
665+ limpk("Embedded fragment.\n");
666+ return 0;
667+ }
668+
669+ for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
670+ switch (opt[i]) {
671+ case 0:
672+ end_of_options = 1;
673+ i++;
674+ break;
675+ case 1:
676+ i++;
677+ break;
678+ default:
679+ /* CHECK: options after EOO. */
680+ if (end_of_options) {
681+ limpk("IP option %u after end\n",
682+ opt[i]);
683+ return 0;
684+ }
685+ /* CHECK: options at tail. */
686+ else if (i+1 >= iph->ihl * 4) {
687+ limpk("IP option %u at tail\n",
688+ opt[i]);
689+ return 0;
690+ }
691+ /* CHECK: zero-length or one-length options. */
692+ else if (opt[i+1] < 2) {
693+ limpk("IP option %u %u len\n",
694+ opt[i], opt[i+1]);
695+ return 0;
696+ }
697+ /* CHECK: oversize options. */
698+ else if (&opt[i] + opt[i+1] > endhdr) {
699+ limpk("IP option %u at %u too long\n",
700+ opt[i], i);
701+ return 0;
702+ }
703+ /* Move to next option */
704+ i += opt[i+1];
705+ }
706+ }
707+
708+ /* Fragment checks. */
709+
710+ /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
711+ if ((ntohs(iph->frag_off) & IP_MF)
712+ && (ntohs(iph->tot_len) % 8) != 0) {
713+ limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
714+ return 0;
715+ }
716+
717+ /* CHECK: Oversize fragment a-la Ping of Death. */
718+ if (offset * 8 + datalen > 65535) {
719+ limpk("Oversize fragment to %u.\n", offset * 8);
720+ return 0;
721+ }
722+
723+ /* CHECK: DF set and offset or MF set. */
724+ if ((ntohs(iph->frag_off) & IP_DF)
725+ && (offset || (ntohs(iph->frag_off) & IP_MF))) {
726+ limpk("DF set and offset=%u, MF=%u.\n",
727+ offset, ntohs(iph->frag_off) & IP_MF);
728+ return 0;
729+ }
730+
731+ /* CHECK: Zero-sized fragments. */
732+ if ((offset || (ntohs(iph->frag_off) & IP_MF))
733+ && datalen == 0) {
734+ limpk("Zero size fragment offset=%u\n", offset);
735+ return 0;
736+ }
737+
738+ /* Note: we can have even middle fragments smaller than this:
739+ consider a large packet passing through a 600MTU then
740+ 576MTU link: this gives a fragment of 24 data bytes. But
741+ everyone packs fragments largest first, hence a fragment
742+ can't START before 576 - MAX_IP_HEADER_LEN. */
743+
744+ /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
745+ down to 128 (576 taken from RFC 791: All hosts must be
746+ prepared to accept datagrams of up to 576 octets). Use 128
747+ here. */
748+#define MIN_LIKELY_MTU 128
749+ /* CHECK: Min size of first frag = 128. */
750+ if ((ntohs(iph->frag_off) & IP_MF)
751+ && offset == 0
752+ && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
753+ limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
754+ MIN_LIKELY_MTU);
755+ return 0;
756+ }
757+
758+ /* CHECK: Min offset of frag = 128 - IP hdr len. */
759+ if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
760+ limpk("Fragment starts at %u < %u\n", offset * 8,
761+ MIN_LIKELY_MTU - iph->ihl * 4);
762+ return 0;
763+ }
764+
765+ /* CHECK: Protocol specification non-zero. */
766+ if (iph->protocol == 0) {
767+ limpk("Zero protocol\n");
768+ return 0;
769+ }
770+
771+ /* CHECK: Do not use what is unused.
772+ * First bit of fragmentation flags should be unused.
773+ * May be used by OS fingerprinting tools.
774+ * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
775+ */
776+ if (ntohs(iph->frag_off)>>15) {
777+ limpk("IP unused bit set\n");
778+ return 0;
779+ }
780+
781+ /* Per-protocol checks. */
782+ switch (iph->protocol) {
783+ case IPPROTO_ICMP:
784+ return check_icmp(protoh, datalen, offset,
785+ (ntohs(iph->frag_off) & IP_MF),
786+ embedded);
787+
788+ case IPPROTO_UDP:
789+ return check_udp(iph, protoh, datalen, offset,
790+ (ntohs(iph->frag_off) & IP_MF),
791+ embedded);
792+
793+ case IPPROTO_TCP:
794+ return check_tcp(iph, protoh, datalen, offset,
795+ (ntohs(iph->frag_off) & IP_MF),
796+ embedded);
797+ default:
798+ /* Ignorance is bliss. */
799+ return 1;
800+ }
801+}
802+
803+static int
804+match(const struct sk_buff *skb,
805+ const struct net_device *in,
806+ const struct net_device *out,
807+ const void *matchinfo,
808+ int offset,
809+ const void *hdr,
810+ u_int16_t datalen,
811+ int *hotdrop)
812+{
813+ return !check_ip(skb->nh.iph, skb->len, 0);
814+}
815+
816+/* Called when user tries to insert an entry of this type. */
817+static int
818+checkentry(const char *tablename,
819+ const struct ipt_ip *ip,
820+ void *matchinfo,
821+ unsigned int matchsize,
822+ unsigned int hook_mask)
823+{
824+ if (matchsize != IPT_ALIGN(0))
825+ return 0;
826+
827+ return 1;
828+}
829+
830+static struct ipt_match unclean_match
831+= { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
832+
833+static int __init init(void)
834+{
835+ return ipt_register_match(&unclean_match);
836+}
837+
838+static void __exit fini(void)
839+{
840+ ipt_unregister_match(&unclean_match);
841+}
842+
843+module_init(init);
844+module_exit(fini);
845+MODULE_LICENSE("GPL");
846diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc1/net/ipv4/netfilter/Kconfig
847--- linux-2.6.6-rc1.org/net/ipv4/netfilter/Kconfig 2004-04-19 10:38:53.000000000 +0200
848+++ linux-2.6.6-rc1/net/ipv4/netfilter/Kconfig 2004-04-19 10:47:23.000000000 +0200
849@@ -206,6 +206,11 @@
850
851 To compile it as a module, choose M here. If unsure, say N.
852
853+config IP_NF_MATCH_UNCLEAN
854+ tristate 'unclean match support (EXPERIMENTAL)'
855+ depends on EXPERIMENTAL && IP_NF_IPTABLES
856+ help
857+
858 config IP_NF_MATCH_TTL
859 tristate "TTL match support"
860 depends on IP_NF_IPTABLES
861@@ -701,5 +706,56 @@
862 depends on IP_NF_IPTABLES
863 help
864
865+config IP_NF_CONNTRACK_MARK
866+ bool 'Connection mark tracking support'
867+config IP_NF_TARGET_CONNMARK
868+ tristate 'CONNMARK target support'
869+ depends on IP_NF_MANGLE
870+config IP_NF_MATCH_CONNMARK
871+ tristate ' Connection mark match support'
872+ depends on IP_NF_IPTABLES
873+ help
874+
875+config IP_NF_TARGET_IPMARK
876+ tristate 'IPMARK target support'
877+ depends on IP_NF_MANGLE
878+ help
879+
880+config IP_NF_TARGET_TARPIT
881+ tristate 'TARPIT target support'
882+ depends on IP_NF_FILTER
883+ help
884+
885+config IP_NF_TARGET_XOR
886+ tristate 'XOR target support'
887+ depends on IP_NF_MANGLE
888+ help
889+
890+config IP_NF_MATCH_ADDRTYPE
891+ tristate 'address type match support'
892+ depends on IP_NF_IPTABLES
893+ help
894+
895+config IP_NF_MATCH_POLICY
896+ tristate "IPsec policy match support"
897+ depends on IP_NF_IPTABLES && XFRM
898+ help
899+ Policy matching allows you to match packets based on the
900+ IPsec policy that was used during decapsulation/will
901+ be used during encapsulation.
902+
903+ To compile it as a module, choose M here. If unsure, say N.
904+ help
905+
906+config IP_NF_CT_PROTO_SCTP
907+ tristate 'SCTP protocol connection tracking support'
908+ depends on IP_NF_CONNTRACK
909+ help
910+
911+config IP_NF_MATCH_STRING
912+ tristate 'String match support'
913+ depends on IP_NF_IPTABLES
914+ help
915+
916 endmenu
917
918diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc1/net/ipv4/netfilter/Makefile
919--- linux-2.6.6-rc1.org/net/ipv4/netfilter/Makefile 2004-04-19 10:38:53.000000000 +0200
920+++ linux-2.6.6-rc1/net/ipv4/netfilter/Makefile 2004-04-19 10:47:23.000000000 +0200
921@@ -19,6 +19,9 @@
922 # connection tracking
923 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
924
925+# SCTP protocol connection tracking
926+obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
927+
928 # connection tracking helpers
929 obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
930 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
931@@ -87,14 +90,19 @@
932 obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
933
934
935+obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
936+obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
937 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
938 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
939+obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
940 obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
941 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
942 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
943+obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
944 obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
945
946 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
947+obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
948
949 # targets
950 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
951@@ -102,6 +110,8 @@
952 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
953 obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
954 obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
955+obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
956+obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
957 obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
958 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
959 obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
960@@ -110,6 +120,8 @@
961 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
962 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
963 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
964+obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
965+obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
966 obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
967 obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
968 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
969diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_core.c
970--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-19 10:38:53.000000000 +0200
971+++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_core.c 2004-04-19 10:44:16.000000000 +0200
972@@ -717,6 +717,9 @@
973 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
974 conntrack->master = expected;
975 expected->sibling = conntrack;
976+#if CONFIG_IP_NF_CONNTRACK_MARK
977+ conntrack->mark = expected->expectant->mark;
978+#endif
979 LIST_DELETE(&ip_conntrack_expect_list, expected);
980 expected->expectant->expecting--;
981 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
982diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
983--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 1970-01-01 01:00:00.000000000 +0100
984+++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_proto_sctp.c 2004-04-19 10:46:18.000000000 +0200
985@@ -0,0 +1,529 @@
986+/*
987+ * Connection tracking protocol helper module for SCTP.
988+ *
989+ * SCTP is defined in RFC 2960. References to various sections in this code
990+ * are to this RFC.
991+ *
992+ * This program is free software; you can redistribute it and/or modify
993+ * it under the terms of the GNU General Public License version 2 as
994+ * published by the Free Software Foundation.
995+ */
996+
997+#include <linux/types.h>
998+#include <linux/sched.h>
999+#include <linux/timer.h>
1000+#include <linux/netfilter.h>
1001+#include <linux/module.h>
1002+#include <linux/in.h>
1003+#include <linux/ip.h>
1004+#include <linux/sctp.h>
1005+#include <linux/string.h>
1006+
1007+#include <linux/netfilter_ipv4/ip_conntrack.h>
1008+#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
1009+#include <linux/netfilter_ipv4/lockhelp.h>
1010+
1011+#if 0
1012+#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
1013+#else
1014+#define DEBUGP(format, args...)
1015+#endif
1016+
1017+/* Protects conntrack->proto.sctp */
1018+static DECLARE_RWLOCK(sctp_lock);
1019+
1020+/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
1021+ closely. They're more complex. --RR
1022+
1023+ And so for me for SCTP :D -Kiran */
1024+
1025+static const char *sctp_conntrack_names[] = {
1026+ "NONE",
1027+ "CLOSED",
1028+ "COOKIE_WAIT",
1029+ "COOKIE_ECHOED",
1030+ "ESTABLISHED",
1031+ "SHUTDOWN_SENT",
1032+ "SHUTDOWN_RECD",
1033+ "SHUTDOWN_ACK_SENT",
1034+};
1035+
1036+#define SECS * HZ
1037+#define MINS * 60 SECS
1038+#define HOURS * 60 MINS
1039+#define DAYS * 24 HOURS
1040+
1041+unsigned long ip_ct_sctp_timeout_closed = 10 SECS;
1042+unsigned long ip_ct_sctp_timeout_cookie_wait = 3 SECS;
1043+unsigned long ip_ct_sctp_timeout_cookie_echoed = 3 SECS;
1044+unsigned long ip_ct_sctp_timeout_established = 5 DAYS;
1045+unsigned long ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000;
1046+unsigned long ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000;
1047+unsigned long ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS;
1048+
1049+static unsigned long * sctp_timeouts[]
1050+= { 0, /* SCTP_CONNTRACK_NONE */
1051+ &ip_ct_sctp_timeout_closed, /* SCTP_CONNTRACK_CLOSED */
1052+ &ip_ct_sctp_timeout_cookie_wait, /* SCTP_CONNTRACK_COOKIE_WAIT */
1053+ &ip_ct_sctp_timeout_cookie_echoed, /* SCTP_CONNTRACK_COOKIE_ECHOED */
1054+ &ip_ct_sctp_timeout_established, /* SCTP_CONNTRACK_ESTABLISHED */
1055+ &ip_ct_sctp_timeout_shutdown_sent, /* SCTP_CONNTRACK_SHUTDOWN_SENT */
1056+ &ip_ct_sctp_timeout_shutdown_recd, /* SCTP_CONNTRACK_SHUTDOWN_RECD */
1057+ &ip_ct_sctp_timeout_shutdown_ack_sent /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
1058+ };
1059+
1060+#define sNO SCTP_CONNTRACK_NONE
1061+#define sCL SCTP_CONNTRACK_CLOSED
1062+#define sCW SCTP_CONNTRACK_COOKIE_WAIT
1063+#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
1064+#define sES SCTP_CONNTRACK_ESTABLISHED
1065+#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
1066+#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
1067+#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
1068+#define sIV SCTP_CONNTRACK_MAX
1069+
1070+/*
1071+ These are the descriptions of the states:
1072+
1073+NOTE: These state names are tantalizingly similar to the states of an
1074+SCTP endpoint. But the interpretation of the states is a little different,
1075+considering that these are the states of the connection and not of an end
1076+point. Please note the subtleties. -Kiran
1077+
1078+NONE - Nothing so far.
1079+COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
1080+ an INIT_ACK chunk in the reply direction.
1081+COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
1082+ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
1083+SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
1084+SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
1085+SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
1086+ to that of the SHUTDOWN chunk.
1087+CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
1088+ the SHUTDOWN chunk. Connection is closed.
1089+*/
1090+
1091+/* TODO
1092+ - I have assumed that the first INIT is in the original direction.
1093+ This messes things when an INIT comes in the reply direction in CLOSED
1094+ state.
1095+ - Check the error type in the reply dir before transitioning from
1096+cookie echoed to closed.
1097+ - Sec 5.2.4 of RFC 2960
1098+ - Multi Homing support.
1099+*/
1100+
1101+/* SCTP conntrack state transitions */
1102+static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
1103+ {
1104+/* ORIGINAL */
1105+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
1106+/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
1107+/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
1108+/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
1109+/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
1110+/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
1111+/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
1112+/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
1113+/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
1114+/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
1115+ },
1116+ {
1117+/* REPLY */
1118+/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
1119+/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
1120+/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
1121+/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
1122+/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
1123+/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
1124+/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
1125+/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
1126+/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
1127+/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
1128+ }
1129+};
1130+
1131+static int sctp_pkt_to_tuple(const struct sk_buff *skb,
1132+ unsigned int dataoff,
1133+ struct ip_conntrack_tuple *tuple)
1134+{
1135+ sctp_sctphdr_t hdr;
1136+
1137+ DEBUGP(__FUNCTION__);
1138+ DEBUGP("\n");
1139+
1140+ /* Actually only need first 8 bytes. */
1141+ if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
1142+ return 0;
1143+
1144+ tuple->src.u.sctp.port = hdr.source;
1145+ tuple->dst.u.sctp.port = hdr.dest;
1146+
1147+ return 1;
1148+}
1149+
1150+static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
1151+ const struct ip_conntrack_tuple *orig)
1152+{
1153+ DEBUGP(__FUNCTION__);
1154+ DEBUGP("\n");
1155+
1156+ tuple->src.u.sctp.port = orig->dst.u.sctp.port;
1157+ tuple->dst.u.sctp.port = orig->src.u.sctp.port;
1158+ return 1;
1159+}
1160+
1161+/* Print out the per-protocol part of the tuple. */
1162+static unsigned int sctp_print_tuple(char *buffer,
1163+ const struct ip_conntrack_tuple *tuple)
1164+{
1165+ DEBUGP(__FUNCTION__);
1166+ DEBUGP("\n");
1167+
1168+ return sprintf(buffer, "sport=%hu dport=%hu ",
1169+ ntohs(tuple->src.u.sctp.port),
1170+ ntohs(tuple->dst.u.sctp.port));
1171+}
1172+
1173+/* Print out the private part of the conntrack. */
1174+static unsigned int sctp_print_conntrack(char *buffer,
1175+ const struct ip_conntrack *conntrack)
1176+{
1177+ enum sctp_conntrack state;
1178+
1179+ DEBUGP(__FUNCTION__);
1180+ DEBUGP("\n");
1181+
1182+ READ_LOCK(&sctp_lock);
1183+ state = conntrack->proto.sctp.state;
1184+ READ_UNLOCK(&sctp_lock);
1185+
1186+ return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
1187+}
1188+
1189+#define for_each_sctp_chunk(skb, sch, offset, count) \
1190+for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0; \
1191+ offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch)); \
1192+ offset += (htons(sch.length) + 3) & ~3, count++)
1193+
1194+/* Some validity checks to make sure the chunks are fine */
1195+static int do_basic_checks(struct ip_conntrack *conntrack,
1196+ const struct sk_buff *skb,
1197+ char *map)
1198+{
1199+ u_int32_t offset, count;
1200+ sctp_chunkhdr_t sch;
1201+ int flag;
1202+
1203+ DEBUGP(__FUNCTION__);
1204+ DEBUGP("\n");
1205+
1206+ flag = 0;
1207+
1208+ for_each_sctp_chunk (skb, sch, offset, count) {
1209+ DEBUGP("Chunk Num: %d Type: %d\n", count, sch.type);
1210+
1211+ if (sch.type == SCTP_CID_INIT
1212+ || sch.type == SCTP_CID_INIT_ACK
1213+ || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
1214+ flag = 1;
1215+ }
1216+
1217+ /* Cookie Ack/Echo chunks not the first OR
1218+ Init / Init Ack / Shutdown compl chunks not the only chunks */
1219+ if ((sch.type == SCTP_CID_COOKIE_ACK
1220+ || sch.type == SCTP_CID_COOKIE_ECHO
1221+ || flag)
1222+ && count !=0 ) {
1223+ DEBUGP("Basic checks failed\n");
1224+ return 1;
1225+ }
1226+
1227+ if (map) {
1228+ set_bit (sch.type, (void *)map);
1229+ }
1230+ }
1231+
1232+ DEBUGP("Basic checks passed\n");
1233+ return 0;
1234+}
1235+
1236+static int new_state(enum ip_conntrack_dir dir,
1237+ enum sctp_conntrack cur_state,
1238+ int chunk_type)
1239+{
1240+ int i;
1241+
1242+ DEBUGP(__FUNCTION__);
1243+ DEBUGP("\n");
1244+
1245+ DEBUGP("Chunk type: %d\n", chunk_type);
1246+
1247+ switch (chunk_type) {
1248+ case SCTP_CID_INIT:
1249+ DEBUGP("SCTP_CID_INIT\n");
1250+ i = 0; break;
1251+ case SCTP_CID_INIT_ACK:
1252+ DEBUGP("SCTP_CID_INIT_ACK\n");
1253+ i = 1; break;
1254+ case SCTP_CID_ABORT:
1255+ DEBUGP("SCTP_CID_ABORT\n");
1256+ i = 2; break;
1257+ case SCTP_CID_SHUTDOWN:
1258+ DEBUGP("SCTP_CID_SHUTDOWN\n");
1259+ i = 3; break;
1260+ case SCTP_CID_SHUTDOWN_ACK:
1261+ DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
1262+ i = 4; break;
1263+ case SCTP_CID_ERROR:
1264+ DEBUGP("SCTP_CID_ERROR\n");
1265+ i = 5; break;
1266+ case SCTP_CID_COOKIE_ECHO:
1267+ DEBUGP("SCTP_CID_COOKIE_ECHO\n");
1268+ i = 6; break;
1269+ case SCTP_CID_COOKIE_ACK:
1270+ DEBUGP("SCTP_CID_COOKIE_ACK\n");
1271+ i = 7; break;
1272+ case SCTP_CID_SHUTDOWN_COMPLETE:
1273+ DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
1274+ i = 8; break;
1275+ default:
1276+ /* Other chunks like DATA, SACK, HEARTBEAT and
1277+ its ACK do not cause a change in state */
1278+ DEBUGP("Unknown chunk type, Will stay in %s\n",
1279+ sctp_conntrack_names[cur_state]);
1280+ return cur_state;
1281+ }
1282+
1283+ DEBUGP("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
1284+ dir, sctp_conntrack_names[cur_state], chunk_type,
1285+ sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
1286+
1287+ return sctp_conntracks[dir][i][cur_state];
1288+}
1289+
1290+/* Returns verdict for packet, or -1 for invalid. */
1291+static int sctp_packet(struct ip_conntrack *conntrack,
1292+ const struct sk_buff *skb,
1293+ enum ip_conntrack_info ctinfo)
1294+{
1295+ enum sctp_conntrack newconntrack, oldsctpstate;
1296+ sctp_sctphdr_t sctph;
1297+ sctp_chunkhdr_t sch;
1298+ u_int32_t offset, count;
1299+ char map[256 / sizeof (char)] = {0};
1300+
1301+ DEBUGP(__FUNCTION__);
1302+ DEBUGP("\n");
1303+
1304+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
1305+ return -1;
1306+
1307+ if (do_basic_checks(conntrack, skb, map) != 0)
1308+ return -1;
1309+
1310+ /* Check the verification tag (Sec 8.5) */
1311+ if (!test_bit(SCTP_CID_INIT, (void *)map)
1312+ && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
1313+ && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
1314+ && !test_bit(SCTP_CID_ABORT, (void *)map)
1315+ && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
1316+ && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
1317+ DEBUGP("Verification tag check failed\n");
1318+ return -1;
1319+ }
1320+
1321+ oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
1322+ for_each_sctp_chunk (skb, sch, offset, count) {
1323+ WRITE_LOCK(&sctp_lock);
1324+
1325+ /* Special cases of Verification tag check (Sec 8.5.1) */
1326+ if (sch.type == SCTP_CID_INIT) {
1327+ /* Sec 8.5.1 (A) */
1328+ if (sctph.vtag != 0) {
1329+ WRITE_UNLOCK(&sctp_lock);
1330+ return -1;
1331+ }
1332+ } else if (sch.type == SCTP_CID_ABORT) {
1333+ /* Sec 8.5.1 (B) */
1334+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
1335+ && !(sctph.vtag == conntrack->proto.sctp.vtag
1336+ [1 - CTINFO2DIR(ctinfo)])) {
1337+ WRITE_UNLOCK(&sctp_lock);
1338+ return -1;
1339+ }
1340+ } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
1341+ /* Sec 8.5.1 (C) */
1342+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
1343+ && !(sctph.vtag == conntrack->proto.sctp.vtag
1344+ [1 - CTINFO2DIR(ctinfo)]
1345+ && (sch.flags & 1))) {
1346+ WRITE_UNLOCK(&sctp_lock);
1347+ return -1;
1348+ }
1349+ } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
1350+ /* Sec 8.5.1 (D) */
1351+ if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
1352+ WRITE_UNLOCK(&sctp_lock);
1353+ return -1;
1354+ }
1355+ }
1356+
1357+ oldsctpstate = conntrack->proto.sctp.state;
1358+ newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
1359+
1360+ /* Invalid */
1361+ if (newconntrack == SCTP_CONNTRACK_MAX) {
1362+ DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
1363+ CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
1364+ WRITE_UNLOCK(&sctp_lock);
1365+ return -1;
1366+ }
1367+
1368+ /* If it is an INIT or an INIT ACK note down the vtag */
1369+ if (sch.type == SCTP_CID_INIT
1370+ || sch.type == SCTP_CID_INIT_ACK) {
1371+ sctp_inithdr_t inithdr;
1372+
1373+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
1374+ &inithdr, sizeof(inithdr)) != 0) {
1375+ WRITE_UNLOCK(&sctp_lock);
1376+ return -1;
1377+ }
1378+ DEBUGP("Setting vtag %x for dir %d\n",
1379+ inithdr.init_tag, CTINFO2DIR(ctinfo));
1380+ conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
1381+ }
1382+
1383+ conntrack->proto.sctp.state = newconntrack;
1384+ WRITE_UNLOCK(&sctp_lock);
1385+ }
1386+
1387+ ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
1388+
1389+ if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
1390+ && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
1391+ && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
1392+ DEBUGP("Setting assured bit\n");
1393+ set_bit(IPS_ASSURED_BIT, &conntrack->status);
1394+ }
1395+
1396+ return NF_ACCEPT;
1397+}
1398+
1399+/* Called when a new connection for this protocol found. */
1400+static int sctp_new(struct ip_conntrack *conntrack,
1401+ const struct sk_buff *skb)
1402+{
1403+ enum sctp_conntrack newconntrack;
1404+ sctp_sctphdr_t sctph;
1405+ sctp_chunkhdr_t sch;
1406+ u_int32_t offset, count;
1407+ char map[256 / sizeof (char)] = {0};
1408+
1409+ DEBUGP(__FUNCTION__);
1410+ DEBUGP("\n");
1411+
1412+ if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
1413+ return -1;
1414+
1415+ if (do_basic_checks(conntrack, skb, map) != 0)
1416+ return -1;
1417+
1418+ /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
1419+ if ((test_bit (SCTP_CID_ABORT, (void *)map))
1420+ || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
1421+ || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
1422+ return -1;
1423+ }
1424+
1425+ newconntrack = SCTP_CONNTRACK_MAX;
1426+ for_each_sctp_chunk (skb, sch, offset, count) {
1427+ /* Don't need lock here: this conntrack not in circulation yet */
1428+ newconntrack = new_state (IP_CT_DIR_ORIGINAL,
1429+ SCTP_CONNTRACK_NONE, sch.type);
1430+
1431+ /* Invalid: delete conntrack */
1432+ if (newconntrack == SCTP_CONNTRACK_MAX) {
1433+ DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
1434+ return 0;
1435+ }
1436+
1437+ /* Copy the vtag into the state info */
1438+ if (sch.type == SCTP_CID_INIT) {
1439+ if (sctph.vtag == 0) {
1440+ sctp_inithdr_t inithdr;
1441+
1442+ if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
1443+ &inithdr, sizeof(inithdr)) != 0) {
1444+ return -1;
1445+ }
1446+
1447+ DEBUGP("Setting vtag %x for new conn\n",
1448+ inithdr.init_tag);
1449+
1450+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] =
1451+ inithdr.init_tag;
1452+ } else {
1453+ /* Sec 8.5.1 (A) */
1454+ return -1;
1455+ }
1456+ }
1457+ /* If it is a shutdown ack OOTB packet, we expect a return
1458+ shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
1459+ else {
1460+ DEBUGP("Setting vtag %x for new conn OOTB\n",
1461+ sctph.vtag);
1462+ conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
1463+ }
1464+
1465+ conntrack->proto.sctp.state = newconntrack;
1466+ }
1467+
1468+ return 1;
1469+}
1470+
1471+static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
1472+ const struct sk_buff *skb)
1473+{
1474+ /* To be implemented */
1475+ return 0;
1476+}
1477+
1478+struct ip_conntrack_protocol ip_conntrack_protocol_sctp = {
1479+ .list = { NULL, NULL },
1480+ .proto = IPPROTO_SCTP,
1481+ .name = "sctp",
1482+ .pkt_to_tuple = sctp_pkt_to_tuple,
1483+ .invert_tuple = sctp_invert_tuple,
1484+ .print_tuple = sctp_print_tuple,
1485+ .print_conntrack = sctp_print_conntrack,
1486+ .packet = sctp_packet,
1487+ .new = sctp_new,
1488+ .destroy = NULL,
1489+ .exp_matches_pkt = sctp_exp_matches_pkt,
1490+ .me = THIS_MODULE
1491+};
1492+
1493+int __init init(void)
1494+{
1495+ int ret;
1496+
1497+ ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
1498+ DEBUGP("SCTP conntrack module loading %s\n",
1499+ ret ? "failed": "succeeded");
1500+ return ret;
1501+}
1502+
1503+void __exit fini(void)
1504+{
1505+ ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
1506+ DEBUGP("SCTP conntrack module unloaded\n");
1507+}
1508+
1509+module_init(init);
1510+module_exit(fini);
1511+
1512+MODULE_LICENSE("GPL");
1513+MODULE_AUTHOR("Kiran Kumar Immidi");
1514+MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
1515diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c
1516--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-19 10:38:51.000000000 +0200
1517+++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-04-19 10:44:16.000000000 +0200
1518@@ -110,6 +110,9 @@
1519 len += sprintf(buffer + len, "[ASSURED] ");
1520 len += sprintf(buffer + len, "use=%u ",
1521 atomic_read(&conntrack->ct_general.use));
1522+#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
1523+ len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
1524+#endif
1525 len += sprintf(buffer + len, "\n");
1526
1527 return len;
1528diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc1/net/ipv4/netfilter/ip_tables.c
1529--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ip_tables.c 2004-04-19 10:38:53.000000000 +0200
1530+++ linux-2.6.6-rc1/net/ipv4/netfilter/ip_tables.c 2004-04-19 10:45:57.000000000 +0200
1531@@ -8,6 +8,10 @@
1532 * it under the terms of the GNU General Public License version 2 as
1533 * published by the Free Software Foundation.
1534 *
1535+ * 6 Mar 2002 Robert Olsson <robban@robtex.com>
1536+ * 17 Apr 2003 Chris Wilson <chris@netservers.co.uk>
1537+ * - mark_source_chains speedup for complex chains
1538+ *
1539 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
1540 * - increase module usage count as soon as we have rules inside
1541 * a table
1542@@ -498,6 +502,9 @@
1543 {
1544 unsigned int hook;
1545
1546+ /* keep track of where we have been: */
1547+ unsigned char *been = vmalloc(newinfo->size);
1548+
1549 /* No recursion; use packet counter to save back ptrs (reset
1550 to 0 as we leave), and comefrom to save source hook bitmask */
1551 for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
1552@@ -510,6 +517,7 @@
1553
1554 /* Set initial back pointer. */
1555 e->counters.pcnt = pos;
1556+ memset(been, 0, newinfo->size);
1557
1558 for (;;) {
1559 struct ipt_standard_target *t
1560@@ -518,6 +526,7 @@
1561 if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
1562 printk("iptables: loop hook %u pos %u %08X.\n",
1563 hook, pos, e->comefrom);
1564+ vfree(been);
1565 return 0;
1566 }
1567 e->comefrom
1568@@ -565,10 +574,14 @@
1569 } else {
1570 int newpos = t->verdict;
1571
1572- if (strcmp(t->target.u.user.name,
1573+ if ( (pos < 0 || pos >= newinfo->size
1574+ || !been[pos])
1575+ && strcmp(t->target.u.user.name,
1576 IPT_STANDARD_TARGET) == 0
1577 && newpos >= 0) {
1578 /* This a jump; chase it. */
1579+ if (pos >= 0 && pos < newinfo->size)
1580+ been[pos]++;
1581 duprintf("Jump rule %u -> %u\n",
1582 pos, newpos);
1583 } else {
1584@@ -584,6 +597,7 @@
1585 next:
1586 duprintf("Finished chain %u\n", hook);
1587 }
1588+ vfree(been);
1589 return 1;
1590 }
1591
1592diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_CONNMARK.c
1593--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
1594+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_CONNMARK.c 2004-04-19 10:44:16.000000000 +0200
1595@@ -0,0 +1,118 @@
1596+/* This kernel module is used to modify the connection mark values, or
1597+ * to optionally restore the skb nfmark from the connection mark
1598+ *
1599+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
1600+ * by Henrik Nordstrom <hno@marasystems.com>
1601+ *
1602+ * This program is free software; you can redistribute it and/or modify
1603+ * it under the terms of the GNU General Public License as published by
1604+ * the Free Software Foundation; either version 2 of the License, or
1605+ * (at your option) any later version.
1606+ *
1607+ * This program is distributed in the hope that it will be useful,
1608+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1609+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1610+ * GNU General Public License for more details.
1611+ *
1612+ * You should have received a copy of the GNU General Public License
1613+ * along with this program; if not, write to the Free Software
1614+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1615+ */
1616+#include <linux/module.h>
1617+#include <linux/skbuff.h>
1618+#include <linux/ip.h>
1619+#include <net/checksum.h>
1620+
1621+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
1622+MODULE_DESCRIPTION("IP tables CONNMARK matching module");
1623+MODULE_LICENSE("GPL");
1624+
1625+#include <linux/netfilter_ipv4/ip_tables.h>
1626+#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
1627+#include <linux/netfilter_ipv4/ip_conntrack.h>
1628+
1629+static unsigned int
1630+target(struct sk_buff **pskb,
1631+ const struct net_device *in,
1632+ const struct net_device *out,
1633+ unsigned int hooknum,
1634+ const void *targinfo,
1635+ void *userinfo)
1636+{
1637+ const struct ipt_connmark_target_info *markinfo = targinfo;
1638+ unsigned long diff;
1639+ unsigned long nfmark;
1640+ unsigned long newmark;
1641+
1642+ enum ip_conntrack_info ctinfo;
1643+ struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
1644+ if (ct) {
1645+ switch(markinfo->mode) {
1646+ case IPT_CONNMARK_SET:
1647+ newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
1648+ if (newmark != ct->mark)
1649+ ct->mark = newmark;
1650+ break;
1651+ case IPT_CONNMARK_SAVE:
1652+ newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
1653+ if (ct->mark != newmark)
1654+ ct->mark = newmark;
1655+ break;
1656+ case IPT_CONNMARK_RESTORE:
1657+ nfmark = (*pskb)->nfmark;
1658+ diff = (ct->mark ^ nfmark & markinfo->mask);
1659+ if (diff != 0) {
1660+ (*pskb)->nfmark = nfmark ^ diff;
1661+ (*pskb)->nfcache |= NFC_ALTERED;
1662+ }
1663+ break;
1664+ }
1665+ }
1666+
1667+ return IPT_CONTINUE;
1668+}
1669+
1670+static int
1671+checkentry(const char *tablename,
1672+ const struct ipt_entry *e,
1673+ void *targinfo,
1674+ unsigned int targinfosize,
1675+ unsigned int hook_mask)
1676+{
1677+ struct ipt_connmark_target_info *matchinfo = targinfo;
1678+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
1679+ printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
1680+ targinfosize,
1681+ IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
1682+ return 0;
1683+ }
1684+
1685+ if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
1686+ if (strcmp(tablename, "mangle") != 0) {
1687+ printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1688+ return 0;
1689+ }
1690+ }
1691+
1692+ return 1;
1693+}
1694+
1695+static struct ipt_target ipt_connmark_reg = {
1696+ .name = "CONNMARK",
1697+ .target = &target,
1698+ .checkentry = &checkentry,
1699+ .me = THIS_MODULE
1700+};
1701+
1702+static int __init init(void)
1703+{
1704+ return ipt_register_target(&ipt_connmark_reg);
1705+}
1706+
1707+static void __exit fini(void)
1708+{
1709+ ipt_unregister_target(&ipt_connmark_reg);
1710+}
1711+
1712+module_init(init);
1713+module_exit(fini);
1714diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_IPMARK.c
1715--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
1716+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_IPMARK.c 2004-04-19 10:44:26.000000000 +0200
1717@@ -0,0 +1,81 @@
1718+/* This is a module which is used for setting the NFMARK field of an skb. */
1719+#include <linux/module.h>
1720+#include <linux/skbuff.h>
1721+#include <linux/ip.h>
1722+#include <net/checksum.h>
1723+
1724+#include <linux/netfilter_ipv4/ip_tables.h>
1725+#include <linux/netfilter_ipv4/ipt_IPMARK.h>
1726+
1727+MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
1728+MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
1729+MODULE_LICENSE("GPL");
1730+
1731+static unsigned int
1732+target(struct sk_buff **pskb,
1733+ const struct net_device *in,
1734+ const struct net_device *out,
1735+ unsigned int hooknum,
1736+ const void *targinfo,
1737+ void *userinfo)
1738+{
1739+ const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
1740+ struct iphdr *iph = (*pskb)->nh.iph;
1741+ unsigned long mark;
1742+
1743+ if (ipmarkinfo->addr == IPT_IPMARK_SRC)
1744+ mark = (unsigned long) ntohl(iph->saddr);
1745+ else
1746+ mark = (unsigned long) ntohl(iph->daddr);
1747+
1748+ mark &= ipmarkinfo->andmask;
1749+ mark |= ipmarkinfo->ormask;
1750+
1751+ if ((*pskb)->nfmark != mark) {
1752+ (*pskb)->nfmark = mark;
1753+ (*pskb)->nfcache |= NFC_ALTERED;
1754+ }
1755+ return IPT_CONTINUE;
1756+}
1757+
1758+static int
1759+checkentry(const char *tablename,
1760+ const struct ipt_entry *e,
1761+ void *targinfo,
1762+ unsigned int targinfosize,
1763+ unsigned int hook_mask)
1764+{
1765+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
1766+ printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
1767+ targinfosize,
1768+ IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
1769+ return 0;
1770+ }
1771+
1772+ if (strcmp(tablename, "mangle") != 0) {
1773+ printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1774+ return 0;
1775+ }
1776+
1777+ return 1;
1778+}
1779+
1780+static struct ipt_target ipt_ipmark_reg = {
1781+ .name = "IPMARK",
1782+ .target = target,
1783+ .checkentry = checkentry,
1784+ .me = THIS_MODULE
1785+};
1786+
1787+static int __init init(void)
1788+{
1789+ return ipt_register_target(&ipt_ipmark_reg);
1790+}
1791+
1792+static void __exit fini(void)
1793+{
1794+ ipt_unregister_target(&ipt_ipmark_reg);
1795+}
1796+
1797+module_init(init);
1798+module_exit(fini);
1799diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TARPIT.c
1800--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
1801+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_TARPIT.c 2004-04-19 10:44:29.000000000 +0200
1802@@ -0,0 +1,287 @@
1803+/*
1804+ * Kernel module to capture and hold incoming TCP connections using
1805+ * no local per-connection resources.
1806+ *
1807+ * Based on ipt_REJECT.c and offering functionality similar to
1808+ * LaBrea <http://www.hackbusters.net/LaBrea/>.
1809+ *
1810+ * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
1811+ *
1812+ * This program is free software; you can redistribute it and/or modify
1813+ * it under the terms of the GNU General Public License as published by
1814+ * the Free Software Foundation; either version 2 of the License, or
1815+ * (at your option) any later version.
1816+ *
1817+ * This program is distributed in the hope that it will be useful,
1818+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1819+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1820+ * GNU General Public License for more details.
1821+ *
1822+ * You should have received a copy of the GNU General Public License
1823+ * along with this program; if not, write to the Free Software
1824+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1825+ *
1826+ * Goal:
1827+ * - Allow incoming TCP connections to be established.
1828+ * - Passing data should result in the connection being switched to the
1829+ * persist state (0 byte window), in which the remote side stops sending
1830+ * data and asks to continue every 60 seconds.
1831+ * - Attempts to shut down the connection should be ignored completely, so
1832+ * the remote side ends up having to time it out.
1833+ *
1834+ * This means:
1835+ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
1836+ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
1837+ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
1838+ */
1839+
1840+#include <linux/config.h>
1841+#include <linux/module.h>
1842+#include <linux/skbuff.h>
1843+#include <linux/ip.h>
1844+#include <net/ip.h>
1845+#include <net/tcp.h>
1846+#include <net/icmp.h>
1847+struct in_device;
1848+#include <net/route.h>
1849+#include <linux/random.h>
1850+#include <linux/netfilter_ipv4/ip_tables.h>
1851+
1852+#if 0
1853+#define DEBUGP printk
1854+#else
1855+#define DEBUGP(format, args...)
1856+#endif
1857+
1858+MODULE_LICENSE("GPL");
1859+MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
1860+
1861+/* Stolen from ip_finish_output2 */
1862+static int ip_direct_send(struct sk_buff *skb)
1863+{
1864+ struct dst_entry *dst = skb->dst;
1865+ struct hh_cache *hh = dst->hh;
1866+
1867+ if (hh) {
1868+ read_lock_bh(&hh->hh_lock);
1869+ memcpy(skb->data - 16, hh->hh_data, 16);
1870+ read_unlock_bh(&hh->hh_lock);
1871+ skb_push(skb, hh->hh_len);
1872+ return hh->hh_output(skb);
1873+ } else if (dst->neighbour)
1874+ return dst->neighbour->output(skb);
1875+
1876+ if (net_ratelimit())
1877+ printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
1878+ kfree_skb(skb);
1879+ return -EINVAL;
1880+}
1881+
1882+
1883+/* Send reply */
1884+static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
1885+{
1886+ struct sk_buff *nskb;
1887+ struct rtable *nrt;
1888+ struct tcphdr *otcph, *ntcph;
1889+ unsigned int otcplen;
1890+ u_int16_t tmp;
1891+
1892+ /* A truncated TCP header isn't going to be useful */
1893+ if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
1894+ return;
1895+
1896+ otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
1897+ + oskb->nh.iph->ihl);
1898+ otcplen = oskb->len - oskb->nh.iph->ihl*4;
1899+
1900+ /* No replies for RST or FIN */
1901+ if (otcph->rst || otcph->fin)
1902+ return;
1903+
1904+ /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
1905+ if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
1906+ return;
1907+
1908+ /* Check checksum. */
1909+ if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
1910+ oskb->nh.iph->daddr,
1911+ csum_partial((char *)otcph, otcplen, 0)) != 0)
1912+ return;
1913+
1914+ /* Copy skb (even if skb is about to be dropped, we can't just
1915+ clone it because there may be other things, such as tcpdump,
1916+ interested in it) */
1917+ nskb = skb_copy(oskb, GFP_ATOMIC);
1918+ if (!nskb)
1919+ return;
1920+
1921+ /* This packet will not be the same as the other: clear nf fields */
1922+ nf_conntrack_put(nskb->nfct);
1923+ nskb->nfct = NULL;
1924+ nskb->nfcache = 0;
1925+#ifdef CONFIG_NETFILTER_DEBUG
1926+ nskb->nf_debug = 0;
1927+#endif
1928+
1929+ ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
1930+
1931+ /* Truncate to length (no data) */
1932+ ntcph->doff = sizeof(struct tcphdr)/4;
1933+ skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
1934+ nskb->nh.iph->tot_len = htons(nskb->len);
1935+
1936+ /* Swap source and dest */
1937+ nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
1938+ tmp = ntcph->source;
1939+ ntcph->source = ntcph->dest;
1940+ ntcph->dest = tmp;
1941+
1942+ /* Use supplied sequence number or make a new one */
1943+ ntcph->seq = otcph->ack ? otcph->ack_seq
1944+ : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr,
1945+ nskb->nh.iph->daddr,
1946+ ntcph->source,
1947+ ntcph->dest));
1948+
1949+ /* Our SYN-ACKs must have a >0 window */
1950+ ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
1951+
1952+ ntcph->urg_ptr = 0;
1953+
1954+ /* Reset flags */
1955+ ((u_int8_t *)ntcph)[13] = 0;
1956+
1957+ if (otcph->syn && otcph->ack) {
1958+ ntcph->rst = 1;
1959+ ntcph->ack_seq = 0;
1960+ } else {
1961+ ntcph->syn = otcph->syn;
1962+ ntcph->ack = 1;
1963+ ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
1964+ }
1965+
1966+ /* Adjust TCP checksum */
1967+ ntcph->check = 0;
1968+ ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
1969+ nskb->nh.iph->saddr,
1970+ nskb->nh.iph->daddr,
1971+ csum_partial((char *)ntcph,
1972+ sizeof(struct tcphdr), 0));
1973+
1974+ /* Adjust IP TTL */
1975+ nskb->nh.iph->ttl = sysctl_ip_default_ttl;
1976+
1977+ /* Set DF, id = 0 */
1978+ nskb->nh.iph->frag_off = htons(IP_DF);
1979+ nskb->nh.iph->id = 0;
1980+
1981+ /* Adjust IP checksum */
1982+ nskb->nh.iph->check = 0;
1983+ nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
1984+ nskb->nh.iph->ihl);
1985+
1986+ if (ip_route_output(&nrt, nskb->nh.iph->daddr,
1987+ local ? nskb->nh.iph->saddr : 0,
1988+ RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
1989+ 0) != 0)
1990+ goto free_nskb;
1991+
1992+ dst_release(nskb->dst);
1993+ nskb->dst = &nrt->u.dst;
1994+
1995+ /* "Never happens" */
1996+ if (nskb->len > nskb->dst->pmtu)
1997+ goto free_nskb;
1998+
1999+ ip_direct_send (nskb);
2000+
2001+ return;
2002+
2003+ free_nskb:
2004+ kfree_skb(nskb);
2005+}
2006+
2007+
2008+static unsigned int tarpit(struct sk_buff **pskb,
2009+ const struct net_device *in,
2010+ const struct net_device *out,
2011+ unsigned int hooknum,
2012+ const void *targinfo,
2013+ void *userinfo)
2014+{
2015+ struct sk_buff *skb = *pskb;
2016+ struct rtable *rt = (struct rtable*)skb->dst;
2017+
2018+ /* Do we have an input route cache entry? */
2019+ if (!rt)
2020+ return NF_DROP;
2021+
2022+ /* No replies to physical multicast/broadcast */
2023+ if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
2024+ return NF_DROP;
2025+
2026+ /* Now check at the protocol level */
2027+ if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
2028+ return NF_DROP;
2029+
2030+ /* Our naive response construction doesn't deal with IP
2031+ options, and probably shouldn't try. */
2032+ if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
2033+ return NF_DROP;
2034+
2035+ /* We aren't interested in fragments */
2036+ if (skb->nh.iph->frag_off & htons(IP_OFFSET))
2037+ return NF_DROP;
2038+
2039+ tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
2040+
2041+ return NF_DROP;
2042+}
2043+
2044+
2045+static int check(const char *tablename,
2046+ const struct ipt_entry *e,
2047+ void *targinfo,
2048+ unsigned int targinfosize,
2049+ unsigned int hook_mask)
2050+{
2051+ /* Only allow these for input/forward packet filtering. */
2052+ if (strcmp(tablename, "filter") != 0) {
2053+ DEBUGP("TARPIT: bad table %s'.\n", tablename);
2054+ return 0;
2055+ }
2056+ if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
2057+ | (1 << NF_IP_FORWARD))) != 0) {
2058+ DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
2059+ return 0;
2060+ }
2061+
2062+ /* Must specify that it's a TCP packet */
2063+ if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
2064+ DEBUGP("TARPIT: not valid for non-tcp\n");
2065+ return 0;
2066+ }
2067+
2068+ return 1;
2069+}
2070+
2071+static struct ipt_target ipt_tarpit_reg = {
2072+ .name = "TARPIT",
2073+ .target = tarpit,
2074+ .checkentry = check,
2075+ .me = THIS_MODULE
2076+};
2077+
2078+static int __init init(void)
2079+{
2080+ return ipt_register_target(&ipt_tarpit_reg);
2081+}
2082+
2083+static void __exit fini(void)
2084+{
2085+ ipt_unregister_target(&ipt_tarpit_reg);
2086+}
2087+
2088+module_init(init);
2089+module_exit(fini);
2090diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_XOR.c
2091--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_XOR.c 1970-01-01 01:00:00.000000000 +0100
2092+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_XOR.c 2004-04-19 10:44:34.000000000 +0200
2093@@ -0,0 +1,117 @@
2094+/* XOR target for IP tables
2095+ * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
2096+ * Based on ipt_TTL.c
2097+ *
2098+ * Version 1.0
2099+ *
2100+ * This software is distributed under the terms of GNU GPL
2101+ */
2102+
2103+#include <linux/module.h>
2104+#include <linux/skbuff.h>
2105+#include <linux/ip.h>
2106+#include <linux/tcp.h>
2107+#include <linux/udp.h>
2108+
2109+#include <linux/netfilter_ipv4/ip_tables.h>
2110+#include <linux/netfilter_ipv4/ipt_XOR.h>
2111+
2112+MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
2113+MODULE_DESCRIPTION("IP tables XOR module");
2114+MODULE_LICENSE("GPL");
2115+
2116+static unsigned int
2117+ipt_xor_target(struct sk_buff **pskb,
2118+ const struct net_device *in, const struct net_device *out,
2119+ unsigned int hooknum, const void *targinfo, void *userinfo)
2120+{
2121+ struct ipt_XOR_info *info = (void *) targinfo;
2122+ struct iphdr *iph;
2123+ struct tcphdr *tcph;
2124+ struct udphdr *udph;
2125+ int i, j, k;
2126+
2127+ if (!skb_ip_make_writable(pskb, (*pskb)->len))
2128+ return NF_DROP;
2129+
2130+ iph = (*pskb)->nh.iph;
2131+
2132+ if (iph->protocol == IPPROTO_TCP) {
2133+ tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
2134+ for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
2135+ for (k=0; k<=info->block_size; k++) {
2136+ (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^=
2137+ info->key[j];
2138+ i++;
2139+ }
2140+ j++;
2141+ if (info->key[j] == 0x00)
2142+ j = 0;
2143+ }
2144+ } else if (iph->protocol == IPPROTO_UDP) {
2145+ udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
2146+ for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
2147+ for (k=0; k<=info->block_size; k++) {
2148+ (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^=
2149+ info->key[j];
2150+ i++;
2151+ }
2152+ j++;
2153+ if (info->key[j] == 0x00)
2154+ j = 0;
2155+ }
2156+ }
2157+
2158+ return IPT_CONTINUE;
2159+}
2160+
2161+static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
2162+ void *targinfo, unsigned int targinfosize,
2163+ unsigned int hook_mask)
2164+{
2165+ struct ipt_XOR_info *info = targinfo;
2166+
2167+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
2168+ printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n",
2169+ targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
2170+ return 0;
2171+ }
2172+
2173+ if (strcmp(tablename, "mangle")) {
2174+ printk(KERN_WARNING "XOR: can only be called from"
2175+ "\"mangle\" table, not \"%s\"\n", tablename);
2176+ return 0;
2177+ }
2178+
2179+ if (!strcmp(info->key, "")) {
2180+ printk(KERN_WARNING "XOR: You must specify a key");
2181+ return 0;
2182+ }
2183+
2184+ if (info->block_size == 0) {
2185+ printk(KERN_WARNING "XOR: You must specify a block-size");
2186+ return 0;
2187+ }
2188+
2189+ return 1;
2190+}
2191+
2192+static struct ipt_target ipt_XOR = {
2193+ .name = "XOR",
2194+ .target = ipt_xor_target,
2195+ .checkentry = ipt_xor_checkentry,
2196+ .me = THIS_MODULE,
2197+};
2198+
2199+static int __init init(void)
2200+{
2201+ return ipt_register_target(&ipt_XOR);
2202+}
2203+
2204+static void __exit fini(void)
2205+{
2206+ ipt_unregister_target(&ipt_XOR);
2207+}
2208+
2209+module_init(init);
2210+module_exit(fini);
2211diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_addrtype.c
2212--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_addrtype.c 1970-01-01 01:00:00.000000000 +0100
2213+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_addrtype.c 2004-04-19 10:44:36.000000000 +0200
2214@@ -0,0 +1,68 @@
2215+/*
2216+ * iptables module to match inet_addr_type() of an ip.
2217+ */
2218+
2219+#include <linux/module.h>
2220+#include <linux/skbuff.h>
2221+#include <linux/netdevice.h>
2222+#include <net/route.h>
2223+
2224+#include <linux/netfilter_ipv4/ipt_addrtype.h>
2225+#include <linux/netfilter_ipv4/ip_tables.h>
2226+
2227+MODULE_LICENSE("GPL");
2228+
2229+static inline int match_type(u_int32_t addr, u_int16_t mask)
2230+{
2231+ return !!(mask & (1 << inet_addr_type(addr)));
2232+}
2233+
2234+static int match(const struct sk_buff *skb, const struct net_device *in,
2235+ const struct net_device *out, const void *matchinfo,
2236+ int offset, int *hotdrop)
2237+{
2238+ const struct ipt_addrtype_info *info = matchinfo;
2239+ const struct iphdr *iph = skb->nh.iph;
2240+ int ret = 1;
2241+
2242+ if (info->source)
2243+ ret &= match_type(iph->saddr, info->source)^info->invert_source;
2244+ if (info->dest)
2245+ ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
2246+
2247+ return ret;
2248+}
2249+
2250+static int checkentry(const char *tablename, const struct ipt_ip *ip,
2251+ void *matchinfo, unsigned int matchsize,
2252+ unsigned int hook_mask)
2253+{
2254+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
2255+ printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
2256+ matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
2257+ return 0;
2258+ }
2259+
2260+ return 1;
2261+}
2262+
2263+static struct ipt_match addrtype_match = {
2264+ .name = "addrtype",
2265+ .match = match,
2266+ .checkentry = checkentry,
2267+ .me = THIS_MODULE
2268+};
2269+
2270+static int __init init(void)
2271+{
2272+ return ipt_register_match(&addrtype_match);
2273+}
2274+
2275+static void __exit fini(void)
2276+{
2277+ ipt_unregister_match(&addrtype_match);
2278+
2279+}
2280+
2281+module_init(init);
2282+module_exit(fini);
2283diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_connmark.c
2284--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
2285+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_connmark.c 2004-04-19 10:44:16.000000000 +0200
2286@@ -0,0 +1,81 @@
2287+/* This kernel module matches connection mark values set by the
2288+ * CONNMARK target
2289+ *
2290+ * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
2291+ * by Henrik Nordstrom <hno@marasystems.com>
2292+ *
2293+ * This program is free software; you can redistribute it and/or modify
2294+ * it under the terms of the GNU General Public License as published by
2295+ * the Free Software Foundation; either version 2 of the License, or
2296+ * (at your option) any later version.
2297+ *
2298+ * This program is distributed in the hope that it will be useful,
2299+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2300+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2301+ * GNU General Public License for more details.
2302+ *
2303+ * You should have received a copy of the GNU General Public License
2304+ * along with this program; if not, write to the Free Software
2305+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2306+ */
2307+
2308+#include <linux/module.h>
2309+#include <linux/skbuff.h>
2310+
2311+MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
2312+MODULE_DESCRIPTION("IP tables connmark match module");
2313+MODULE_LICENSE("GPL");
2314+
2315+#include <linux/netfilter_ipv4/ip_tables.h>
2316+#include <linux/netfilter_ipv4/ipt_connmark.h>
2317+#include <linux/netfilter_ipv4/ip_conntrack.h>
2318+
2319+static int
2320+match(const struct sk_buff *skb,
2321+ const struct net_device *in,
2322+ const struct net_device *out,
2323+ const void *matchinfo,
2324+ int offset,
2325+ int *hotdrop)
2326+{
2327+ const struct ipt_connmark_info *info = matchinfo;
2328+ enum ip_conntrack_info ctinfo;
2329+ struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2330+ if (!ct)
2331+ return 0;
2332+
2333+ return ((ct->mark & info->mask) == info->mark) ^ info->invert;
2334+}
2335+
2336+static int
2337+checkentry(const char *tablename,
2338+ const struct ipt_ip *ip,
2339+ void *matchinfo,
2340+ unsigned int matchsize,
2341+ unsigned int hook_mask)
2342+{
2343+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
2344+ return 0;
2345+
2346+ return 1;
2347+}
2348+
2349+static struct ipt_match connmark_match = {
2350+ .name = "connmark",
2351+ .match = &match,
2352+ .checkentry = &checkentry,
2353+ .me = THIS_MODULE
2354+};
2355+
2356+static int __init init(void)
2357+{
2358+ return ipt_register_match(&connmark_match);
2359+}
2360+
2361+static void __exit fini(void)
2362+{
2363+ ipt_unregister_match(&connmark_match);
2364+}
2365+
2366+module_init(init);
2367+module_exit(fini);
2368diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_owner.c
2369--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_owner.c 2004-04-15 03:35:57.000000000 +0200
2370+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_owner.c 2004-04-19 10:46:08.000000000 +0200
2371@@ -6,12 +6,19 @@
2372 * This program is free software; you can redistribute it and/or modify
2373 * it under the terms of the GNU General Public License version 2 as
2374 * published by the Free Software Foundation.
2375+ *
2376+ * 03/26/2003 Patrick McHardy <kaber@trash.net> : LOCAL_IN support
2377 */
2378
2379 #include <linux/module.h>
2380 #include <linux/skbuff.h>
2381 #include <linux/file.h>
2382+#include <linux/ip.h>
2383+#include <linux/tcp.h>
2384+#include <linux/udp.h>
2385 #include <net/sock.h>
2386+#include <net/tcp.h>
2387+#include <net/udp.h>
2388
2389 #include <linux/netfilter_ipv4/ipt_owner.h>
2390 #include <linux/netfilter_ipv4/ip_tables.h>
2391@@ -21,7 +28,7 @@
2392 MODULE_DESCRIPTION("iptables owner match");
2393
2394 static int
2395-match_comm(const struct sk_buff *skb, const char *comm)
2396+match_comm(const struct sock *sk, const char *comm)
2397 {
2398 struct task_struct *g, *p;
2399 struct files_struct *files;
2400@@ -38,7 +45,7 @@
2401 spin_lock(&files->file_lock);
2402 for (i=0; i < files->max_fds; i++) {
2403 if (fcheck_files(files, i) ==
2404- skb->sk->sk_socket->file) {
2405+ sk->sk_socket->file) {
2406 spin_unlock(&files->file_lock);
2407 task_unlock(p);
2408 read_unlock(&tasklist_lock);
2409@@ -54,7 +61,7 @@
2410 }
2411
2412 static int
2413-match_pid(const struct sk_buff *skb, pid_t pid)
2414+match_pid(const struct sock *sk, pid_t pid)
2415 {
2416 struct task_struct *p;
2417 struct files_struct *files;
2418@@ -70,7 +77,7 @@
2419 spin_lock(&files->file_lock);
2420 for (i=0; i < files->max_fds; i++) {
2421 if (fcheck_files(files, i) ==
2422- skb->sk->sk_socket->file) {
2423+ sk->sk_socket->file) {
2424 spin_unlock(&files->file_lock);
2425 task_unlock(p);
2426 read_unlock(&tasklist_lock);
2427@@ -86,10 +93,10 @@
2428 }
2429
2430 static int
2431-match_sid(const struct sk_buff *skb, pid_t sid)
2432+match_sid(const struct sock *sk, pid_t sid)
2433 {
2434 struct task_struct *g, *p;
2435- struct file *file = skb->sk->sk_socket->file;
2436+ struct file *file = sk->sk_socket->file;
2437 int i, found=0;
2438
2439 read_lock(&tasklist_lock);
2440@@ -129,41 +136,71 @@
2441 int *hotdrop)
2442 {
2443 const struct ipt_owner_info *info = matchinfo;
2444+ struct iphdr *iph = skb->nh.iph;
2445+ struct sock *sk = NULL;
2446+ int ret = 0;
2447+
2448+ if (out) {
2449+ sk = skb->sk;
2450+ } else {
2451+ if (iph->protocol == IPPROTO_TCP) {
2452+ struct tcphdr *tcph =
2453+ (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
2454+ sk = tcp_v4_lookup(iph->saddr, tcph->source,
2455+ iph->daddr, tcph->dest,
2456+ skb->dev->ifindex);
2457+ if (sk && sk->sk_state == TCP_TIME_WAIT) {
2458+ tcp_tw_put((struct tcp_tw_bucket *)sk);
2459+ return ret;
2460+ }
2461+ } else if (iph->protocol == IPPROTO_UDP) {
2462+ struct udphdr *udph =
2463+ (struct udphdr *)((u_int32_t *)iph + iph->ihl);
2464+ sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
2465+ udph->dest, skb->dev->ifindex);
2466+ }
2467+ }
2468
2469- if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
2470- return 0;
2471+ if (!sk || !sk->sk_socket || !sk->sk_socket->file)
2472+ goto out;
2473
2474 if(info->match & IPT_OWNER_UID) {
2475- if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
2476+ if ((sk->sk_socket->file->f_uid != info->uid) ^
2477 !!(info->invert & IPT_OWNER_UID))
2478- return 0;
2479+ goto out;
2480 }
2481
2482 if(info->match & IPT_OWNER_GID) {
2483- if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
2484+ if ((sk->sk_socket->file->f_gid != info->gid) ^
2485 !!(info->invert & IPT_OWNER_GID))
2486- return 0;
2487+ goto out;
2488 }
2489
2490 if(info->match & IPT_OWNER_PID) {
2491- if (!match_pid(skb, info->pid) ^
2492+ if (!match_pid(sk, info->pid) ^
2493 !!(info->invert & IPT_OWNER_PID))
2494- return 0;
2495+ goto out;
2496 }
2497
2498 if(info->match & IPT_OWNER_SID) {
2499- if (!match_sid(skb, info->sid) ^
2500+ if (!match_sid(sk, info->sid) ^
2501 !!(info->invert & IPT_OWNER_SID))
2502- return 0;
2503+ goto out;
2504 }
2505
2506 if(info->match & IPT_OWNER_COMM) {
2507- if (!match_comm(skb, info->comm) ^
2508+ if (!match_comm(sk, info->comm) ^
2509 !!(info->invert & IPT_OWNER_COMM))
2510- return 0;
2511+ goto out;
2512 }
2513
2514- return 1;
2515+ ret = 1;
2516+
2517+out:
2518+ if (in && sk)
2519+ sock_put(sk);
2520+
2521+ return ret;
2522 }
2523
2524 static int
2525@@ -173,11 +210,19 @@
2526 unsigned int matchsize,
2527 unsigned int hook_mask)
2528 {
2529- if (hook_mask
2530- & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
2531- printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
2532- return 0;
2533- }
2534+ if (hook_mask
2535+ & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
2536+ (1 << NF_IP_LOCAL_IN))) {
2537+ printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
2538+ "or POST_ROUTING.\n");
2539+ return 0;
2540+ }
2541+
2542+ if ((hook_mask & (1 << NF_IP_LOCAL_IN))
2543+ && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
2544+ printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
2545+ return 0;
2546+ }
2547
2548 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
2549 printk("Matchsize %u != %Zu\n", matchsize,
2550diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_policy.c
2551--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
2552+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_policy.c 2004-04-19 10:46:16.000000000 +0200
2553@@ -0,0 +1,176 @@
2554+/* IP tables module for matching IPsec policy
2555+ *
2556+ * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
2557+ *
2558+ * This program is free software; you can redistribute it and/or modify
2559+ * it under the terms of the GNU General Public License version 2 as
2560+ * published by the Free Software Foundation.
2561+ */
2562+
2563+#include <linux/kernel.h>
2564+#include <linux/config.h>
2565+#include <linux/module.h>
2566+#include <linux/skbuff.h>
2567+#include <linux/init.h>
2568+#include <net/xfrm.h>
2569+
2570+#include <linux/netfilter_ipv4.h>
2571+#include <linux/netfilter_ipv4/ipt_policy.h>
2572+#include <linux/netfilter_ipv4/ip_tables.h>
2573+
2574+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
2575+MODULE_DESCRIPTION("IPtables IPsec policy matching module");
2576+MODULE_LICENSE("GPL");
2577+
2578+
2579+static inline int
2580+match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
2581+{
2582+#define MISMATCH(x,y) (e->match.x && ((e->x != (y)) ^ e->invert.x))
2583+
2584+ if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
2585+ MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
2586+ MISMATCH(proto, x->id.proto) ||
2587+ MISMATCH(mode, x->props.mode) ||
2588+ MISMATCH(spi, x->id.spi) ||
2589+ MISMATCH(reqid, x->props.reqid))
2590+ return 0;
2591+ return 1;
2592+}
2593+
2594+static int
2595+match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
2596+{
2597+ const struct ipt_policy_elem *e;
2598+ struct sec_path *sp = skb->sp;
2599+ int strict = info->flags & POLICY_MATCH_STRICT;
2600+ int i, pos;
2601+
2602+ if (sp == NULL)
2603+ return -1;
2604+ if (strict && info->len != sp->len)
2605+ return 0;
2606+
2607+ for (i = sp->len - 1; i >= 0; i--) {
2608+ pos = strict ? i - sp->len + 1 : 0;
2609+ if (pos >= info->len)
2610+ return 0;
2611+ e = &info->pol[pos];
2612+
2613+ if (match_xfrm_state(sp->x[i].xvec, e)) {
2614+ if (!strict)
2615+ return 1;
2616+ } else if (strict)
2617+ return 0;
2618+ }
2619+
2620+ return strict ? 1 : 0;
2621+}
2622+
2623+static int
2624+match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
2625+{
2626+ const struct ipt_policy_elem *e;
2627+ struct dst_entry *dst = skb->dst;
2628+ int strict = info->flags & POLICY_MATCH_STRICT;
2629+ int i, pos;
2630+
2631+ if (dst->xfrm == NULL)
2632+ return -1;
2633+
2634+ for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
2635+ pos = strict ? i : 0;
2636+ if (pos >= info->len)
2637+ return 0;
2638+ e = &info->pol[pos];
2639+
2640+ if (match_xfrm_state(dst->xfrm, e)) {
2641+ if (!strict)
2642+ return 1;
2643+ } else if (strict)
2644+ return 0;
2645+ }
2646+
2647+ return strict ? 1 : 0;
2648+}
2649+
2650+static int match(const struct sk_buff *skb,
2651+ const struct net_device *in,
2652+ const struct net_device *out,
2653+ const void *matchinfo, int offset, int *hotdrop)
2654+{
2655+ const struct ipt_policy_info *info = matchinfo;
2656+ int ret;
2657+
2658+ if (info->flags & POLICY_MATCH_IN)
2659+ ret = match_policy_in(skb, info);
2660+ else
2661+ ret = match_policy_out(skb, info);
2662+
2663+ if (ret < 0) {
2664+ if (info->flags & POLICY_MATCH_NONE)
2665+ ret = 1;
2666+ else
2667+ ret = 0;
2668+ } else if (info->flags & POLICY_MATCH_NONE)
2669+ ret = 0;
2670+
2671+ return ret;
2672+}
2673+
2674+static int checkentry(const char *tablename, const struct ipt_ip *ip,
2675+ void *matchinfo, unsigned int matchsize,
2676+ unsigned int hook_mask)
2677+{
2678+ struct ipt_policy_info *info = matchinfo;
2679+
2680+ if (matchsize != IPT_ALIGN(sizeof(*info))) {
2681+ printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
2682+ matchsize, IPT_ALIGN(sizeof(*info)));
2683+ return 0;
2684+ }
2685+ if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
2686+ printk(KERN_ERR "ipt_policy: neither incoming nor "
2687+ "outgoing policy selected\n");
2688+ return 0;
2689+ }
2690+ if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
2691+ && info->flags & POLICY_MATCH_OUT) {
2692+ printk(KERN_ERR "ipt_policy: output policy not valid in "
2693+ "PRE_ROUTING and INPUT\n");
2694+ return 0;
2695+ }
2696+ if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
2697+ && info->flags & POLICY_MATCH_IN) {
2698+ printk(KERN_ERR "ipt_policy: input policy not valid in "
2699+ "POST_ROUTING and OUTPUT\n");
2700+ return 0;
2701+ }
2702+ if (info->len > POLICY_MAX_ELEM) {
2703+ printk(KERN_ERR "ipt_policy: too many policy elements\n");
2704+ return 0;
2705+ }
2706+
2707+ return 1;
2708+}
2709+
2710+static struct ipt_match policy_match =
2711+{
2712+ .name = "policy",
2713+ .match = match,
2714+ .checkentry = checkentry,
2715+ .me = THIS_MODULE,
2716+};
2717+
2718+static int __init init(void)
2719+{
2720+ return ipt_register_match(&policy_match);
2721+}
2722+
2723+static void __exit fini(void)
2724+{
2725+ ipt_unregister_match(&policy_match);
2726+}
2727+
2728+module_init(init);
2729+module_exit(fini);
2730diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_string.c
2731--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
2732+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_string.c 2004-04-19 10:47:23.000000000 +0200
2733@@ -0,0 +1,178 @@
2734+/* Kernel module to match a string into a packet.
2735+ *
2736+ * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
2737+ *
2738+ * ChangeLog
2739+ * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
2740+ * Fixed SMP re-entrancy problem using per-cpu data areas
2741+ * for the skip/shift tables.
2742+ * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
2743+ * Fixed kernel panic, due to overrunning boyer moore string
2744+ * tables. Also slightly tweaked heuristic for deciding what
2745+ * search algo to use.
2746+ * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
2747+ * Implemented Boyer Moore Sublinear search algorithm
2748+ * alongside the existing linear search based on memcmp().
2749+ * Also a quick check to decide which method to use on a per
2750+ * packet basis.
2751+ */
2752+
2753+#include <linux/smp.h>
2754+#include <linux/percpu.h>
2755+#include <linux/module.h>
2756+#include <linux/skbuff.h>
2757+#include <linux/file.h>
2758+#include <net/sock.h>
2759+
2760+#include <linux/netfilter_ipv4/ip_tables.h>
2761+#include <linux/netfilter_ipv4/ipt_string.h>
2762+
2763+MODULE_LICENSE("GPL");
2764+
2765+struct string_per_cpu {
2766+ int skip[BM_MAX_HLEN];
2767+ int shift[BM_MAX_HLEN];
2768+ int len[BM_MAX_HLEN];
2769+};
2770+
2771+static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
2772+
2773+/* Boyer Moore Sublinear string search - VERY FAST */
2774+char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
2775+{
2776+ int M1, right_end, sk, sh;
2777+ int ended, j, i;
2778+
2779+ int *skip, *shift, *len;
2780+
2781+ /* use data suitable for this CPU */
2782+ shift=__gewt_cpu_var(bm_string_data).shift;
2783+ skip=__gewt_cpu_var(bm_string_data).skip;
2784+ len=__gewt_cpu_var(bm_string_data).len;
2785+
2786+ /* Setup skip/shift tables */
2787+ M1 = right_end = needle_len-1;
2788+ for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
2789+ for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
2790+
2791+ for (i = 1; i < needle_len; i++) {
2792+ for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
2793+ len[i] = j;
2794+ }
2795+
2796+ shift[0] = 1;
2797+ for (i = 1; i < needle_len; i++) shift[i] = needle_len;
2798+ for (i = M1; i > 0; i--) shift[len[i]] = i;
2799+ ended = 0;
2800+
2801+ for (i = 0; i < needle_len; i++) {
2802+ if (len[i] == M1 - i) ended = i;
2803+ if (ended) shift[i] = ended;
2804+ }
2805+
2806+ /* Do the search*/
2807+ while (right_end < haystack_len)
2808+ {
2809+ for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
2810+ if (i == needle_len) {
2811+ return haystack+(right_end - M1);
2812+ }
2813+
2814+ sk = skip[(int)haystack[right_end - i]];
2815+ sh = shift[i];
2816+ right_end = max(right_end - i + sk, right_end + sh);
2817+ }
2818+
2819+ return NULL;
2820+}
2821+
2822+/* Linear string search based on memcmp() */
2823+char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
2824+{
2825+ char *k = haystack + (haystack_len-needle_len);
2826+ char *t = haystack;
2827+
2828+ while ( t <= k ) {
2829+ if (memcmp(t, needle, needle_len) == 0)
2830+ return t;
2831+ t++;
2832+ }
2833+
2834+ return NULL;
2835+}
2836+
2837+static int
2838+match(const struct sk_buff *skb,
2839+ const struct net_device *in,
2840+ const struct net_device *out,
2841+ const void *matchinfo,
2842+ int offset,
2843+ int *hotdrop)
2844+{
2845+ const struct ipt_string_info *info = matchinfo;
2846+ struct iphdr *ip = skb->nh.iph;
2847+ int hlen, nlen;
2848+ char *needle, *haystack;
2849+ proc_ipt_search search=search_linear;
2850+
2851+ if ( !ip ) return 0;
2852+
2853+ /* get lenghts, and validate them */
2854+ nlen=info->len;
2855+ hlen=ntohs(ip->tot_len)-(ip->ihl*4);
2856+ if ( nlen > hlen ) return 0;
2857+
2858+ needle=(char *)&info->string;
2859+ haystack=(char *)ip+(ip->ihl*4);
2860+
2861+ /* The sublinear search comes in to its own
2862+ * on the larger packets */
2863+ if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
2864+ (nlen>IPT_STRING_NEEDLE_THRESH) ) {
2865+ if ( hlen < BM_MAX_HLEN ) {
2866+ search=search_sublinear;
2867+ }else{
2868+ if (net_ratelimit())
2869+ printk(KERN_INFO "ipt_string: Packet too big "
2870+ "to attempt sublinear string search "
2871+ "(%d bytes)\n", hlen );
2872+ }
2873+ }
2874+
2875+ return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
2876+}
2877+
2878+static int
2879+checkentry(const char *tablename,
2880+ const struct ipt_ip *ip,
2881+ void *matchinfo,
2882+ unsigned int matchsize,
2883+ unsigned int hook_mask)
2884+{
2885+
2886+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
2887+ return 0;
2888+
2889+ return 1;
2890+}
2891+
2892+
2893+static struct ipt_match string_match = {
2894+ .name = "string",
2895+ .match = &match,
2896+ .checkentry = &checkentry,
2897+ .me = THIS_MODULE
2898+};
2899+
2900+static int __init init(void)
2901+{
2902+ return ipt_register_match(&string_match);
2903+}
2904+
2905+static void __exit fini(void)
2906+{
2907+ ipt_unregister_match(&string_match);
2908+}
2909+
2910+module_init(init);
2911+module_exit(fini);
2912diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc1/net/ipv4/netfilter/ipt_unclean.c
2913--- linux-2.6.6-rc1.org/net/ipv4/netfilter/ipt_unclean.c 1970-01-01 01:00:00.000000000 +0100
2914+++ linux-2.6.6-rc1/net/ipv4/netfilter/ipt_unclean.c 2004-04-19 10:47:12.000000000 +0200
2915@@ -0,0 +1,604 @@
2916+/* Kernel module to match suspect packets. */
2917+#include <linux/module.h>
2918+#include <linux/skbuff.h>
2919+#include <linux/ip.h>
2920+#include <linux/udp.h>
2921+#include <linux/tcp.h>
2922+#include <linux/icmp.h>
2923+#include <net/checksum.h>
2924+
2925+#include <linux/netfilter_ipv4/ip_tables.h>
2926+
2927+#define limpk(format, args...) \
2928+do { \
2929+ if (net_ratelimit()) \
2930+ printk("ipt_unclean: %s" format, \
2931+ embedded ? "(embedded packet) " : "" , ## args); \
2932+} while(0)
2933+
2934+enum icmp_error_status
2935+{
2936+ ICMP_MAY_BE_ERROR,
2937+ ICMP_IS_ERROR,
2938+ ICMP_NOT_ERROR
2939+};
2940+
2941+struct icmp_info
2942+{
2943+ size_t min_len, max_len;
2944+ enum icmp_error_status err;
2945+ u_int8_t min_code, max_code;
2946+};
2947+
2948+static int
2949+check_ip(struct iphdr *iph, size_t length, int embedded);
2950+
2951+/* ICMP-specific checks. */
2952+static int
2953+check_icmp(const struct icmphdr *icmph,
2954+ u_int16_t datalen,
2955+ unsigned int offset,
2956+ int more_frags,
2957+ int embedded)
2958+{
2959+ static struct icmp_info info[]
2960+ = { [ICMP_ECHOREPLY]
2961+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
2962+ [ICMP_DEST_UNREACH]
2963+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
2964+ [ICMP_SOURCE_QUENCH]
2965+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
2966+ [ICMP_REDIRECT]
2967+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
2968+ [ICMP_ECHO]
2969+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
2970+ /* Router advertisement. */
2971+ [9]
2972+ = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
2973+ /* Router solicitation. */
2974+ [10]
2975+ = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
2976+ [ICMP_TIME_EXCEEDED]
2977+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
2978+ [ICMP_PARAMETERPROB]
2979+ = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
2980+ [ICMP_TIMESTAMP]
2981+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
2982+ [ICMP_TIMESTAMPREPLY]
2983+ = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
2984+ [ICMP_INFO_REQUEST]
2985+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
2986+ [ICMP_INFO_REPLY]
2987+ = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
2988+ [ICMP_ADDRESS]
2989+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
2990+ [ICMP_ADDRESSREPLY]
2991+ = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
2992+
2993+ /* Can't do anything if it's a fragment. */
2994+ if (offset)
2995+ return 1;
2996+
2997+ /* Must cover type and code. */
2998+ if (datalen < 2) {
2999+ limpk("ICMP len=%u too short\n", datalen);
3000+ return 0;
3001+ }
3002+
3003+ /* If not embedded. */
3004+ if (!embedded) {
3005+ /* Bad checksum? Don't print, just ignore. */
3006+ if (!more_frags
3007+ && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
3008+ return 0;
3009+
3010+ /* CHECK: Truncated ICMP (even if first fragment). */
3011+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
3012+ && info[icmph->type].min_len != 0
3013+ && datalen < info[icmph->type].min_len) {
3014+ limpk("ICMP type %u len %u too short\n",
3015+ icmph->type, datalen);
3016+ return 0;
3017+ }
3018+
3019+ /* CHECK: Check within known error ICMPs. */
3020+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
3021+ && info[icmph->type].err == ICMP_IS_ERROR) {
3022+ /* CHECK: Embedded packet must be at least
3023+ length of iph + 8 bytes. */
3024+ struct iphdr *inner = (void *)icmph + 8;
3025+
3026+ /* datalen > 8 since all ICMP_IS_ERROR types
3027+ have min length > 8 */
3028+ if (datalen - 8 < sizeof(struct iphdr)) {
3029+ limpk("ICMP error internal way too short\n");
3030+ return 0;
3031+ }
3032+ if (datalen - 8 < inner->ihl*4 + 8) {
3033+ limpk("ICMP error internal too short\n");
3034+ return 0;
3035+ }
3036+ if (!check_ip(inner, datalen - 8, 1))
3037+ return 0;
3038+ }
3039+ } else {
3040+ /* CHECK: Can't embed ICMP unless known non-error. */
3041+ if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
3042+ || info[icmph->type].err != ICMP_NOT_ERROR) {
3043+ limpk("ICMP type %u not embeddable\n",
3044+ icmph->type);
3045+ return 0;
3046+ }
3047+ }
3048+
3049+ /* CHECK: Invalid ICMP codes. */
3050+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
3051+ && (icmph->code < info[icmph->type].min_code
3052+ || icmph->code > info[icmph->type].max_code)) {
3053+ limpk("ICMP type=%u code=%u\n",
3054+ icmph->type, icmph->code);
3055+ return 0;
3056+ }
3057+
3058+ /* CHECK: Above maximum length. */
3059+ if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
3060+ && info[icmph->type].max_len != 0
3061+ && datalen > info[icmph->type].max_len) {
3062+ limpk("ICMP type=%u too long: %u bytes\n",
3063+ icmph->type, datalen);
3064+ return 0;
3065+ }
3066+
3067+ switch (icmph->type) {
3068+ case ICMP_PARAMETERPROB: {
3069+ /* CHECK: Problem param must be within error packet's
3070+ * IP header. */
3071+ struct iphdr *iph = (void *)icmph + 8;
3072+ u_int32_t arg = ntohl(icmph->un.gateway);
3073+
3074+ if (icmph->code == 0) {
3075+ /* Code 0 means that upper 8 bits is pointer
3076+ to problem. */
3077+ if ((arg >> 24) >= iph->ihl*4) {
3078+ limpk("ICMP PARAMETERPROB ptr = %u\n",
3079+ ntohl(icmph->un.gateway) >> 24);
3080+ return 0;
3081+ }
3082+ arg &= 0x00FFFFFF;
3083+ }
3084+
3085+ /* CHECK: Rest must be zero. */
3086+ if (arg) {
3087+ limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
3088+ arg);
3089+ return 0;
3090+ }
3091+ break;
3092+ }
3093+
3094+ case ICMP_TIME_EXCEEDED:
3095+ case ICMP_SOURCE_QUENCH:
3096+ /* CHECK: Unused must be zero. */
3097+ if (icmph->un.gateway != 0) {
3098+ limpk("ICMP type=%u unused = %u\n",
3099+ icmph->type, ntohl(icmph->un.gateway));
3100+ return 0;
3101+ }
3102+ break;
3103+ }
3104+
3105+ return 1;
3106+}
3107+
3108+/* UDP-specific checks. */
3109+static int
3110+check_udp(const struct iphdr *iph,
3111+ const struct udphdr *udph,
3112+ u_int16_t datalen,
3113+ unsigned int offset,
3114+ int more_frags,
3115+ int embedded)
3116+{
3117+ /* Can't do anything if it's a fragment. */
3118+ if (offset)
3119+ return 1;
3120+
3121+ /* CHECK: Must cover UDP header. */
3122+ if (datalen < sizeof(struct udphdr)) {
3123+ limpk("UDP len=%u too short\n", datalen);
3124+ return 0;
3125+ }
3126+
3127+ /* Bad checksum? Don't print, just say it's unclean. */
3128+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
3129+ if (!more_frags && !embedded && udph->check
3130+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
3131+ csum_partial((char *)udph, datalen, 0)) != 0)
3132+ return 0;
3133+
3134+ /* CHECK: Destination port can't be zero. */
3135+ if (!udph->dest) {
3136+ limpk("UDP zero destination port\n");
3137+ return 0;
3138+ }
3139+
3140+ if (!more_frags) {
3141+ if (!embedded) {
3142+ /* CHECK: UDP length must match. */
3143+ if (ntohs(udph->len) != datalen) {
3144+ limpk("UDP len too short %u vs %u\n",
3145+ ntohs(udph->len), datalen);
3146+ return 0;
3147+ }
3148+ } else {
3149+ /* CHECK: UDP length be >= this truncated pkt. */
3150+ if (ntohs(udph->len) < datalen) {
3151+ limpk("UDP len too long %u vs %u\n",
3152+ ntohs(udph->len), datalen);
3153+ return 0;
3154+ }
3155+ }
3156+ } else {
3157+ /* CHECK: UDP length must be > this frag's length. */
3158+ if (ntohs(udph->len) <= datalen) {
3159+ limpk("UDP fragment len too short %u vs %u\n",
3160+ ntohs(udph->len), datalen);
3161+ return 0;
3162+ }
3163+ }
3164+
3165+ return 1;
3166+}
3167+
3168+#define TH_FIN 0x01
3169+#define TH_SYN 0x02
3170+#define TH_RST 0x04
3171+#define TH_PUSH 0x08
3172+#define TH_ACK 0x10
3173+#define TH_URG 0x20
3174+#define TH_ECE 0x40
3175+#define TH_CWR 0x80
3176+
3177+/* table of valid flag combinations - ECE and CWR are always valid */
3178+static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
3179+{
3180+ [TH_SYN] = 1,
3181+ [TH_SYN|TH_ACK] = 1,
3182+ [TH_RST] = 1,
3183+ [TH_RST|TH_ACK] = 1,
3184+ [TH_RST|TH_ACK|TH_PUSH] = 1,
3185+ [TH_FIN|TH_ACK] = 1,
3186+ [TH_ACK] = 1,
3187+ [TH_ACK|TH_PUSH] = 1,
3188+ [TH_ACK|TH_URG] = 1,
3189+ [TH_ACK|TH_URG|TH_PUSH] = 1,
3190+ [TH_FIN|TH_ACK|TH_PUSH] = 1,
3191+ [TH_FIN|TH_ACK|TH_URG] = 1,
3192+ [TH_FIN|TH_ACK|TH_URG|TH_PUSH] = 1
3193+};
3194+
3195+/* TCP-specific checks. */
3196+static int
3197+check_tcp(const struct iphdr *iph,
3198+ const struct tcphdr *tcph,
3199+ u_int16_t datalen,
3200+ unsigned int offset,
3201+ int more_frags,
3202+ int embedded)
3203+{
3204+ u_int8_t *opt = (u_int8_t *)tcph;
3205+ u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
3206+ u_int8_t tcpflags;
3207+ int end_of_options = 0;
3208+ size_t i;
3209+
3210+ /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
3211+ /* In fact, this is caught below (offset < 516). */
3212+
3213+ /* Can't do anything if it's a fragment. */
3214+ if (offset)
3215+ return 1;
3216+
3217+ /* CHECK: Smaller than minimal TCP hdr. */
3218+ if (datalen < sizeof(struct tcphdr)) {
3219+ if (!embedded) {
3220+ limpk("Packet length %u < TCP header.\n", datalen);
3221+ return 0;
3222+ }
3223+ /* Must have ports available (datalen >= 8), from
3224+ check_icmp which set embedded = 1 */
3225+ /* CHECK: TCP ports inside ICMP error */
3226+ if (!tcph->source || !tcph->dest) {
3227+ limpk("Zero TCP ports %u/%u.\n",
3228+ htons(tcph->source), htons(tcph->dest));
3229+ return 0;
3230+ }
3231+ return 1;
3232+ }
3233+
3234+ /* CHECK: Smaller than actual TCP hdr. */
3235+ if (datalen < tcph->doff * 4) {
3236+ if (!embedded) {
3237+ limpk("Packet length %u < actual TCP header.\n",
3238+ datalen);
3239+ return 0;
3240+ } else
3241+ return 1;
3242+ }
3243+
3244+ /* Bad checksum? Don't print, just say it's unclean. */
3245+ /* FIXME: SRC ROUTE packets won't match checksum --RR */
3246+ if (!more_frags && !embedded
3247+ && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
3248+ csum_partial((char *)tcph, datalen, 0)) != 0)
3249+ return 0;
3250+
3251+ /* CHECK: TCP ports non-zero */
3252+ if (!tcph->source || !tcph->dest) {
3253+ limpk("Zero TCP ports %u/%u.\n",
3254+ htons(tcph->source), htons(tcph->dest));
3255+ return 0;
3256+ }
3257+
3258+ /* CHECK: TCP reserved bits zero. */
3259+ if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
3260+ limpk("TCP reserved bits not zero\n");
3261+ return 0;
3262+ }
3263+
3264+ /* CHECK: TCP flags. */
3265+ tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
3266+ if (!tcp_valid_flags[tcpflags]) {
3267+ limpk("TCP flags bad: %u\n", tcpflags);
3268+ return 0;
3269+ }
3270+
3271+ for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
3272+ switch (opt[i]) {
3273+ case 0:
3274+ end_of_options = 1;
3275+ i++;
3276+ break;
3277+ case 1:
3278+ i++;
3279+ break;
3280+ default:
3281+ /* CHECK: options after EOO. */
3282+ if (end_of_options) {
3283+ limpk("TCP option %u after end\n",
3284+ opt[i]);
3285+ return 0;
3286+ }
3287+ /* CHECK: options at tail. */
3288+ else if (i+1 >= tcph->doff * 4) {
3289+ limpk("TCP option %u at tail\n",
3290+ opt[i]);
3291+ return 0;
3292+ }
3293+ /* CHECK: zero-length options. */
3294+ else if (opt[i+1] == 0) {
3295+ limpk("TCP option %u 0 len\n",
3296+ opt[i]);
3297+ return 0;
3298+ }
3299+ /* CHECK: oversize options. */
3300+ else if (&opt[i] + opt[i+1] > endhdr) {
3301+ limpk("TCP option %u at %Zu too long\n",
3302+ (unsigned int) opt[i], i);
3303+ return 0;
3304+ }
3305+ /* Move to next option */
3306+ i += opt[i+1];
3307+ }
3308+ }
3309+
3310+ return 1;
3311+}
3312+
3313+/* Returns 1 if ok */
3314+/* Standard IP checks. */
3315+static int
3316+check_ip(struct iphdr *iph, size_t length, int embedded)
3317+{
3318+ u_int8_t *opt = (u_int8_t *)iph;
3319+ u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
3320+ int end_of_options = 0;
3321+ void *protoh;
3322+ size_t datalen;
3323+ unsigned int i;
3324+ unsigned int offset;
3325+
3326+ /* Should only happen for local outgoing raw-socket packets. */
3327+ /* CHECK: length >= ip header. */
3328+ if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
3329+ limpk("Packet length %Zu < IP header.\n", length);
3330+ return 0;
3331+ }
3332+
3333+ offset = ntohs(iph->frag_off) & IP_OFFSET;
3334+ protoh = (void *)iph + iph->ihl * 4;
3335+ datalen = length - iph->ihl * 4;
3336+
3337+ /* CHECK: Embedded fragment. */
3338+ if (embedded && offset) {
3339+ limpk("Embedded fragment.\n");
3340+ return 0;
3341+ }
3342+
3343+ for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
3344+ switch (opt[i]) {
3345+ case 0:
3346+ end_of_options = 1;
3347+ i++;
3348+ break;
3349+ case 1:
3350+ i++;
3351+ break;
3352+ default:
3353+ /* CHECK: options after EOO. */
3354+ if (end_of_options) {
3355+ limpk("IP option %u after end\n",
3356+ opt[i]);
3357+ return 0;
3358+ }
3359+ /* CHECK: options at tail. */
3360+ else if (i+1 >= iph->ihl * 4) {
3361+ limpk("IP option %u at tail\n",
3362+ opt[i]);
3363+ return 0;
3364+ }
3365+ /* CHECK: zero-length or one-length options. */
3366+ else if (opt[i+1] < 2) {
3367+ limpk("IP option %u %u len\n",
3368+ opt[i], opt[i+1]);
3369+ return 0;
3370+ }
3371+ /* CHECK: oversize options. */
3372+ else if (&opt[i] + opt[i+1] > endhdr) {
3373+ limpk("IP option %u at %u too long\n",
3374+ opt[i], i);
3375+ return 0;
3376+ }
3377+ /* Move to next option */
3378+ i += opt[i+1];
3379+ }
3380+ }
3381+
3382+ /* Fragment checks. */
3383+
3384+ /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
3385+ if ((ntohs(iph->frag_off) & IP_MF)
3386+ && (ntohs(iph->tot_len) % 8) != 0) {
3387+ limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
3388+ return 0;
3389+ }
3390+
3391+ /* CHECK: Oversize fragment a-la Ping of Death. */
3392+ if (offset * 8 + datalen > 65535) {
3393+ limpk("Oversize fragment to %u.\n", offset * 8);
3394+ return 0;
3395+ }
3396+
3397+ /* CHECK: DF set and offset or MF set. */
3398+ if ((ntohs(iph->frag_off) & IP_DF)
3399+ && (offset || (ntohs(iph->frag_off) & IP_MF))) {
3400+ limpk("DF set and offset=%u, MF=%u.\n",
3401+ offset, ntohs(iph->frag_off) & IP_MF);
3402+ return 0;
3403+ }
3404+
3405+ /* CHECK: Zero-sized fragments. */
3406+ if ((offset || (ntohs(iph->frag_off) & IP_MF))
3407+ && datalen == 0) {
3408+ limpk("Zero size fragment offset=%u\n", offset);
3409+ return 0;
3410+ }
3411+
3412+ /* Note: we can have even middle fragments smaller than this:
3413+ consider a large packet passing through a 600MTU then
3414+ 576MTU link: this gives a fragment of 24 data bytes. But
3415+ everyone packs fragments largest first, hence a fragment
3416+ can't START before 576 - MAX_IP_HEADER_LEN. */
3417+
3418+ /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
3419+ down to 128 (576 taken from RFC 791: All hosts must be
3420+ prepared to accept datagrams of up to 576 octets). Use 128
3421+ here. */
3422+#define MIN_LIKELY_MTU 128
3423+ /* CHECK: Min size of first frag = 128. */
3424+ if ((ntohs(iph->frag_off) & IP_MF)
3425+ && offset == 0
3426+ && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
3427+ limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
3428+ MIN_LIKELY_MTU);
3429+ return 0;
3430+ }
3431+
3432+ /* CHECK: Min offset of frag = 128 - IP hdr len. */
3433+ if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
3434+ limpk("Fragment starts at %u < %u\n", offset * 8,
3435+ MIN_LIKELY_MTU - iph->ihl * 4);
3436+ return 0;
3437+ }
3438+
3439+ /* CHECK: Protocol specification non-zero. */
3440+ if (iph->protocol == 0) {
3441+ limpk("Zero protocol\n");
3442+ return 0;
3443+ }
3444+
3445+ /* CHECK: Do not use what is unused.
3446+ * First bit of fragmentation flags should be unused.
3447+ * May be used by OS fingerprinting tools.
3448+ * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
3449+ */
3450+ if (ntohs(iph->frag_off)>>15) {
3451+ limpk("IP unused bit set\n");
3452+ return 0;
3453+ }
3454+
3455+ /* Per-protocol checks. */
3456+ switch (iph->protocol) {
3457+ case IPPROTO_ICMP:
3458+ return check_icmp(protoh, datalen, offset,
3459+ (ntohs(iph->frag_off) & IP_MF),
3460+ embedded);
3461+
3462+ case IPPROTO_UDP:
3463+ return check_udp(iph, protoh, datalen, offset,
3464+ (ntohs(iph->frag_off) & IP_MF),
3465+ embedded);
3466+
3467+ case IPPROTO_TCP:
3468+ return check_tcp(iph, protoh, datalen, offset,
3469+ (ntohs(iph->frag_off) & IP_MF),
3470+ embedded);
3471+ default:
3472+ /* Ignorance is bliss. */
3473+ return 1;
3474+ }
3475+}
3476+
3477+static int
3478+match(const struct sk_buff *skb,
3479+ const struct net_device *in,
3480+ const struct net_device *out,
3481+ const void *matchinfo,
3482+ int offset,
3483+ const void *hdr,
3484+ u_int16_t datalen,
3485+ int *hotdrop)
3486+{
3487+ return !check_ip(skb->nh.iph, skb->len, 0);
3488+}
3489+
3490+/* Called when user tries to insert an entry of this type. */
3491+static int
3492+checkentry(const char *tablename,
3493+ const struct ipt_ip *ip,
3494+ void *matchinfo,
3495+ unsigned int matchsize,
3496+ unsigned int hook_mask)
3497+{
3498+ if (matchsize != IPT_ALIGN(0))
3499+ return 0;
3500+
3501+ return 1;
3502+}
3503+
3504+static struct ipt_match unclean_match
3505+= { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
3506+
3507+static int __init init(void)
3508+{
3509+ return ipt_register_match(&unclean_match);
3510+}
3511+
3512+static void __exit fini(void)
3513+{
3514+ ipt_unregister_match(&unclean_match);
3515+}
3516+
3517+module_init(init);
3518+module_exit(fini);
3519+MODULE_LICENSE("GPL");
3520diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc1/net/ipv4/tcp_ipv4.c
3521--- linux-2.6.6-rc1.org/net/ipv4/tcp_ipv4.c 2004-04-15 03:34:35.000000000 +0200
3522+++ linux-2.6.6-rc1/net/ipv4/tcp_ipv4.c 2004-04-19 10:46:08.000000000 +0200
3523@@ -2670,6 +2670,7 @@
3524 EXPORT_SYMBOL(tcp_v4_connect);
3525 EXPORT_SYMBOL(tcp_v4_do_rcv);
3526 EXPORT_SYMBOL(tcp_v4_lookup_listener);
3527+EXPORT_SYMBOL(tcp_v4_lookup);
3528 EXPORT_SYMBOL(tcp_v4_rebuild_header);
3529 EXPORT_SYMBOL(tcp_v4_remember_stamp);
3530 EXPORT_SYMBOL(tcp_v4_send_check);
3531diff -Nur --exclude '*.orig' linux-2.6.6-rc1.org/net/ipv4/udp.c linux-2.6.6-rc1/net/ipv4/udp.c
3532--- linux-2.6.6-rc1.org/net/ipv4/udp.c 2004-04-19 10:38:52.000000000 +0200
3533+++ linux-2.6.6-rc1/net/ipv4/udp.c 2004-04-19 10:46:08.000000000 +0200
3534@@ -1558,6 +1558,7 @@
3535 EXPORT_SYMBOL(udp_port_rover);
3536 EXPORT_SYMBOL(udp_prot);
3537 EXPORT_SYMBOL(udp_sendmsg);
3538+EXPORT_SYMBOL(udp_v4_lookup);
3539
3540 #ifdef CONFIG_PROC_FS
3541 EXPORT_SYMBOL(udp_proc_register);
This page took 0.669448 seconds and 4 git commands to generate.