1 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ip_conntrack.h
2 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ip_conntrack.h 2004-01-26 03:31:19.000000000 +0100
3 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ip_conntrack.h 2004-01-30 12:25:22.000000000 +0100
6 #endif /* CONFIG_IP_NF_NAT_NEEDED */
8 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
13 /* get master conntrack via master expectation */
14 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_CONNMARK.h
15 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
16 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-01-30 12:25:22.000000000 +0100
18 +#ifndef _IPT_CONNMARK_H_target
19 +#define _IPT_CONNMARK_H_target
22 + IPT_CONNMARK_SET = 0,
24 + IPT_CONNMARK_RESTORE
27 +struct ipt_connmark_target_info {
32 +#endif /*_IPT_CONNMARK_H_target*/
33 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_TTL.h
34 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
35 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_TTL.h 2004-01-30 12:25:07.000000000 +0100
37 +/* TTL modification module for IP tables
38 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
49 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
51 +struct ipt_TTL_info {
58 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_connlimit.h
59 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
60 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-01-30 12:25:34.000000000 +0100
62 +#ifndef _IPT_CONNLIMIT_H
63 +#define _IPT_CONNLIMIT_H
65 +struct ipt_connlimit_data;
67 +struct ipt_connlimit_info {
71 + struct ipt_connlimit_data *data;
73 +#endif /* _IPT_CONNLIMIT_H */
74 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_connmark.h
75 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
76 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_connmark.h 2004-01-30 12:25:22.000000000 +0100
78 +#ifndef _IPT_CONNMARK_H
79 +#define _IPT_CONNMARK_H
81 +struct ipt_connmark_info {
82 + unsigned long mark, mask;
86 +#endif /*_IPT_CONNMARK_H*/
87 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_mport.h
88 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
89 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_mport.h 2004-01-30 12:25:56.000000000 +0100
93 +#include <linux/netfilter_ipv4/ip_tables.h>
95 +#define IPT_MPORT_SOURCE (1<<0)
96 +#define IPT_MPORT_DESTINATION (1<<1)
97 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
99 +#define IPT_MULTI_PORTS 15
101 +/* Must fit inside union ipt_matchinfo: 32 bytes */
102 +/* every entry in ports[] except for the last one has one bit in pflags
103 + * associated with it. If this bit is set, the port is the first port of
104 + * a portrange, with the next entry being the last.
105 + * End of list is marked with pflags bit set and port=65535.
106 + * If 14 ports are used (last one does not have a pflag), the last port
107 + * is repeated to fill the last entry in ports[] */
110 + u_int8_t flags:2; /* Type of comparison */
111 + u_int16_t pflags:14; /* Port flags */
112 + u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
114 +#endif /*_IPT_MPORT_H*/
115 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_nth.h
116 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
117 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_nth.h 2004-01-30 12:26:19.000000000 +0100
122 +#include <linux/param.h>
123 +#include <linux/types.h>
125 +#ifndef IPT_NTH_NUM_COUNTERS
126 +#define IPT_NTH_NUM_COUNTERS 16
129 +struct ipt_nth_info {
137 +#endif /*_IPT_NTH_H*/
138 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_u32.h
139 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
140 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv4/ipt_u32.h 2004-01-30 12:25:44.000000000 +0100
144 +#include <linux/netfilter_ipv4/ip_tables.h>
154 +struct ipt_u32_location_element
159 +struct ipt_u32_value_element
164 +/* *** any way to allow for an arbitrary number of elements?
165 + for now I settle for a limit of 10 of each */
166 +#define U32MAXSIZE 10
170 + struct ipt_u32_location_element location[U32MAXSIZE+1];
172 + struct ipt_u32_value_element value[U32MAXSIZE+1];
178 + struct ipt_u32_test tests[U32MAXSIZE+1];
181 +#endif /*_IPT_U32_H*/
182 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.2-rc2/include/linux/netfilter_ipv6/ip6t_REJECT.h
183 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-01-26 03:29:50.000000000 +0100
184 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-01-30 12:26:08.000000000 +0100
186 #define _IP6T_REJECT_H
188 enum ip6t_reject_with {
189 - IP6T_ICMP_NET_UNREACHABLE,
190 - IP6T_ICMP_HOST_UNREACHABLE,
191 - IP6T_ICMP_PROT_UNREACHABLE,
192 - IP6T_ICMP_PORT_UNREACHABLE,
193 - IP6T_ICMP_ECHOREPLY
194 + IP6T_ICMP6_NO_ROUTE,
195 + IP6T_ICMP6_ADM_PROHIBITED,
196 + IP6T_ICMP6_NOT_NEIGHBOUR,
197 + IP6T_ICMP6_ADDR_UNREACH,
198 + IP6T_ICMP6_PORT_UNREACH,
199 + IP6T_ICMP6_ECHOREPLY,
203 struct ip6t_reject_info {
204 enum ip6t_reject_with with; /* reject type */
207 -#endif /*_IPT_REJECT_H*/
208 +#endif /*_IP6T_REJECT_H*/
209 diff -Nur linux-2.6.2-rc2.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.2-rc2/include/linux/netfilter_ipv6/ip6t_nth.h
210 --- linux-2.6.2-rc2.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
211 +++ linux-2.6.2-rc2/include/linux/netfilter_ipv6/ip6t_nth.h 2004-01-30 12:26:19.000000000 +0100
216 +#include <linux/param.h>
217 +#include <linux/types.h>
219 +#ifndef IP6T_NTH_NUM_COUNTERS
220 +#define IP6T_NTH_NUM_COUNTERS 16
223 +struct ip6t_nth_info {
231 +#endif /*_IP6T_NTH_H*/
232 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/Kconfig linux-2.6.2-rc2/net/ipv4/netfilter/Kconfig
233 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/Kconfig 2004-01-26 03:31:15.000000000 +0100
234 +++ linux-2.6.2-rc2/net/ipv4/netfilter/Kconfig 2004-01-30 12:26:19.000000000 +0100
235 @@ -579,5 +579,140 @@
237 To compile it as a module, choose M here. If unsure, say N.
239 +config IP_NF_TARGET_TTL
240 + tristate 'TTL target support'
241 + depends on IP_NF_MANGLE
243 + This adds an iptables TTL manipulation target, which enables the user
244 + to set the TTL value of an IP packet or to increment / decrement it
247 +config IP_NF_CONNTRACK_MARK
248 + bool 'Connection mark tracking support'
249 +config IP_NF_TARGET_CONNMARK
250 + tristate 'CONNMARK target support'
251 + depends on IP_NF_MANGLE
252 +config IP_NF_MATCH_CONNMARK
253 + tristate ' Connection mark match support'
254 + depends on IP_NF_IPTABLES
257 + This patch adds per connection marks, and a target (CONNMARK)
258 + respective a match (connmark) for using these.
263 + This module matches the netfilter mark field associated
264 + with a connection (which can be set using the CONNMARK
267 + --mark value[/mask]
268 + Matches packets in connections with the given
269 + unsigned mark value (if a mask is specified, this
270 + is logically ANDed with the mark before the comparison).
274 + This is used to set the netfilter mark value associated
275 + with the connection
278 + Set connection mark
281 + Set connection mark to the same as the one on the
285 + Set the netfilter packet mark value to the one
286 + associated with the connection. This is only valid
287 + in the mangle table.
289 +config IP_NF_MATCH_CONNLIMIT
290 + tristate 'Connections/IP limit match support'
291 + depends on IP_NF_IPTABLES
293 + This adds an iptables match which allows you to restrict the
294 + number of parallel TCP connections to a server per client IP address
295 + (or address block).
299 + # allow 2 telnet connections per client host
300 + iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
302 + # you can also match the other way around:
303 + iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
305 + # limit the nr of parallel http requests to 16 per class C sized
306 + # network (24 bit netmask)
307 + iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 \
308 + --connlimit-mask 24 -j REJECT
310 +config IP_NF_MATCH_U32
311 + tristate 'U32 match support'
312 + depends on IP_NF_IPTABLES
315 + U32 allows you to extract quantities of up to 4 bytes from a packet,
316 + AND them with specified masks, shift them by specified amounts and
317 + test whether the results are in any of a set of specified ranges.
318 + The specification of what to extract is general enough to skip over
319 + headers with lengths stored in the packet, as in IP or TCP header
321 + Details and examples are in the kernel module source.
323 +config IP_NF_MATCH_MPORT
324 + tristate 'Multiple port with ranges match support'
325 + depends on IP_NF_IPTABLES
327 + This module is an enhanced multiport match. It has support for byte
328 + ranges as well as for single ports.
329 + Up to 15 ports are allowed. Note that a portrange uses up 2 port values.
332 + # iptables -A FORWARD -p tcp -m mport --ports 23:42,65
334 +config IP_NF_MATCH_NTH
335 + tristate 'Nth match support'
336 + depends on IP_NF_IPTABLES
338 + This option adds an iptables `Nth' match, which allows you to match every Nth
339 + packet encountered. By default there are 16 different counters that can be
342 + This match functions in one of two ways
343 + 1) Match ever Nth packet, and only the Nth packet.
345 + iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
346 + This rule will drop every 10th packet.
347 + 2) Unique rule for every packet. This is an easy and quick
348 + method to produce load-balancing for both inbound and outbound.
350 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
351 + --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
352 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
353 + --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
354 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
355 + --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
356 + This example evenly splits connections between the three SNAT
359 + By using the mangle table and iproute2, you can setup complex
360 + load-balanced routing. There's lot of other uses. Be creative!
362 + Suppported options are:
363 + --every Nth Match every Nth packet
364 + [--counter] num Use counter 0-15 (default:0)
365 + [--start] num Initialize the counter at the number 'num'
366 + instead of 0. Must be between 0 and Nth-1
367 + [--packet] num Match on 'num' packet. Must be between 0
369 + If --packet is used for a counter than
370 + there must be Nth number of --packet
371 + rules, covering all values between 0 and
376 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/Makefile linux-2.6.2-rc2/net/ipv4/netfilter/Makefile
377 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/Makefile 2004-01-26 03:30:09.000000000 +0100
378 +++ linux-2.6.2-rc2/net/ipv4/netfilter/Makefile 2004-01-30 12:26:19.000000000 +0100
381 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
382 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
384 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
386 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
387 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
389 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
391 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
393 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
396 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
398 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
401 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
402 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
403 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
404 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
405 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
408 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
409 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
410 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
411 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
412 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
413 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
414 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
416 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.2-rc2/net/ipv4/netfilter/ip_conntrack_core.c
417 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ip_conntrack_core.c 2004-01-26 03:29:48.000000000 +0100
418 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ip_conntrack_core.c 2004-01-30 12:25:22.000000000 +0100
420 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
421 conntrack->master = expected;
422 expected->sibling = conntrack;
423 +#if CONFIG_IP_NF_CONNTRACK_MARK
424 + conntrack->mark = expected->expectant->mark;
426 LIST_DELETE(&ip_conntrack_expect_list, expected);
427 expected->expectant->expecting--;
428 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
429 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.2-rc2/net/ipv4/netfilter/ip_conntrack_standalone.c
430 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-01-26 03:30:37.000000000 +0100
431 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ip_conntrack_standalone.c 2004-01-30 12:25:22.000000000 +0100
433 len += sprintf(buffer + len, "[ASSURED] ");
434 len += sprintf(buffer + len, "use=%u ",
435 atomic_read(&conntrack->ct_general.use));
436 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
437 + len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
439 len += sprintf(buffer + len, "\n");
442 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.2-rc2/net/ipv4/netfilter/ipt_CONNMARK.c
443 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_CONNMARK.c 1970-01-01 01:00:00.000000000 +0100
444 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ipt_CONNMARK.c 2004-01-30 12:25:22.000000000 +0100
446 +/* This is a module which is used for setting/remembering the mark field of
447 + * an connection, or optionally restore it to the skb
449 +#include <linux/module.h>
450 +#include <linux/skbuff.h>
451 +#include <linux/ip.h>
452 +#include <net/checksum.h>
454 +#include <linux/netfilter_ipv4/ip_tables.h>
455 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
456 +#include <linux/netfilter_ipv4/ip_conntrack.h>
459 +target(struct sk_buff **pskb,
460 + unsigned int hooknum,
461 + const struct net_device *in,
462 + const struct net_device *out,
463 + const void *targinfo,
466 + const struct ipt_connmark_target_info *markinfo = targinfo;
468 + enum ip_conntrack_info ctinfo;
469 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
471 + switch(markinfo->mode) {
472 + case IPT_CONNMARK_SET:
473 + ct->mark = markinfo->mark;
475 + case IPT_CONNMARK_SAVE:
476 + ct->mark = (*pskb)->nfmark;
478 + case IPT_CONNMARK_RESTORE:
479 + if (ct->mark != (*pskb)->nfmark) {
480 + (*pskb)->nfmark = ct->mark;
481 + (*pskb)->nfcache |= NFC_ALTERED;
487 + return IPT_CONTINUE;
491 +checkentry(const char *tablename,
492 + const struct ipt_entry *e,
494 + unsigned int targinfosize,
495 + unsigned int hook_mask)
497 + struct ipt_connmark_target_info *matchinfo = targinfo;
498 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
499 + printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
501 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
505 + if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
506 + if (strcmp(tablename, "mangle") != 0) {
507 + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
515 +static struct ipt_target ipt_connmark_reg = {
516 + .name = "CONNMARK",
518 + .checkentry = checkentry,
522 +static int __init init(void)
524 + if (ipt_register_target(&ipt_connmark_reg))
530 +static void __exit fini(void)
532 + ipt_unregister_target(&ipt_connmark_reg);
537 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.2-rc2/net/ipv4/netfilter/ipt_TTL.c
538 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
539 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ipt_TTL.c 2004-01-30 12:25:07.000000000 +0100
541 +/* TTL modification target for IP tables
542 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
546 + * This software is distributed under the terms of GNU GPL
549 +#include <linux/module.h>
550 +#include <linux/skbuff.h>
551 +#include <linux/ip.h>
552 +#include <net/checksum.h>
554 +#include <linux/netfilter_ipv4/ip_tables.h>
555 +#include <linux/netfilter_ipv4/ipt_TTL.h>
557 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
558 +MODULE_DESCRIPTION("IP tables TTL modification module");
559 +MODULE_LICENSE("GPL");
561 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
562 + const struct net_device *in, const struct net_device *out,
563 + const void *targinfo, void *userinfo)
565 + struct iphdr *iph = (*pskb)->nh.iph;
566 + const struct ipt_TTL_info *info = targinfo;
567 + u_int16_t diffs[2];
570 + switch (info->mode) {
572 + new_ttl = info->ttl;
575 + new_ttl = iph->ttl + info->ttl;
580 + new_ttl = iph->ttl + info->ttl;
585 + new_ttl = iph->ttl;
589 + if (new_ttl != iph->ttl) {
590 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
591 + iph->ttl = new_ttl;
592 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
593 + iph->check = csum_fold(csum_partial((char *)diffs,
595 + iph->check^0xFFFF));
596 + (*pskb)->nfcache |= NFC_ALTERED;
599 + return IPT_CONTINUE;
602 +static int ipt_ttl_checkentry(const char *tablename,
603 + const struct ipt_entry *e,
605 + unsigned int targinfosize,
606 + unsigned int hook_mask)
608 + struct ipt_TTL_info *info = targinfo;
610 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
611 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
613 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
617 + if (strcmp(tablename, "mangle")) {
618 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
622 + if (info->mode > IPT_TTL_MAXMODE) {
623 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
628 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
629 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
636 +static struct ipt_target ipt_TTL = {
638 + .target = ipt_ttl_target,
639 + .checkentry = ipt_ttl_checkentry,
643 +static int __init init(void)
645 + return ipt_register_target(&ipt_TTL);
648 +static void __exit fini(void)
650 + ipt_unregister_target(&ipt_TTL);
655 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.2-rc2/net/ipv4/netfilter/ipt_connlimit.c
656 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
657 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ipt_connlimit.c 2004-01-30 12:25:34.000000000 +0100
660 + * netfilter module to limit the number of parallel tcp
661 + * connections per IP address.
662 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
663 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
664 + * only ignore TIME_WAIT or gone connections
668 + * Kernel module to match connection tracking information.
669 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
671 +#include <linux/module.h>
672 +#include <linux/skbuff.h>
673 +#include <linux/list.h>
674 +#include <linux/netfilter_ipv4/ip_conntrack.h>
675 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
676 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
677 +#include <linux/netfilter_ipv4/ip_tables.h>
678 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
682 +MODULE_LICENSE("GPL");
684 +/* we'll save the tuples of all connections we care about */
685 +struct ipt_connlimit_conn
687 + struct list_head list;
688 + struct ip_conntrack_tuple tuple;
691 +struct ipt_connlimit_data {
693 + struct list_head iphash[256];
696 +static int ipt_iphash(u_int32_t addr)
700 + hash = addr & 0xff;
701 + hash ^= (addr >> 8) & 0xff;
702 + hash ^= (addr >> 16) & 0xff;
703 + hash ^= (addr >> 24) & 0xff;
707 +static int count_them(struct ipt_connlimit_data *data,
708 + u_int32_t addr, u_int32_t mask,
709 + struct ip_conntrack *ct)
712 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
713 + "fin_wait", "time_wait", "close", "close_wait",
714 + "last_ack", "listen" };
716 + int addit = 1, matches = 0;
717 + struct ip_conntrack_tuple tuple;
718 + struct ip_conntrack_tuple_hash *found;
719 + struct ipt_connlimit_conn *conn;
720 + struct list_head *hash,*lh;
722 + spin_lock(&data->lock);
723 + tuple = ct->tuplehash[0].tuple;
724 + hash = &data->iphash[ipt_iphash(addr & mask)];
726 + /* check the saved connections */
727 + for (lh = hash->next; lh != hash; lh = lh->next) {
728 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
729 + found = ip_conntrack_find_get(&conn->tuple,ct);
730 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
732 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
733 + /* Just to be sure we have it only once in the list.
734 + We should'nt see tuples twice unless someone hooks this
735 + into a table without "-p tcp --syn" */
739 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
740 + ipt_iphash(addr & mask),
741 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
742 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
743 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
745 + if (NULL == found) {
746 + /* this one is gone */
748 + list_del(lh->next);
752 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
753 + /* we don't care about connections which are
754 + closed already -> ditch it */
756 + list_del(lh->next);
758 + nf_conntrack_put(&found->ctrack->infos[0]);
761 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
762 + /* same source IP address -> be counted! */
765 + nf_conntrack_put(&found->ctrack->infos[0]);
768 + /* save the new connection in our list */
770 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
771 + ipt_iphash(addr & mask),
772 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
773 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
775 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
778 + memset(conn,0,sizeof(*conn));
779 + INIT_LIST_HEAD(&conn->list);
780 + conn->tuple = tuple;
781 + list_add(&conn->list,hash);
784 + spin_unlock(&data->lock);
789 +match(const struct sk_buff *skb,
790 + const struct net_device *in,
791 + const struct net_device *out,
792 + const void *matchinfo,
798 + const struct ipt_connlimit_info *info = matchinfo;
799 + int connections, match;
800 + struct ip_conntrack *ct;
801 + enum ip_conntrack_info ctinfo;
803 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
805 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
809 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
810 + if (-1 == connections) {
811 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
812 + *hotdrop = 1; /* let's free some memory :-) */
815 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
817 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
818 + "connections=%d limit=%d match=%s\n",
819 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
820 + connections, info->limit, match ? "yes" : "no");
826 +static int check(const char *tablename,
827 + const struct ipt_ip *ip,
829 + unsigned int matchsize,
830 + unsigned int hook_mask)
832 + struct ipt_connlimit_info *info = matchinfo;
836 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
839 + /* refuse anything but tcp */
840 + if (ip->proto != IPPROTO_TCP)
843 + /* init private data */
844 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
845 + spin_lock_init(&(info->data->lock));
846 + for (i = 0; i < 256; i++)
847 + INIT_LIST_HEAD(&(info->data->iphash[i]));
852 +static void destroy(void *matchinfo, unsigned int matchinfosize)
854 + struct ipt_connlimit_info *info = matchinfo;
855 + struct ipt_connlimit_conn *conn;
856 + struct list_head *hash;
860 + for (i = 0; i < 256; i++) {
861 + hash = &(info->data->iphash[i]);
862 + while (hash != hash->next) {
863 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
864 + list_del(hash->next);
871 +static struct ipt_match connlimit_match
872 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
874 +static int __init init(void)
876 + /* NULL if ip_conntrack not a module */
877 + if (ip_conntrack_module)
878 + __MOD_INC_USE_COUNT(ip_conntrack_module);
879 + return ipt_register_match(&connlimit_match);
882 +static void __exit fini(void)
884 + ipt_unregister_match(&connlimit_match);
885 + if (ip_conntrack_module)
886 + __MOD_DEC_USE_COUNT(ip_conntrack_module);
891 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.2-rc2/net/ipv4/netfilter/ipt_connmark.c
892 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_connmark.c 1970-01-01 01:00:00.000000000 +0100
893 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ipt_connmark.c 2004-01-30 12:25:22.000000000 +0100
895 +/* Kernel module to match connection mark values. */
896 +#include <linux/module.h>
897 +#include <linux/skbuff.h>
899 +#include <linux/netfilter_ipv4/ip_tables.h>
900 +#include <linux/netfilter_ipv4/ipt_connmark.h>
901 +#include <linux/netfilter_ipv4/ip_conntrack.h>
904 +match(const struct sk_buff *skb,
905 + const struct net_device *in,
906 + const struct net_device *out,
907 + const void *matchinfo,
913 + const struct ipt_connmark_info *info = matchinfo;
914 + enum ip_conntrack_info ctinfo;
915 + struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
919 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
923 +checkentry(const char *tablename,
924 + const struct ipt_ip *ip,
926 + unsigned int matchsize,
927 + unsigned int hook_mask)
929 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
935 +static struct ipt_match connmark_match = {
936 + .name = "connmark",
938 + .checkentry = &checkentry,
942 +static int __init init(void)
944 + return ipt_register_match(&connmark_match);
947 +static void __exit fini(void)
949 + ipt_unregister_match(&connmark_match);
954 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.2-rc2/net/ipv4/netfilter/ipt_mport.c
955 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
956 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ipt_mport.c 2004-01-30 12:25:56.000000000 +0100
958 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
959 + the same place so we can treat them as equal. */
960 +#include <linux/module.h>
961 +#include <linux/types.h>
962 +#include <linux/udp.h>
963 +#include <linux/skbuff.h>
965 +#include <linux/netfilter_ipv4/ipt_mport.h>
966 +#include <linux/netfilter_ipv4/ip_tables.h>
968 +MODULE_LICENSE("GPL");
971 +#define duprintf(format, args...) printk(format , ## args)
973 +#define duprintf(format, args...)
976 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
978 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
982 + u_int16_t pflags = minfo->pflags;
983 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
987 + && minfo->ports[i] == 65535)
990 + s = minfo->ports[i];
993 + e = minfo->ports[++i];
998 + if (minfo->flags & IPT_MPORT_SOURCE
999 + && src >= s && src <= e)
1002 + if (minfo->flags & IPT_MPORT_DESTINATION
1003 + && dst >= s && dst <= e)
1011 +match(const struct sk_buff *skb,
1012 + const struct net_device *in,
1013 + const struct net_device *out,
1014 + const void *matchinfo,
1017 + u_int16_t datalen,
1020 + const struct udphdr *udp = hdr;
1021 + const struct ipt_mport *minfo = matchinfo;
1023 + /* Must be big enough to read ports. */
1024 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
1025 + /* We've been asked to examine this packet, and we
1026 + can't. Hence, no choice but to drop. */
1027 + duprintf("ipt_mport:"
1028 + " Dropping evil offset=0 tinygram.\n");
1033 + /* Must not be a fragment. */
1035 + && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
1038 +/* Called when user tries to insert an entry of this type. */
1040 +checkentry(const char *tablename,
1041 + const struct ipt_ip *ip,
1043 + unsigned int matchsize,
1044 + unsigned int hook_mask)
1046 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
1049 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
1050 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
1051 + && !(ip->invflags & IPT_INV_PROTO)
1052 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
1055 +static struct ipt_match mport_match
1056 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
1058 +static int __init init(void)
1060 + return ipt_register_match(&mport_match);
1063 +static void __exit fini(void)
1065 + ipt_unregister_match(&mport_match);
1070 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.2-rc2/net/ipv4/netfilter/ipt_nth.c
1071 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
1072 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ipt_nth.c 2004-01-30 12:26:19.000000000 +0100
1075 + This is a module which is used for match support for every Nth packet
1076 + This file is distributed under the terms of the GNU General Public
1077 + License (GPL). Copies of the GPL can be obtained from:
1078 + ftp://prep.ai.mit.edu/pub/gnu/GPL
1080 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
1081 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
1082 + * added support for multiple counters
1083 + * added support for matching on individual packets
1084 + in the counter cycle
1088 +#include <linux/module.h>
1089 +#include <linux/skbuff.h>
1090 +#include <linux/ip.h>
1091 +#include <net/tcp.h>
1092 +#include <linux/spinlock.h>
1093 +#include <linux/netfilter_ipv4/ip_tables.h>
1094 +#include <linux/netfilter_ipv4/ipt_nth.h>
1096 +MODULE_LICENSE("GPL");
1099 + * State information.
1106 +static struct state states[IPT_NTH_NUM_COUNTERS];
1109 +ipt_nth_match(const struct sk_buff *pskb,
1110 + const struct net_device *in,
1111 + const struct net_device *out,
1112 + const void *matchinfo,
1115 + u_int16_t datalen,
1118 + /* Parameters from userspace */
1119 + const struct ipt_nth_info *info = matchinfo;
1120 + unsigned counter = info->counter;
1121 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
1123 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
1127 + spin_lock(&states[counter].lock);
1129 + /* Are we matching every nth packet?*/
1130 + if (info->packet == 0xFF)
1132 + /* We're matching every nth packet and only every nth packet*/
1133 + /* Do we match or invert match? */
1134 + if (info->not == 0)
1136 + if (states[counter].number == 0)
1138 + ++states[counter].number;
1141 + if (states[counter].number >= info->every)
1142 + states[counter].number = 0; /* reset the counter */
1144 + ++states[counter].number;
1149 + if (states[counter].number == 0)
1151 + ++states[counter].number;
1154 + if (states[counter].number >= info->every)
1155 + states[counter].number = 0;
1157 + ++states[counter].number;
1163 + /* We're using the --packet, so there must be a rule for every value */
1164 + if (states[counter].number == info->packet)
1166 + /* only increment the counter when a match happens */
1167 + if (states[counter].number >= info->every)
1168 + states[counter].number = 0; /* reset the counter */
1170 + ++states[counter].number;
1179 + spin_unlock(&states[counter].lock);
1183 + spin_unlock(&states[counter].lock);
1188 +ipt_nth_checkentry(const char *tablename,
1189 + const struct ipt_ip *e,
1191 + unsigned int matchsize,
1192 + unsigned int hook_mask)
1194 + /* Parameters from userspace */
1195 + const struct ipt_nth_info *info = matchinfo;
1196 + unsigned counter = info->counter;
1197 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
1199 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
1203 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
1204 + printk("nth: matchsize %u != %u\n", matchsize,
1205 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
1209 + states[counter].number = info->startat;
1214 +static struct ipt_match ipt_nth_reg = {
1218 + ipt_nth_checkentry,
1222 +static int __init init(void)
1225 + memset(&states, 0, sizeof(states));
1226 + if (ipt_register_match(&ipt_nth_reg))
1229 + for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
1231 + spin_lock_init(&(states[counter].lock));
1234 + printk("ipt_nth match loaded\n");
1238 +static void __exit fini(void)
1240 + ipt_unregister_match(&ipt_nth_reg);
1241 + printk("ipt_nth match unloaded\n");
1246 diff -Nur linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.2-rc2/net/ipv4/netfilter/ipt_u32.c
1247 --- linux-2.6.2-rc2.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
1248 +++ linux-2.6.2-rc2/net/ipv4/netfilter/ipt_u32.c 2004-01-30 12:25:44.000000000 +0100
1250 +/* Kernel module to match u32 packet content. */
1253 +U32 tests whether quantities of up to 4 bytes extracted from a packet
1254 +have specified values. The specification of what to extract is general
1255 +enough to find data at given offsets from tcp headers or payloads.
1258 + The argument amounts to a program in a small language described below.
1259 + tests := location = value | tests && location = value
1260 + value := range | value , range
1261 + range := number | number : number
1262 + a single number, n, is interpreted the same as n:n
1263 + n:m is interpreted as the range of numbers >=n and <=m
1264 + location := number | location operator number
1265 + operator := & | << | >> | @
1267 + The operators &, <<, >>, && mean the same as in c. The = is really a set
1268 + membership operator and the value syntax describes a set. The @ operator
1269 + is what allows moving to the next header and is described further below.
1271 + *** Until I can find out how to avoid it, there are some artificial limits
1272 + on the size of the tests:
1273 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
1274 + - no more than 10 ranges (and 9 commas) per value
1275 + - no more than 10 numbers (and 9 operators) per location
1277 + To describe the meaning of location, imagine the following machine that
1278 + interprets it. There are three registers:
1279 + A is of type char*, initially the address of the IP header
1280 + B and C are unsigned 32 bit integers, initially zero
1282 + The instructions are:
1283 + number B = number;
1284 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
1285 + &number C = C&number
1286 + <<number C = C<<number
1287 + >>number C = C>>number
1288 + @number A = A+C; then do the instruction number
1289 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
1290 + Otherwise the result of the computation is the final value of C.
1292 + Whitespace is allowed but not required in the tests.
1293 + However the characters that do occur there are likely to require
1294 + shell quoting, so it's a good idea to enclose the arguments in quotes.
1297 + match IP packets with total length >= 256
1298 + The IP header contains a total length field in bytes 2-3.
1299 + --u32 "0&0xFFFF=0x100:0xFFFF"
1301 + AND that with FFFF (giving bytes 2-3),
1302 + and test whether that's in the range [0x100:0xFFFF]
1304 +Example: (more realistic, hence more complicated)
1305 + match icmp packets with icmp type 0
1306 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
1307 + --u32 "6&0xFF=1 && ...
1308 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
1309 + Next test that it's not a fragment.
1310 + (If so it might be part of such a packet but we can't always tell.)
1311 + n.b. This test is generally needed if you want to match anything
1312 + beyond the IP header.
1313 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
1314 + packet (not a fragment). Alternatively, you can allow first fragments
1315 + by only testing the last 5 bits of byte 6.
1316 + ... 4&0x3FFF=0 && ...
1317 + Last test: the first byte past the IP header (the type) is 0
1318 + This is where we have to use the @syntax. The length of the IP header
1319 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
1321 + ... 0>>22&0x3C@0>>24=0"
1322 + The first 0 means read bytes 0-3,
1323 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
1324 + the first byte, so only 22 bits is four times that plus a few more bits.
1325 + &3C then eliminates the two extra bits on the right and the first four
1326 + bits of the first byte.
1327 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
1328 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
1329 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
1330 + @ means to use this number as a new offset into the packet, and read
1331 + four bytes starting from there. This is the first 4 bytes of the icmp
1332 + payload, of which byte 0 is the icmp type. Therefore we simply shift
1333 + the value 24 to the right to throw out all but the first byte and compare
1334 + the result with 0.
1337 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
1338 + First we test that the packet is a tcp packet (similar to icmp).
1339 + --u32 "6&0xFF=6 && ...
1340 + Next, test that it's not a fragment (same as above).
1341 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
1342 + 0>>22&3C as above computes the number of bytes in the IP header.
1343 + @ makes this the new offset into the packet, which is the start of the
1344 + tcp header. The length of the tcp header (again in 32 bit words) is
1345 + the left half of byte 12 of the tcp header. The 12>>26&3C
1346 + computes this length in bytes (similar to the IP header before).
1347 + @ makes this the new offset, which is the start of the tcp payload.
1348 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
1349 + result is any of 1, 2, 5 or 8
1352 +#include <linux/module.h>
1353 +#include <linux/skbuff.h>
1355 +#include <linux/netfilter_ipv4/ipt_u32.h>
1356 +#include <linux/netfilter_ipv4/ip_tables.h>
1358 +/* #include <asm-i386/timex.h> for timing */
1360 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
1361 +MODULE_DESCRIPTION("IP tables u32 matching module");
1362 +MODULE_LICENSE("GPL");
1365 +match(const struct sk_buff *skb,
1366 + const struct net_device *in,
1367 + const struct net_device *out,
1368 + const void *matchinfo,
1371 + u_int16_t datalen,
1374 + const struct ipt_u32 *data = matchinfo;
1376 + unsigned char* origbase = (char*)skb->nh.iph;
1377 + unsigned char* base = origbase;
1378 + unsigned char* head = skb->head;
1379 + unsigned char* end = skb->end;
1381 + u_int32_t pos, val;
1382 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
1383 + cycles1 = get_cycles(); */
1385 + for (testind=0; testind < data->ntests; testind++) {
1386 + base = origbase; /* reset for each test */
1387 + pos = data->tests[testind].location[0].number;
1388 + if (base+pos+3 > end || base+pos < head)
1390 + val = (base[pos]<<24) + (base[pos+1]<<16) +
1391 + (base[pos+2]<<8) + base[pos+3];
1392 + nnums = data->tests[testind].nnums;
1393 + for (i=1; i < nnums; i++) {
1394 + u_int32_t number = data->tests[testind].location[i].number;
1395 + switch (data->tests[testind].location[i].nextop) {
1397 + val = val & number;
1399 + case IPT_U32_LEFTSH:
1400 + val = val << number;
1402 + case IPT_U32_RIGHTSH:
1403 + val = val >> number;
1406 + base = base + val;
1408 + if (base+pos+3 > end || base+pos < head)
1410 + val = (base[pos]<<24) + (base[pos+1]<<16) +
1411 + (base[pos+2]<<8) + base[pos+3];
1415 + nvals = data->tests[testind].nvalues;
1416 + for (i=0; i < nvals; i++) {
1417 + if ((data->tests[testind].value[i].min <= val) &&
1418 + (val <= data->tests[testind].value[i].max)) {
1422 + if (i >= data->tests[testind].nvalues) {
1423 + /* cycles2 = get_cycles();
1424 + printk("failed %d in %d cycles\n", testind,
1425 + cycles2-cycles1); */
1429 + /* cycles2 = get_cycles();
1430 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
1435 +checkentry(const char *tablename,
1436 + const struct ipt_ip *ip,
1438 + unsigned int matchsize,
1439 + unsigned int hook_mask)
1441 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
1446 +static struct ipt_match u32_match
1447 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
1449 +static int __init init(void)
1451 + return ipt_register_match(&u32_match);
1454 +static void __exit fini(void)
1456 + ipt_unregister_match(&u32_match);
1461 diff -Nur linux-2.6.2-rc2.org/net/ipv6/netfilter/Kconfig linux-2.6.2-rc2/net/ipv6/netfilter/Kconfig
1462 --- linux-2.6.2-rc2.org/net/ipv6/netfilter/Kconfig 2004-01-26 03:31:18.000000000 +0100
1463 +++ linux-2.6.2-rc2/net/ipv6/netfilter/Kconfig 2004-01-30 12:26:19.000000000 +0100
1464 @@ -218,5 +218,53 @@
1465 To compile it as a module, choose M here. If unsure, say N.
1467 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
1468 +config IP6_NF_TARGET_REJECT
1469 + tristate 'REJECT target support'
1470 + depends on IP6_NF_FILTER
1472 + This CONFIG_IP6_NF_TARGET_REJECT option adds a REJECT target to ip6tables.
1473 + Please keep in mind that the icmp-types are different from the icmpv6 types
1474 + (see ip6tables -j REJECT -h for more info)
1476 +config IP6_NF_MATCH_NTH
1477 + tristate 'Nth match support'
1478 + depends on IP6_NF_IPTABLES
1480 + This option adds an iptables `Nth' match, which allows you to match every Nth
1481 + packet encountered. By default there are 16 different counters that can be
1484 + This match functions in one of two ways
1485 + 1) Match ever Nth packet, and only the Nth packet.
1487 + iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
1488 + This rule will drop every 10th packet.
1489 + 2) Unique rule for every packet. This is an easy and quick
1490 + method to produce load-balancing for both inbound and outbound.
1492 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1493 + --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
1494 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1495 + --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
1496 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1497 + --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
1498 + This example evenly splits connections between the three SNAT
1501 + By using the mangle table and iproute2, you can setup complex
1502 + load-balanced routing. There's lot of other uses. Be creative!
1504 + Suppported options are:
1505 + --every Nth Match every Nth packet
1506 + [--counter] num Use counter 0-15 (default:0)
1507 + [--start] num Initialize the counter at the number 'num'
1508 + instead of 0. Must be between 0 and Nth-1
1509 + [--packet] num Match on 'num' packet. Must be between 0
1511 + If --packet is used for a counter than
1512 + there must be Nth number of --packet
1513 + rules, covering all values between 0 and
1514 + Nth-1 inclusively.
1518 diff -Nur linux-2.6.2-rc2.org/net/ipv6/netfilter/Makefile linux-2.6.2-rc2/net/ipv6/netfilter/Makefile
1519 --- linux-2.6.2-rc2.org/net/ipv6/netfilter/Makefile 2004-01-26 03:30:53.000000000 +0100
1520 +++ linux-2.6.2-rc2/net/ipv6/netfilter/Makefile 2004-01-30 12:26:19.000000000 +0100
1522 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
1523 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
1524 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
1525 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
1526 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
1527 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
1529 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
1530 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
1531 diff -Nur linux-2.6.2-rc2.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.2-rc2/net/ipv6/netfilter/ip6t_REJECT.c
1532 --- linux-2.6.2-rc2.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
1533 +++ linux-2.6.2-rc2/net/ipv6/netfilter/ip6t_REJECT.c 2004-01-30 12:26:08.000000000 +0100
1536 + * This is a module which is used for rejecting packets.
1537 + * Added support for customized reject packets (Jozsef Kadlecsik).
1539 + * Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
1541 +#include <linux/config.h>
1542 +#include <linux/module.h>
1543 +#include <linux/skbuff.h>
1544 +#include <linux/icmpv6.h>
1545 +#include <net/tcp.h>
1546 +#include <linux/netfilter_ipv6/ip6_tables.h>
1547 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
1550 +#define DEBUGP printk
1552 +#define DEBUGP(format, args...)
1556 +/* Send RST reply */
1557 +static void send_reset(struct sk_buff *oldskb)
1559 + struct sk_buff *nskb;
1560 + struct tcphdr *otcph, *tcph;
1561 + struct rtable *rt;
1562 + unsigned int otcplen;
1565 + /* IP header checks: fragment, too short. */
1566 + if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
1567 + || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
1570 + otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
1571 + otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
1573 + /* No RST for RST. */
1577 + /* Check checksum. */
1578 + if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
1579 + oldskb->nh.iph->daddr,
1580 + csum_partial((char *)otcph, otcplen, 0)) != 0)
1583 + /* Copy skb (even if skb is about to be dropped, we can't just
1584 + clone it because there may be other things, such as tcpdump,
1585 + interested in it) */
1586 + nskb = skb_copy(oldskb, GFP_ATOMIC);
1590 + /* This packet will not be the same as the other: clear nf fields */
1591 + nf_conntrack_put(nskb->nfct);
1592 + nskb->nfct = NULL;
1593 + nskb->nfcache = 0;
1594 +#ifdef CONFIG_NETFILTER_DEBUG
1595 + nskb->nf_debug = 0;
1598 + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
1600 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
1601 + tcph->source = xchg(&tcph->dest, tcph->source);
1603 + /* Truncate to length (no data) */
1604 + tcph->doff = sizeof(struct tcphdr)/4;
1605 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
1606 + nskb->nh.iph->tot_len = htons(nskb->len);
1610 + tcph->seq = otcph->ack_seq;
1611 + tcph->ack_seq = 0;
1614 + tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
1615 + + otcplen - (otcph->doff<<2));
1620 + ((u_int8_t *)tcph)[13] = 0;
1622 + tcph->ack = needs_ack;
1625 + tcph->urg_ptr = 0;
1627 + /* Adjust TCP checksum */
1629 + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
1630 + nskb->nh.iph->saddr,
1631 + nskb->nh.iph->daddr,
1632 + csum_partial((char *)tcph,
1633 + sizeof(struct tcphdr), 0));
1635 + /* Adjust IP TTL, DF */
1636 + nskb->nh.iph->ttl = MAXTTL;
1637 + /* Set DF, id = 0 */
1638 + nskb->nh.iph->frag_off = htons(IP_DF);
1639 + nskb->nh.iph->id = 0;
1641 + /* Adjust IP checksum */
1642 + nskb->nh.iph->check = 0;
1643 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
1644 + nskb->nh.iph->ihl);
1647 + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
1648 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
1652 + dst_release(nskb->dst);
1653 + nskb->dst = &rt->u.dst;
1655 + /* "Never happens" */
1656 + if (nskb->len > nskb->dst->pmtu)
1659 + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
1660 + ip_finish_output);
1668 +static unsigned int reject6_target(struct sk_buff **pskb,
1669 + unsigned int hooknum,
1670 + const struct net_device *in,
1671 + const struct net_device *out,
1672 + const void *targinfo,
1675 + const struct ip6t_reject_info *reject = targinfo;
1677 + /* WARNING: This code causes reentry within ip6tables.
1678 + This means that the ip6tables jump stack is now crap. We
1679 + must return an absolute verdict. --RR */
1680 + DEBUGP("REJECTv6: calling icmpv6_send\n");
1681 + switch (reject->with) {
1682 + case IP6T_ICMP6_NO_ROUTE:
1683 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
1685 + case IP6T_ICMP6_ADM_PROHIBITED:
1686 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
1688 + case IP6T_ICMP6_NOT_NEIGHBOUR:
1689 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
1691 + case IP6T_ICMP6_ADDR_UNREACH:
1692 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
1694 + case IP6T_ICMP6_PORT_UNREACH:
1695 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
1698 + case IPT_ICMP_ECHOREPLY: {
1699 + struct icmp6hdr *icmph = (struct icmphdr *)
1700 + ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
1701 + unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
1703 + /* Not non-head frags, or truncated */
1704 + if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
1705 + && datalen >= 4) {
1706 + /* Usually I don't like cut & pasting code,
1707 + but dammit, my party is starting in 45
1709 + struct icmp_bxm icmp_param;
1711 + icmp_param.icmph=*icmph;
1712 + icmp_param.icmph.type=ICMP_ECHOREPLY;
1713 + icmp_param.data_ptr=(icmph+1);
1714 + icmp_param.data_len=datalen;
1715 + icmp_reply(&icmp_param, *pskb);
1719 + case IPT_TCP_RESET:
1720 + send_reset(*pskb);
1724 + printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
1731 +static inline int find_ping_match(const struct ip6t_entry_match *m)
1733 + const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
1735 + if (strcmp(m->u.kernel.match->name, "icmp6") == 0
1736 + && icmpinfo->type == ICMPV6_ECHO_REQUEST
1737 + && !(icmpinfo->invflags & IP6T_ICMP_INV))
1743 +static int check(const char *tablename,
1744 + const struct ip6t_entry *e,
1746 + unsigned int targinfosize,
1747 + unsigned int hook_mask)
1749 + const struct ip6t_reject_info *rejinfo = targinfo;
1751 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
1752 + DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
1756 + /* Only allow these for packet filtering. */
1757 + if (strcmp(tablename, "filter") != 0) {
1758 + DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
1761 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
1762 + | (1 << NF_IP6_FORWARD)
1763 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
1764 + DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
1768 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
1769 + /* Must specify that it's an ICMP ping packet. */
1770 + if (e->ipv6.proto != IPPROTO_ICMPV6
1771 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
1772 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
1775 + /* Must contain ICMP match. */
1776 + if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
1777 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
1780 + } else if (rejinfo->with == IP6T_TCP_RESET) {
1781 + /* Must specify that it's a TCP packet */
1782 + if (e->ipv6.proto != IPPROTO_TCP
1783 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
1784 + DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
1792 +static struct ip6t_target ip6t_reject_reg
1793 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
1795 +static int __init init(void)
1797 + if (ip6t_register_target(&ip6t_reject_reg))
1802 +static void __exit fini(void)
1804 + ip6t_unregister_target(&ip6t_reject_reg);
1809 diff -Nur linux-2.6.2-rc2.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.2-rc2/net/ipv6/netfilter/ip6t_nth.c
1810 --- linux-2.6.2-rc2.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
1811 +++ linux-2.6.2-rc2/net/ipv6/netfilter/ip6t_nth.c 2004-01-30 12:26:19.000000000 +0100
1814 + This is a module which is used for match support for every Nth packet
1815 + This file is distributed under the terms of the GNU General Public
1816 + License (GPL). Copies of the GPL can be obtained from:
1817 + ftp://prep.ai.mit.edu/pub/gnu/GPL
1819 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
1820 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
1821 + * added support for multiple counters
1822 + * added support for matching on individual packets
1823 + in the counter cycle
1824 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
1828 +#include <linux/module.h>
1829 +#include <linux/skbuff.h>
1830 +#include <linux/ip.h>
1831 +#include <net/tcp.h>
1832 +#include <linux/spinlock.h>
1833 +#include <linux/netfilter_ipv6/ip6_tables.h>
1834 +#include <linux/netfilter_ipv6/ip6t_nth.h>
1836 +MODULE_LICENSE("GPL");
1839 + * State information.
1846 +static struct state states[IP6T_NTH_NUM_COUNTERS];
1849 +ip6t_nth_match(const struct sk_buff *pskb,
1850 + const struct net_device *in,
1851 + const struct net_device *out,
1852 + const void *matchinfo,
1855 + u_int16_t datalen,
1858 + /* Parameters from userspace */
1859 + const struct ip6t_nth_info *info = matchinfo;
1860 + unsigned counter = info->counter;
1861 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
1863 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
1867 + spin_lock(&states[counter].lock);
1869 + /* Are we matching every nth packet?*/
1870 + if (info->packet == 0xFF)
1872 + /* We're matching every nth packet and only every nth packet*/
1873 + /* Do we match or invert match? */
1874 + if (info->not == 0)
1876 + if (states[counter].number == 0)
1878 + ++states[counter].number;
1881 + if (states[counter].number >= info->every)
1882 + states[counter].number = 0; /* reset the counter */
1884 + ++states[counter].number;
1889 + if (states[counter].number == 0)
1891 + ++states[counter].number;
1894 + if (states[counter].number >= info->every)
1895 + states[counter].number = 0;
1897 + ++states[counter].number;
1903 + /* We're using the --packet, so there must be a rule for every value */
1904 + if (states[counter].number == info->packet)
1906 + /* only increment the counter when a match happens */
1907 + if (states[counter].number >= info->every)
1908 + states[counter].number = 0; /* reset the counter */
1910 + ++states[counter].number;
1919 + spin_unlock(&states[counter].lock);
1923 + spin_unlock(&states[counter].lock);
1928 +ip6t_nth_checkentry(const char *tablename,
1929 + const struct ip6t_ip6 *e,
1931 + unsigned int matchsize,
1932 + unsigned int hook_mask)
1934 + /* Parameters from userspace */
1935 + const struct ip6t_nth_info *info = matchinfo;
1936 + unsigned counter = info->counter;
1937 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
1939 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
1943 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
1944 + printk("nth: matchsize %u != %u\n", matchsize,
1945 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
1949 + states[counter].number = info->startat;
1954 +static struct ip6t_match ip6t_nth_reg = {
1958 + ip6t_nth_checkentry,
1962 +static int __init init(void)
1965 + memset(&states, 0, sizeof(states));
1966 + if (ip6t_register_match(&ip6t_nth_reg))
1969 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
1971 + spin_lock_init(&(states[counter].lock));
1974 + printk("ip6t_nth match loaded\n");
1978 +static void __exit fini(void)
1980 + ip6t_unregister_match(&ip6t_nth_reg);
1981 + printk("ip6t_nth match unloaded\n");