aboutsummaryrefslogtreecommitdiffstats
path: root/package/iptables/patches
diff options
context:
space:
mode:
Diffstat (limited to 'package/iptables/patches')
-rw-r--r--package/iptables/patches/01-ipp2p-0.8.1rc1.patch454
-rw-r--r--package/iptables/patches/02-layer7-1.5nbd.patch416
-rw-r--r--package/iptables/patches/04-multiport_v1.patch221
-rw-r--r--package/iptables/patches/05-imq1.patch224
4 files changed, 1315 insertions, 0 deletions
diff --git a/package/iptables/patches/01-ipp2p-0.8.1rc1.patch b/package/iptables/patches/01-ipp2p-0.8.1rc1.patch
new file mode 100644
index 0000000000..f7129b4560
--- /dev/null
+++ b/package/iptables/patches/01-ipp2p-0.8.1rc1.patch
@@ -0,0 +1,454 @@
+diff -urN iptables.old/extensions/Makefile iptables.dev/extensions/Makefile
+--- iptables.old/extensions/Makefile 2005-07-20 04:22:56.000000000 +0200
++++ iptables.dev/extensions/Makefile 2006-03-23 14:42:28.000000000 +0100
+@@ -8,6 +8,10 @@
+ PF_EXT_SLIB:=ah addrtype comment connlimit connmark conntrack dscp ecn esp hashlimit helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NFQUEUE NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
+ PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner physdev standard tcp udp HL LOG NFQUEUE MARK TRACE
+
++
++# ipp2p
++PF_EXT_SLIB += ipp2p
++
+ # Optionals
+ PF_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
+ PF6_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test6),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
+diff -urN iptables.old/extensions/libipt_ipp2p.c iptables.dev/extensions/libipt_ipp2p.c
+--- iptables.old/extensions/libipt_ipp2p.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_ipp2p.c 2006-03-23 14:43:26.000000000 +0100
+@@ -0,0 +1,401 @@
++
++#include <stdio.h>
++#include <netdb.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++#include <ctype.h>
++
++#include <iptables.h>
++
++#include <linux/netfilter_ipv4/ipt_ipp2p.h>
++
++static void
++help(void)
++{
++ printf(
++ "IPP2P v%s options:\n"
++ " --ipp2p Grab all known p2p packets\n"
++ " --edk [TCP&UDP] All known eDonkey/eMule/Overnet packets\n"
++ " --dc [TCP] All known Direct Connect packets\n"
++ " --kazaa [TCP&UDP] All known KaZaA packets\n"
++ " --gnu [TCP&UDP] All known Gnutella packets\n"
++ " --bit [TCP&UDP] All known BitTorrent packets\n"
++ " --apple [TCP] All known AppleJuice packets\n"
++ " --winmx [TCP] All known WinMX\n"
++ " --soul [TCP] All known SoulSeek\n"
++ " --ares [TCP] All known Ares\n\n"
++ " EXPERIMENTAL protocols (please send feedback to: ipp2p@ipp2p.org) :\n"
++ " --mute [TCP] All known Mute packets\n"
++ " --waste [TCP] All known Waste packets\n"
++ " --xdcc [TCP] All known XDCC packets (only xdcc login)\n\n"
++ " DEBUG SUPPPORT, use only if you know why\n"
++ " --debug Generate kernel debug output, THIS WILL SLOW DOWN THE FILTER\n"
++ "\nNote that the follwing options will have the same meaning:\n"
++ " '--ipp2p' is equal to '--edk --dc --kazaa --gnu --bit --apple --winmx --soul --ares'\n"
++ "\nIPP2P was intended for TCP only. Due to increasing usage of UDP we needed to change this.\n"
++ "You can now use -p udp to search UDP packets only or without -p switch to search UDP and TCP packets.\n"
++ "\nSee README included with this package for more details or visit http://www.ipp2p.org\n"
++ "\nExamples:\n"
++ " iptables -A FORWARD -m ipp2p --ipp2p -j MARK --set-mark 0x01\n"
++ " iptables -A FORWARD -p udp -m ipp2p --kazaa --bit -j DROP\n"
++ " iptables -A FORWARD -p tcp -m ipp2p --edk --soul -j DROP\n\n"
++ , IPP2P_VERSION);
++}
++
++static struct option opts[] = {
++ { "ipp2p", 0, 0, '1' },
++ { "edk", 0, 0, '2' },
++ { "dc", 0, 0, '7' },
++ { "gnu", 0, 0, '9' },
++ { "kazaa", 0, 0, 'a' },
++ { "bit", 0, 0, 'b' },
++ { "apple", 0, 0, 'c' },
++ { "soul", 0, 0, 'd' },
++ { "winmx", 0, 0, 'e' },
++ { "ares", 0, 0, 'f' },
++ { "mute", 0, 0, 'g' },
++ { "waste", 0, 0, 'h' },
++ { "xdcc", 0, 0, 'i' },
++ { "debug", 0, 0, 'j' },
++ {0}
++};
++
++
++
++static void
++init(struct ipt_entry_match *m, unsigned int *nfcache)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)m->data;
++
++ *nfcache |= NFC_UNKNOWN;
++
++ /*init the module with default values*/
++ info->cmd = 0;
++ info->debug = 0;
++
++}
++
++
++static int
++parse(int c, char **argv, int invert, unsigned int *flags,
++ const struct ipt_entry *entry,
++ unsigned int *nfcache,
++ struct ipt_entry_match **match)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)(*match)->data;
++
++ switch (c) {
++ case '1': /*cmd: ipp2p*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags) != 0)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += SHORT_HAND_IPP2P;
++ info->cmd = *flags;
++ break;
++
++ case '2': /*cmd: edk*/
++ if ((*flags & IPP2P_EDK) == IPP2P_EDK)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--edk' may only be "
++ "specified once");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_EDK) == IPP2P_DATA_EDK)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--edk' OR `--edk-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_EDK;
++ info->cmd = *flags;
++ break;
++
++
++ case '7': /*cmd: dc*/
++ if ((*flags & IPP2P_DC) == IPP2P_DC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--dc' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & IPP2P_DATA_DC) == IPP2P_DATA_DC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--dc' OR `--dc-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_DC;
++ info->cmd = *flags;
++ break;
++
++
++ case '9': /*cmd: gnu*/
++ if ((*flags & IPP2P_GNU) == IPP2P_GNU)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--gnu' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_GNU) == IPP2P_DATA_GNU)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--gnu' OR `--gnu-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_GNU;
++ info->cmd = *flags;
++ break;
++
++ case 'a': /*cmd: kazaa*/
++ if ((*flags & IPP2P_KAZAA) == IPP2P_KAZAA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--kazaa' may only be "
++ "specified once!");
++/* if ((*flags & SHORT_HAND_DATA) == SHORT_HAND_DATA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p-data' may only be "
++ "specified alone!");*/
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if ((*flags & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: use `--kazaa' OR `--kazaa-data' but not both of them!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_KAZAA;
++ info->cmd = *flags;
++ break;
++
++ case 'b': /*cmd: bit*/
++ if ((*flags & IPP2P_BIT) == IPP2P_BIT)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--bit' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_BIT;
++ info->cmd = *flags;
++ break;
++
++ case 'c': /*cmd: apple*/
++ if ((*flags & IPP2P_APPLE) == IPP2P_APPLE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--apple' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_APPLE;
++ info->cmd = *flags;
++ break;
++
++
++ case 'd': /*cmd: soul*/
++ if ((*flags & IPP2P_SOUL) == IPP2P_SOUL)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--soul' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_SOUL;
++ info->cmd = *flags;
++ break;
++
++
++ case 'e': /*cmd: winmx*/
++ if ((*flags & IPP2P_WINMX) == IPP2P_WINMX)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--winmx' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WINMX;
++ info->cmd = *flags;
++ break;
++
++ case 'f': /*cmd: ares*/
++ if ((*flags & IPP2P_ARES) == IPP2P_ARES)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if ((*flags & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ipp2p' may only be "
++ "specified alone!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_ARES;
++ info->cmd = *flags;
++ break;
++
++ case 'g': /*cmd: mute*/
++ if ((*flags & IPP2P_MUTE) == IPP2P_MUTE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--mute' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_MUTE;
++ info->cmd = *flags;
++ break;
++ case 'h': /*cmd: waste*/
++ if ((*flags & IPP2P_WASTE) == IPP2P_WASTE)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--waste' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_WASTE;
++ info->cmd = *flags;
++ break;
++ case 'i': /*cmd: xdcc*/
++ if ((*flags & IPP2P_XDCC) == IPP2P_XDCC)
++ exit_error(PARAMETER_PROBLEM,
++ "ipp2p: `--ares' may only be "
++ "specified once!");
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ *flags += IPP2P_XDCC;
++ info->cmd = *flags;
++ break;
++
++ case 'j': /*cmd: debug*/
++ if (invert) exit_error(PARAMETER_PROBLEM, "ipp2p: invert [!] is not allowed!");
++ info->debug = 1;
++ break;
++
++ default:
++// exit_error(PARAMETER_PROBLEM,
++// "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++ return 0;
++ }
++ return 1;
++}
++
++
++static void
++final_check(unsigned int flags)
++{
++ if (!flags)
++ exit_error(PARAMETER_PROBLEM,
++ "\nipp2p-parameter problem: for ipp2p usage type: iptables -m ipp2p --help\n");
++}
++
++
++
++static void
++print(const struct ipt_ip *ip,
++ const struct ipt_entry_match *match,
++ int numeric)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ printf("ipp2p v%s", IPP2P_VERSION);
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf(" --ipp2p");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf(" --ipp2p-data");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf(" --kazaa");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf(" --kazaa-data");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf(" --gnu-data");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf(" --gnu");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf(" --edk");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf(" --edk-data");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf(" --dc-data");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf(" --dc");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf(" --bit");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf(" --apple");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf(" --soul");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf(" --winmx");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf(" --ares");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf(" --debug");
++ printf(" ");
++}
++
++
++
++static void
++save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
++{
++ struct ipt_p2p_info *info = (struct ipt_p2p_info *)match->data;
++
++ if ((info->cmd & SHORT_HAND_IPP2P) == SHORT_HAND_IPP2P) printf("--ipp2p ");
++// if ((info->cmd & SHORT_HAND_DATA) == SHORT_HAND_DATA) printf("--ipp2p-data ");
++ if ((info->cmd & IPP2P_KAZAA) == IPP2P_KAZAA) printf("--kazaa ");
++// if ((info->cmd & IPP2P_DATA_KAZAA) == IPP2P_DATA_KAZAA) printf("--kazaa-data ");
++// if ((info->cmd & IPP2P_DATA_GNU) == IPP2P_DATA_GNU) printf("--gnu-data ");
++ if ((info->cmd & IPP2P_GNU) == IPP2P_GNU) printf("--gnu ");
++ if ((info->cmd & IPP2P_EDK) == IPP2P_EDK) printf("--edk ");
++// if ((info->cmd & IPP2P_DATA_EDK) == IPP2P_DATA_EDK) printf("--edk-data ");
++// if ((info->cmd & IPP2P_DATA_DC) == IPP2P_DATA_DC) printf("--dc-data ");
++ if ((info->cmd & IPP2P_DC) == IPP2P_DC) printf("--dc ");
++ if ((info->cmd & IPP2P_BIT) == IPP2P_BIT) printf("--bit ");
++ if ((info->cmd & IPP2P_APPLE) == IPP2P_APPLE) printf("--apple ");
++ if ((info->cmd & IPP2P_SOUL) == IPP2P_SOUL) printf("--soul ");
++ if ((info->cmd & IPP2P_WINMX) == IPP2P_WINMX) printf("--winmx ");
++ if ((info->cmd & IPP2P_ARES) == IPP2P_ARES) printf("--ares ");
++ if ((info->cmd & IPP2P_MUTE) == IPP2P_MUTE) printf(" --mute");
++ if ((info->cmd & IPP2P_WASTE) == IPP2P_WASTE) printf(" --waste");
++ if ((info->cmd & IPP2P_XDCC) == IPP2P_XDCC) printf(" --xdcc");
++ if (info->debug != 0) printf("--debug ");
++}
++
++
++
++
++static
++struct iptables_match ipp2p=
++{
++ .next = NULL,
++ .name = "ipp2p",
++ .version = IPTABLES_VERSION,
++ .size = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_p2p_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++
++
++void _init(void)
++{
++ register_match(&ipp2p);
++}
++
+diff -urN iptables.old/include/linux/netfilter_ipv4/ipt_ipp2p.h iptables.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h
+--- iptables.old/include/linux/netfilter_ipv4/ipt_ipp2p.h 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/include/linux/netfilter_ipv4/ipt_ipp2p.h 2006-03-23 14:44:26.000000000 +0100
+@@ -0,0 +1,31 @@
++#ifndef __IPT_IPP2P_H
++#define __IPT_IPP2P_H
++#define IPP2P_VERSION "0.8.1_rc1"
++
++struct ipt_p2p_info {
++ int cmd;
++ int debug;
++};
++
++#endif //__IPT_IPP2P_H
++
++#define SHORT_HAND_IPP2P 1 /* --ipp2p switch*/
++//#define SHORT_HAND_DATA 4 /* --ipp2p-data switch*/
++#define SHORT_HAND_NONE 5 /* no short hand*/
++
++#define IPP2P_EDK (1 << 1)
++#define IPP2P_DATA_KAZAA (1 << 2)
++#define IPP2P_DATA_EDK (1 << 3)
++#define IPP2P_DATA_DC (1 << 4)
++#define IPP2P_DC (1 << 5)
++#define IPP2P_DATA_GNU (1 << 6)
++#define IPP2P_GNU (1 << 7)
++#define IPP2P_KAZAA (1 << 8)
++#define IPP2P_BIT (1 << 9)
++#define IPP2P_APPLE (1 << 10)
++#define IPP2P_SOUL (1 << 11)
++#define IPP2P_WINMX (1 << 12)
++#define IPP2P_ARES (1 << 13)
++#define IPP2P_MUTE (1 << 14)
++#define IPP2P_WASTE (1 << 15)
++#define IPP2P_XDCC (1 << 16)
diff --git a/package/iptables/patches/02-layer7-1.5nbd.patch b/package/iptables/patches/02-layer7-1.5nbd.patch
new file mode 100644
index 0000000000..95c62a860a
--- /dev/null
+++ b/package/iptables/patches/02-layer7-1.5nbd.patch
@@ -0,0 +1,416 @@
+diff -urN iptables.old/extensions/.layer7-test iptables.dev/extensions/.layer7-test
+--- iptables.old/extensions/.layer7-test 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/.layer7-test 2005-11-10 16:57:51.819381000 +0100
+@@ -0,0 +1,2 @@
++#! /bin/sh
++[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_layer7.h ] && echo layer7
+diff -urN iptables.old/extensions/ipt_layer7.h iptables.dev/extensions/ipt_layer7.h
+--- iptables.old/extensions/ipt_layer7.h 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/ipt_layer7.h 2005-11-10 17:46:32.933599750 +0100
+@@ -0,0 +1,27 @@
++/*
++ By Matthew Strait <quadong@users.sf.net>, Dec 2003.
++ http://l7-filter.sf.net
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License
++ as published by the Free Software Foundation; either version
++ 2 of the License, or (at your option) any later version.
++ http://www.gnu.org/licenses/gpl.txt
++*/
++
++#ifndef _IPT_LAYER7_H
++#define _IPT_LAYER7_H
++
++#define MAX_PATTERN_LEN 8192
++#define MAX_PROTOCOL_LEN 256
++
++typedef char *(*proc_ipt_search) (char *, char, char *);
++
++struct ipt_layer7_info {
++ char protocol[MAX_PROTOCOL_LEN];
++ char invert:1;
++ char pattern[MAX_PATTERN_LEN];
++ char pkt;
++};
++
++#endif /* _IPT_LAYER7_H */
+diff -urN iptables.old/extensions/libipt_layer7.c iptables.dev/extensions/libipt_layer7.c
+--- iptables.old/extensions/libipt_layer7.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_layer7.c 2005-11-10 17:47:01.399378750 +0100
+@@ -0,0 +1,358 @@
++/*
++ Shared library add-on to iptables to add layer 7 matching support.
++
++ By Matthew Strait <quadong@users.sf.net>, Oct 2003.
++
++ http://l7-filter.sf.net
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License
++ as published by the Free Software Foundation; either version
++ 2 of the License, or (at your option) any later version.
++ http://www.gnu.org/licenses/gpl.txt
++
++ Based on libipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>
++*/
++
++#define _GNU_SOURCE
++#include <stdio.h>
++#include <netdb.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++#include <ctype.h>
++#include <dirent.h>
++
++#include <iptables.h>
++#include "ipt_layer7.h"
++
++#define MAX_FN_LEN 256
++
++static char l7dir[MAX_FN_LEN] = "\0";
++
++/* Function which prints out usage message. */
++static void help(void)
++{
++ printf(
++ "LAYER7 match v%s options:\n"
++ "--l7dir <directory> : Look for patterns here instead of /etc/l7-protocols/\n"
++ " (--l7dir must be specified before --l7proto if used!)\n"
++ "--l7proto [!] <name> : Match the protocol defined in /etc/l7-protocols/name.pat\n"
++ "--l7pkt : Skip connection tracking and match individual packets\n",
++ IPTABLES_VERSION);
++ fputc('\n', stdout);
++}
++
++static struct option opts[] = {
++ { .name = "l7proto", .has_arg = 1, .flag = 0, .val = '1' },
++ { .name = "l7dir", .has_arg = 1, .flag = 0, .val = '2' },
++ { .name = "l7pkt", .has_arg = 0, .flag = 0, .val = '3' },
++ { .name = 0 }
++};
++
++/* reads filename, puts protocol info into layer7_protocol_info, number of protocols to numprotos */
++int parse_protocol_file(char * filename, const unsigned char * protoname, struct ipt_layer7_info *info)
++{
++ FILE * f;
++ char * line = NULL;
++ size_t len = 0;
++
++ enum { protocol, pattern, done } datatype = protocol;
++
++ f = fopen(filename, "r");
++
++ if(!f)
++ return 0;
++
++ while(getline(&line, &len, f) != -1)
++ {
++ if(strlen(line) < 2 || line[0] == '#')
++ continue;
++
++ /* strip the pesky newline... */
++ if(line[strlen(line) - 1] == '\n')
++ line[strlen(line) - 1] = '\0';
++
++ if(datatype == protocol)
++ {
++ if(strcmp(line, protoname))
++ exit_error(OTHER_PROBLEM,
++ "Protocol name (%s) doesn't match file name (%s). Bailing out\n",
++ protoname, filename);
++
++ if(strlen(line) >= MAX_PROTOCOL_LEN)
++ exit_error(PARAMETER_PROBLEM,
++ "Protocol name in %s too long!", filename);
++ strncpy(info->protocol, line, MAX_PROTOCOL_LEN);
++
++ datatype = pattern;
++ }
++ else if(datatype == pattern)
++ {
++ if(strlen(line) >= MAX_PATTERN_LEN)
++ exit_error(PARAMETER_PROBLEM, "Pattern in %s too long!", filename);
++ strncpy(info->pattern, line, MAX_PATTERN_LEN);
++
++ datatype = done;
++ break;
++ }
++ else
++ exit_error(OTHER_PROBLEM, "Internal error");
++ }
++
++ if(datatype != done)
++ exit_error(OTHER_PROBLEM, "Failed to get all needed data from %s", filename);
++
++ if(line) free(line);
++ fclose(f);
++
++ return 1;
++
++/*
++ fprintf(stderr, "protocol: %s\npattern: %s\n\n",
++ info->protocol,
++ info->pattern);
++*/
++}
++
++static int hex2dec(char c)
++{
++ switch (c)
++ {
++ case '0' ... '9':
++ return c - '0';
++ case 'a' ... 'f':
++ return c - 'a' + 10;
++ case 'A' ... 'F':
++ return c - 'A' + 10;
++ default:
++ exit_error(OTHER_PROBLEM, "hex2dec: bad value!\n");
++ return 0;
++ }
++}
++
++/* takes a string with \xHH escapes and returns one with the characters
++they stand for */
++static char * pre_process(char * s)
++{
++ char * result = malloc(strlen(s) + 1);
++ int sindex = 0, rindex = 0;
++ while( sindex < strlen(s) )
++ {
++ if( sindex + 3 < strlen(s) &&
++ s[sindex] == '\\' && s[sindex+1] == 'x' &&
++ isxdigit(s[sindex + 2]) && isxdigit(s[sindex + 3]) )
++ {
++ /* carefully remember to call tolower here... */
++ result[rindex] = tolower( hex2dec(s[sindex + 2])*16 +
++ hex2dec(s[sindex + 3] ) );
++ sindex += 3; /* 4 total */
++ }
++ else
++ result[rindex] = tolower(s[sindex]);
++
++ sindex++;
++ rindex++;
++ }
++ result[rindex] = '\0';
++
++ return result;
++}
++
++#define MAX_SUBDIRS 128
++char ** readl7dir(char * dirname)
++{
++ DIR * scratchdir;
++ struct dirent ** namelist;
++ char ** subdirs = malloc(MAX_SUBDIRS * sizeof(char *));
++
++ int n, d = 1;
++ subdirs[0] = "";
++
++ n = scandir(dirname, &namelist, 0, alphasort);
++
++ if (n < 0)
++ {
++ perror("scandir");
++ exit_error(OTHER_PROBLEM, "Couldn't open %s\n", dirname);
++ }
++ else
++ {
++ while(n--)
++ {
++ char fulldirname[MAX_FN_LEN];
++
++ snprintf(fulldirname, MAX_FN_LEN, "%s/%s", dirname, namelist[n]->d_name);
++
++ if((scratchdir = opendir(fulldirname)) != NULL)
++ {
++ closedir(scratchdir);
++
++ if(!strcmp(namelist[n]->d_name, ".") ||
++ !strcmp(namelist[n]->d_name, ".."))
++ /* do nothing */ ;
++ else
++ {
++ subdirs[d] = malloc(strlen(namelist[n]->d_name) + 1);
++ strcpy(subdirs[d], namelist[n]->d_name);
++ d++;
++ if(d >= MAX_SUBDIRS - 1)
++ {
++ fprintf(stderr,
++ "Too many subdirectories, skipping the rest!\n");
++ break;
++ }
++ }
++ }
++ free(namelist[n]);
++ }
++ free(namelist);
++ }
++
++ subdirs[d] = NULL;
++
++ return subdirs;
++}
++
++static void
++parse_layer7_protocol(const unsigned char *s, struct ipt_layer7_info *info)
++{
++ char filename[MAX_FN_LEN];
++ char * dir = NULL;
++ char ** subdirs;
++ int n = 0, done = 0;
++
++ if(strlen(l7dir) > 0)
++ dir = l7dir;
++ else
++ dir = "/etc/l7-protocols";
++
++ subdirs = readl7dir(dir);
++
++ while(subdirs[n] != NULL)
++ {
++ int c = snprintf(filename, MAX_FN_LEN, "%s/%s/%s.pat", dir, subdirs[n], s);
++
++ //fprintf(stderr, "Trying to find pattern in %s ... ", filename);
++
++ if(c > MAX_FN_LEN)
++ {
++ exit_error(OTHER_PROBLEM,
++ "Filename beginning with %s is too long!\n", filename);
++ }
++
++ /* read in the pattern from the file */
++ if(parse_protocol_file(filename, s, info))
++ {
++ //fprintf(stderr, "found\n");
++ done = 1;
++ break;
++ }
++
++ //fprintf(stderr, "not found\n");
++
++ n++;
++ }
++
++ if(!done)
++ exit_error(OTHER_PROBLEM,
++ "Couldn't find a pattern definition file for %s.\n", s);
++
++ /* process \xHH escapes and tolower everything. (our regex lib has no
++ case insensitivity option.) */
++ strncpy(info->pattern, pre_process(info->pattern), MAX_PATTERN_LEN);
++}
++
++/* Function which parses command options; returns true if it ate an option */
++static int parse(int c, char **argv, int invert, unsigned int *flags,
++ const struct ipt_entry *entry, unsigned int *nfcache,
++ struct ipt_entry_match **match)
++{
++ struct ipt_layer7_info *layer7info =
++ (struct ipt_layer7_info *)(*match)->data;
++
++ switch (c) {
++ case '1':
++ check_inverse(optarg, &invert, &optind, 0);
++ parse_layer7_protocol(argv[optind-1], layer7info);
++ if (invert)
++ layer7info->invert = 1;
++ *flags = 1;
++ break;
++
++ case '2':
++ /* not going to use this, but maybe we need to strip a ! anyway (?) */
++ check_inverse(optarg, &invert, &optind, 0);
++
++ if(strlen(argv[optind-1]) >= MAX_FN_LEN)
++ exit_error(PARAMETER_PROBLEM, "directory name too long\n");
++
++ strncpy(l7dir, argv[optind-1], MAX_FN_LEN);
++
++ *flags = 1;
++ break;
++ case '3':
++ layer7info->pkt = 1;
++ break;
++
++ default:
++ return 0;
++ }
++
++ return 1;
++}
++
++/* Final check; must have specified --pattern. */
++static void final_check(unsigned int flags)
++{
++ if (!flags)
++ exit_error(PARAMETER_PROBLEM,
++ "LAYER7 match: You must specify `--pattern'");
++}
++
++static void print_protocol(char s[], int invert, int numeric)
++{
++ fputs("l7proto ", stdout);
++ if (invert) fputc('!', stdout);
++ printf("%s ", s);
++}
++
++/* Prints out the matchinfo. */
++static void print(const struct ipt_ip *ip,
++ const struct ipt_entry_match *match,
++ int numeric)
++{
++ printf("LAYER7 ");
++
++ print_protocol(((struct ipt_layer7_info *)match->data)->protocol,
++ ((struct ipt_layer7_info *)match->data)->invert, numeric);
++
++ if (((struct ipt_layer7_info *)match->data)->pkt)
++ printf("l7pkt ");
++}
++/* Saves the union ipt_matchinfo in parsable form to stdout. */
++static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
++{
++ const struct ipt_layer7_info *info =
++ (const struct ipt_layer7_info*) match->data;
++
++ printf("--l7proto %s%s ", (info->invert) ? "! ": "", info->protocol);
++}
++
++static struct iptables_match layer7 = {
++ .name = "layer7",
++ .version = IPTABLES_VERSION,
++ .size = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_layer7_info)),
++ .help = &help,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++void _init(void)
++{
++ register_match(&layer7);
++}
+diff -urN iptables.old/extensions/libipt_layer7.man iptables.dev/extensions/libipt_layer7.man
+--- iptables.old/extensions/libipt_layer7.man 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_layer7.man 2005-11-10 16:57:51.823381250 +0100
+@@ -0,0 +1,13 @@
++This module matches packets based on the application layer data of
++their connections. It uses regular expression matching to compare
++the application layer data to regular expressions found it the layer7
++configuration files. This is an experimental module which can be found at
++http://l7-filter.sf.net. It takes two options.
++.TP
++.BI "--l7proto " "\fIprotocol\fP"
++Match the specified protocol. The protocol name must match a file
++name in /etc/l7-protocols/
++.TP
++.BI "--l7dir " "\fIdirectory\fP"
++Use \fIdirectory\fP instead of /etc/l7-protocols/
++
diff --git a/package/iptables/patches/04-multiport_v1.patch b/package/iptables/patches/04-multiport_v1.patch
new file mode 100644
index 0000000000..90b5144c75
--- /dev/null
+++ b/package/iptables/patches/04-multiport_v1.patch
@@ -0,0 +1,221 @@
+diff -urN iptables.old/extensions/libipt_multiport.c iptables.dev/extensions/libipt_multiport.c
+--- iptables.old/extensions/libipt_multiport.c 2005-02-19 20:19:17.000000000 +0100
++++ iptables.dev/extensions/libipt_multiport.c 2006-02-04 05:46:12.154127750 +0100
+@@ -8,24 +8,6 @@
+ /* To ensure that iptables compiles with an old kernel */
+ #include "../include/linux/netfilter_ipv4/ipt_multiport.h"
+
+-/* Function which prints out usage message. */
+-static void
+-help(void)
+-{
+- printf(
+-"multiport v%s options:\n"
+-" --source-ports port[,port,port...]\n"
+-" --sports ...\n"
+-" match source port(s)\n"
+-" --destination-ports port[,port,port...]\n"
+-" --dports ...\n"
+-" match destination port(s)\n"
+-" --ports port[,port,port]\n"
+-" match both source and destination port(s)\n"
+-" NOTE: this kernel does not support port ranges in multiport.\n",
+-IPTABLES_VERSION);
+-}
+-
+ static void
+ help_v1(void)
+ {
+@@ -75,26 +57,6 @@
+ "invalid port/service `%s' specified", port);
+ }
+
+-static unsigned int
+-parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
+-{
+- char *buffer, *cp, *next;
+- unsigned int i;
+-
+- buffer = strdup(portstring);
+- if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
+-
+- for (cp=buffer, i=0; cp && i<IPT_MULTI_PORTS; cp=next,i++)
+- {
+- next=strchr(cp, ',');
+- if (next) *next++='\0';
+- ports[i] = parse_port(cp, proto);
+- }
+- if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
+- free(buffer);
+- return i;
+-}
+-
+ static void
+ parse_multi_ports_v1(const char *portstring,
+ struct ipt_multiport_v1 *multiinfo,
+@@ -160,58 +122,6 @@
+ "multiport only works with TCP or UDP");
+ }
+
+-/* Function which parses command options; returns true if it
+- ate an option */
+-static int
+-parse(int c, char **argv, int invert, unsigned int *flags,
+- const struct ipt_entry *entry,
+- unsigned int *nfcache,
+- struct ipt_entry_match **match)
+-{
+- const char *proto;
+- struct ipt_multiport *multiinfo
+- = (struct ipt_multiport *)(*match)->data;
+-
+- switch (c) {
+- case '1':
+- check_inverse(argv[optind-1], &invert, &optind, 0);
+- proto = check_proto(entry);
+- multiinfo->count = parse_multi_ports(argv[optind-1],
+- multiinfo->ports, proto);
+- multiinfo->flags = IPT_MULTIPORT_SOURCE;
+- break;
+-
+- case '2':
+- check_inverse(argv[optind-1], &invert, &optind, 0);
+- proto = check_proto(entry);
+- multiinfo->count = parse_multi_ports(argv[optind-1],
+- multiinfo->ports, proto);
+- multiinfo->flags = IPT_MULTIPORT_DESTINATION;
+- break;
+-
+- case '3':
+- check_inverse(argv[optind-1], &invert, &optind, 0);
+- proto = check_proto(entry);
+- multiinfo->count = parse_multi_ports(argv[optind-1],
+- multiinfo->ports, proto);
+- multiinfo->flags = IPT_MULTIPORT_EITHER;
+- break;
+-
+- default:
+- return 0;
+- }
+-
+- if (invert)
+- exit_error(PARAMETER_PROBLEM,
+- "multiport does not support invert");
+-
+- if (*flags)
+- exit_error(PARAMETER_PROBLEM,
+- "multiport can only have one option");
+- *flags = 1;
+- return 1;
+-}
+-
+ static int
+ parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ const struct ipt_entry *entry,
+@@ -289,43 +199,6 @@
+ printf("%s", service);
+ }
+
+-/* Prints out the matchinfo. */
+-static void
+-print(const struct ipt_ip *ip,
+- const struct ipt_entry_match *match,
+- int numeric)
+-{
+- const struct ipt_multiport *multiinfo
+- = (const struct ipt_multiport *)match->data;
+- unsigned int i;
+-
+- printf("multiport ");
+-
+- switch (multiinfo->flags) {
+- case IPT_MULTIPORT_SOURCE:
+- printf("sports ");
+- break;
+-
+- case IPT_MULTIPORT_DESTINATION:
+- printf("dports ");
+- break;
+-
+- case IPT_MULTIPORT_EITHER:
+- printf("ports ");
+- break;
+-
+- default:
+- printf("ERROR ");
+- break;
+- }
+-
+- for (i=0; i < multiinfo->count; i++) {
+- printf("%s", i ? "," : "");
+- print_port(multiinfo->ports[i], ip->proto, numeric);
+- }
+- printf(" ");
+-}
+-
+ static void
+ print_v1(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match,
+@@ -369,34 +242,6 @@
+ printf(" ");
+ }
+
+-/* Saves the union ipt_matchinfo in parsable form to stdout. */
+-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+-{
+- const struct ipt_multiport *multiinfo
+- = (const struct ipt_multiport *)match->data;
+- unsigned int i;
+-
+- switch (multiinfo->flags) {
+- case IPT_MULTIPORT_SOURCE:
+- printf("--sports ");
+- break;
+-
+- case IPT_MULTIPORT_DESTINATION:
+- printf("--dports ");
+- break;
+-
+- case IPT_MULTIPORT_EITHER:
+- printf("--ports ");
+- break;
+- }
+-
+- for (i=0; i < multiinfo->count; i++) {
+- printf("%s", i ? "," : "");
+- print_port(multiinfo->ports[i], ip->proto, 1);
+- }
+- printf(" ");
+-}
+-
+ static void save_v1(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match)
+ {
+@@ -432,19 +277,20 @@
+ printf(" ");
+ }
+
++
+ static struct iptables_match multiport = {
+ .next = NULL,
+ .name = "multiport",
+- .revision = 0,
+ .version = IPTABLES_VERSION,
+- .size = IPT_ALIGN(sizeof(struct ipt_multiport)),
+- .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport)),
+- .help = &help,
++ .revision = 0,
++ .size = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
++ .help = &help_v1,
+ .init = &init,
+- .parse = &parse,
++ .parse = &parse_v1,
+ .final_check = &final_check,
+- .print = &print,
+- .save = &save,
++ .print = &print_v1,
++ .save = &save_v1,
+ .extra_opts = opts
+ };
+
diff --git a/package/iptables/patches/05-imq1.patch b/package/iptables/patches/05-imq1.patch
new file mode 100644
index 0000000000..4591890304
--- /dev/null
+++ b/package/iptables/patches/05-imq1.patch
@@ -0,0 +1,224 @@
+diff -urN iptables.old/extensions/.IMQ-test iptables.dev/extensions/.IMQ-test
+--- iptables.old/extensions/.IMQ-test 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/.IMQ-test 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,3 @@
++#!/bin/sh
++# True if IMQ target patch is applied.
++[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_IMQ.c ] && echo IMQ
+diff -urN iptables.old/extensions/.IMQ-test6 iptables.dev/extensions/.IMQ-test6
+--- iptables.old/extensions/.IMQ-test6 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/.IMQ-test6 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,3 @@
++#!/bin/sh
++# True if IMQ target patch is applied.
++[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_IMQ.c ] && echo IMQ
+diff -urN iptables.old/extensions/libip6t_IMQ.c iptables.dev/extensions/libip6t_IMQ.c
+--- iptables.old/extensions/libip6t_IMQ.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libip6t_IMQ.c 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,101 @@
++/* Shared library add-on to iptables to add IMQ target support. */
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++
++#include <ip6tables.h>
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_IMQ.h>
++
++/* Function which prints out usage message. */
++static void
++help(void)
++{
++ printf(
++"IMQ target v%s options:\n"
++" --todev <N> enqueue to imq<N>, defaults to 0\n",
++IPTABLES_VERSION);
++}
++
++static struct option opts[] = {
++ { "todev", 1, 0, '1' },
++ { 0 }
++};
++
++/* Initialize the target. */
++static void
++init(struct ip6t_entry_target *t, unsigned int *nfcache)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)t->data;
++
++ mr->todev = 0;
++ *nfcache |= NFC_UNKNOWN;
++}
++
++/* Function which parses command options; returns true if it
++ ate an option */
++static int
++parse(int c, char **argv, int invert, unsigned int *flags,
++ const struct ip6t_entry *entry,
++ struct ip6t_entry_target **target)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)(*target)->data;
++
++ switch(c) {
++ case '1':
++ if (check_inverse(optarg, &invert, NULL, 0))
++ exit_error(PARAMETER_PROBLEM,
++ "Unexpected `!' after --todev");
++ mr->todev=atoi(optarg);
++ break;
++ default:
++ return 0;
++ }
++ return 1;
++}
++
++static void
++final_check(unsigned int flags)
++{
++}
++
++/* Prints out the targinfo. */
++static void
++print(const struct ip6t_ip6 *ip,
++ const struct ip6t_entry_target *target,
++ int numeric)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)target->data;
++
++ printf("IMQ: todev %u ", mr->todev);
++}
++
++/* Saves the union ipt_targinfo in parsable form to stdout. */
++static void
++save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
++{
++ struct ip6t_imq_info *mr = (struct ip6t_imq_info*)target->data;
++
++ printf("--todev %u", mr->todev);
++}
++
++static struct ip6tables_target imq = {
++ .next = NULL,
++ .name = "IMQ",
++ .version = IPTABLES_VERSION,
++ .size = IP6T_ALIGN(sizeof(struct ip6t_imq_info)),
++ .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_imq_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++void _init(void)
++{
++ register_target6(&imq);
++}
+diff -urN iptables.old/extensions/libipt_IMQ.c iptables.dev/extensions/libipt_IMQ.c
+--- iptables.old/extensions/libipt_IMQ.c 1970-01-01 01:00:00.000000000 +0100
++++ iptables.dev/extensions/libipt_IMQ.c 2005-10-09 01:00:36.358959750 +0200
+@@ -0,0 +1,101 @@
++/* Shared library add-on to iptables to add IMQ target support. */
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <getopt.h>
++
++#include <iptables.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++#include <linux/netfilter_ipv4/ipt_IMQ.h>
++
++/* Function which prints out usage message. */
++static void
++help(void)
++{
++ printf(
++"IMQ target v%s options:\n"
++" --todev <N> enqueue to imq<N>, defaults to 0\n",
++IPTABLES_VERSION);
++}
++
++static struct option opts[] = {
++ { "todev", 1, 0, '1' },
++ { 0 }
++};
++
++/* Initialize the target. */
++static void
++init(struct ipt_entry_target *t, unsigned int *nfcache)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)t->data;
++
++ mr->todev = 0;
++ *nfcache |= NFC_UNKNOWN;
++}
++
++/* Function which parses command options; returns true if it
++ ate an option */
++static int
++parse(int c, char **argv, int invert, unsigned int *flags,
++ const struct ipt_entry *entry,
++ struct ipt_entry_target **target)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)(*target)->data;
++
++ switch(c) {
++ case '1':
++ if (check_inverse(optarg, &invert, NULL, 0))
++ exit_error(PARAMETER_PROBLEM,
++ "Unexpected `!' after --todev");
++ mr->todev=atoi(optarg);
++ break;
++ default:
++ return 0;
++ }
++ return 1;
++}
++
++static void
++final_check(unsigned int flags)
++{
++}
++
++/* Prints out the targinfo. */
++static void
++print(const struct ipt_ip *ip,
++ const struct ipt_entry_target *target,
++ int numeric)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)target->data;
++
++ printf("IMQ: todev %u ", mr->todev);
++}
++
++/* Saves the union ipt_targinfo in parsable form to stdout. */
++static void
++save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
++{
++ struct ipt_imq_info *mr = (struct ipt_imq_info*)target->data;
++
++ printf("--todev %u", mr->todev);
++}
++
++static struct iptables_target imq = {
++ .next = NULL,
++ .name = "IMQ",
++ .version = IPTABLES_VERSION,
++ .size = IPT_ALIGN(sizeof(struct ipt_imq_info)),
++ .userspacesize = IPT_ALIGN(sizeof(struct ipt_imq_info)),
++ .help = &help,
++ .init = &init,
++ .parse = &parse,
++ .final_check = &final_check,
++ .print = &print,
++ .save = &save,
++ .extra_opts = opts
++};
++
++void _init(void)
++{
++ register_target(&imq);
++}