> - Please decouple the 'childlevel' match and submit it seperately. We
> could even submit it to the kernel soon.
Here you go.
(This module adds support for matching on the "childlevel" of a
connection. Most connections have childlevel 0. Child connections such
as FTP data or IRC-DCC have childlevel 1. Children of children have
childlevel 2, and so on. iptables usage: "-m childlevel --level [!] n")
-matthew
diff -Naur iptables-1.2.9-stock/extensions/.childlevel-test iptables-1.2.9-childlevel/extensions/.childlevel-test
--- iptables-1.2.9-stock/extensions/.childlevel-test 1969-12-31 18:00:00.000000000 -0600
+++ iptables-1.2.9-childlevel/extensions/.childlevel-test 2004-02-16 10:47:17.279087176 -0600
@@ -0,0 +1,2 @@
+#! /bin/sh
+[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_childlevel.h ] && echo childlevel
diff -Naur iptables-1.2.9-stock/extensions/libipt_childlevel.c iptables-1.2.9-childlevel/extensions/libipt_childlevel.c
--- iptables-1.2.9-stock/extensions/libipt_childlevel.c 1969-12-31 18:00:00.000000000 -0600
+++ iptables-1.2.9-childlevel/extensions/libipt_childlevel.c 2004-02-16 11:12:47.613535776 -0600
@@ -0,0 +1,122 @@
+/*
+ Shared library add-on to iptables to add layer 7 matching support.
+
+ http://l7-filter.sf.net
+
+ By Matthew Strait <quadong@xxxxxxxxxxxx>, Dec 2003.
+
+ 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
+*/
+
+#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 <linux/netfilter_ipv4/ipt_childlevel.h>
+
+/* Function which prints out usage message. */
+static void help(void)
+{
+ printf(
+ "CHILDLEVEL match v%s options:\n"
+ "--level <n> : Match childlevel n (0 == master)\n",
+ IPTABLES_VERSION);
+ fputc('\n', stdout);
+}
+
+static struct option opts[] = {
+ { .name = "level", .has_arg = 1, .flag = 0, .val = '1' },
+ { .name = 0 }
+};
+
+/* Initialize the match. */
+static void init(struct ipt_entry_match *m, unsigned int *nfcache)
+{
+ *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, unsigned int *nfcache,
+ struct ipt_entry_match **match)
+{
+ struct ipt_childlevel_info *childlevelinfo =
+ (struct ipt_childlevel_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ check_inverse(optarg, &invert, &optind, 0);
+ childlevelinfo->childlevel = atoi(argv[optind-1]);
+ if (invert)
+ childlevelinfo->invert = 1;
+ *flags = 1;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Final check; must have specified --level. */
+static void final_check(unsigned int flags)
+{
+ if (!flags)
+ exit_error(PARAMETER_PROBLEM,
+ "CHILDLEVEL match: You must specify `--level'");
+}
+
+static void print_protocol(int n, int invert, int numeric)
+{
+ fputs("childlevel ", stdout);
+ if (invert) fputc('!', stdout);
+ printf("%d ", n);
+}
+
+/* Prints out the matchinfo. */
+static void print(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match,
+ int numeric)
+{
+ printf("CHILDLEVEL ");
+
+ print_protocol(((struct ipt_childlevel_info *)match->data)->childlevel,
+ ((struct ipt_childlevel_info *)match->data)->invert, numeric);
+}
+/* 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_childlevel_info *info =
+ (const struct ipt_childlevel_info*) match->data;
+
+ printf("--childlevel %s%d ", (info->invert) ? "! ": "", info->childlevel);
+}
+
+static struct iptables_match childlevel = {
+ .name = "childlevel",
+ .version = IPTABLES_VERSION,
+ .size = IPT_ALIGN(sizeof(struct ipt_childlevel_info)),
+ .userspacesize = IPT_ALIGN(sizeof(struct ipt_childlevel_info)),
+ .help = &help,
+ .init = &init,
+ .parse = &parse,
+ .final_check = &final_check,
+ .print = &print,
+ .save = &save,
+ .extra_opts = opts
+};
+
+void _init(void)
+{
+ register_match(&childlevel);
+}
diff -Naur iptables-1.2.9-stock/iptables.8 iptables-1.2.9-childlevel/iptables.8
--- iptables-1.2.9-stock/iptables.8 2003-06-30 11:16:54.000000000 -0500
+++ iptables-1.2.9-childlevel/iptables.8 2004-02-16 10:48:20.874419216 -0600
@@ -382,6 +382,13 @@
This module matches the SPIs in AH header of IPSec packets.
.TP
.BR "--ahspi " "[!] \fIspi\fP[:\fIspi\fP]"
+.SS childlevel
+This is an experimental module. It matches on whether the
+packet is part of a master connection
+or one of its children (or grandchildren, etc). For instance, most
+packets are level 0. FTP data transfer is level 1.
+.TP
+.BR "--childlevel " "[!] \fIlevel\fP"
.SS conntrack
This module, when combined with connection tracking, allows access to
more connection tracking information than the "state" match.
diff -Naur linux-2.6.2-stock/include/linux/netfilter_ipv4/ipt_childlevel.h linux-2.6.2-childlevel/include/linux/netfilter_ipv4/ipt_childlevel.h
--- linux-2.6.2-stock/include/linux/netfilter_ipv4/ipt_childlevel.h 1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.2-childlevel/include/linux/netfilter_ipv4/ipt_childlevel.h 2004-02-16 10:09:34.000000000 -0600
@@ -0,0 +1,22 @@
+/*
+ By Matthew Strait <quadong@xxxxxxxxxxxx>, 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_CHILDLEVEL_H
+#define _IPT_CHILDLEVEL_H
+
+typedef char *(*proc_ipt_search) (u_int32_t, u_int8_t);
+
+struct ipt_childlevel_info {
+ u_int32_t childlevel;
+ u_int8_t invert;
+};
+
+#endif /* _IPT_CHILDLEVEL_H */
diff -Naur linux-2.6.2-stock/net/ipv4/netfilter/Kconfig linux-2.6.2-childlevel/net/ipv4/netfilter/Kconfig
--- linux-2.6.2-stock/net/ipv4/netfilter/Kconfig 2004-02-15 19:52:12.000000000 -0600
+++ linux-2.6.2-childlevel/net/ipv4/netfilter/Kconfig 2004-02-15 20:05:59.000000000 -0600
@@ -115,6 +115,21 @@
To compile it as a module, choose M here. If unsure, say N.
+config IP_NF_MATCH_CHILDLEVEL
+ tristate "Child Level match support (EXPERIMENTAL)"
+ depends on IP_NF_IPTABLES && IP_NF_CONNTRACK && EXPERIMENTAL
+ help
+ Say Y if you want to be able to classify packets based on whether
+ they belong to a master connection or a child connection. Examples
+ of child connections are the data stream of FTP and IRC-DCC.
+
+ In iptables, "-m childlevel --level 0" will match master connections.
+ '-m childlevel --level 1" will match first generation children of
+ masters. As of iptables 1.2.9, this requires a patch to iptables to
+ work.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config IP_NF_MATCH_PKTTYPE
tristate "Packet type match support"
depends on IP_NF_IPTABLES
diff -Naur linux-2.6.2-stock/net/ipv4/netfilter/Makefile linux-2.6.2-childlevel/net/ipv4/netfilter/Makefile
--- linux-2.6.2-stock/net/ipv4/netfilter/Makefile 2004-02-15 19:52:12.000000000 -0600
+++ linux-2.6.2-childlevel/net/ipv4/netfilter/Makefile 2004-02-16 10:11:53.000000000 -0600
@@ -66,6 +66,8 @@
obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
+obj-$(CONFIG_IP_NF_MATCH_CHILDLEVEL) += ipt_childlevel.o
+
# targets
obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
diff -Naur linux-2.6.2-stock/net/ipv4/netfilter/ipt_childlevel.c linux-2.6.2-childlevel/net/ipv4/netfilter/ipt_childlevel.c
--- linux-2.6.2-stock/net/ipv4/netfilter/ipt_childlevel.c 1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.2-childlevel/net/ipv4/netfilter/ipt_childlevel.c 2004-02-15 19:58:01.000000000 -0600
@@ -0,0 +1,76 @@
+/*
+ Kernel module to match the childlevel of a connection.
+ i.e. The ftp control stream is childlevel 0.
+ The ftp data stream is childlevel 1.
+
+ By Matthew Strait <quadong@xxxxxxxxxxxx>, 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
+*/
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+
+#include <linux/netfilter_ipv4/ipt_childlevel.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+
+MODULE_AUTHOR("Matthew Strait <quadong@xxxxxxxxxxxx>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Childlevel match module");
+
+static int match(const struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, const void *matchinfo,
+ int offset, int *hotdrop)
+{
+ struct ipt_childlevel_info * info = (struct ipt_childlevel_info *)matchinfo;
+ enum ip_conntrack_info ctinfo;
+ struct ip_conntrack * conntrack;
+ int childlevel = 0;
+
+ if(!(conntrack = ip_conntrack_get((struct sk_buff *)skb, &ctinfo))){
+ printk(KERN_ERR "Netfilter: childlevel: error getting conntrack, giving up.\n");
+ return 0;
+ }
+
+ while (master_ct(conntrack) != NULL){
+ childlevel++;
+ conntrack = master_ct(conntrack);
+ }
+
+ return ( (childlevel == info->childlevel) ^ info->invert);
+}
+
+static int
+checkentry(const char *tablename, const struct ipt_ip *ip,
+ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_childlevel_info)))
+ return 0;
+ return 1;
+}
+
+static struct ipt_match childlevel_match = {
+ .name = "childlevel",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ipt_register_match(&childlevel_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&childlevel_match);
+}
+
+module_init(init);
+module_exit(fini);