summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlaforge <laforge>2002-05-29 15:11:49 +0000
committerlaforge <laforge>2002-05-29 15:11:49 +0000
commit919709a8c30bf2bd5760b84cc858010b1e487ae4 (patch)
tree9c5a189f331e05fd216c6fb426aa825cca2e2193
parent85b9d8de2aeb08541844c30d00153a7b87525ab1 (diff)
add ECN match plugin
-rw-r--r--extensions/Makefile2
-rw-r--r--extensions/libipt_ecn.c187
2 files changed, 188 insertions, 1 deletions
diff --git a/extensions/Makefile b/extensions/Makefile
index e67ac27..36cddb2 100644
--- a/extensions/Makefile
+++ b/extensions/Makefile
@@ -1,6 +1,6 @@
#! /usr/bin/make
-PF_EXT_SLIB:=ah conntrack dscp esp icmp length limit mac mark multiport owner pkttype standard state tcp tcpmss tos ttl udp unclean DNAT DSCP ECN LOG MARK MASQUERADE MIRROR REDIRECT REJECT SAME SNAT TCPMSS TOS ULOG
+PF_EXT_SLIB:=ah conntrack dscp ecn esp icmp length limit mac mark multiport owner pkttype standard state tcp tcpmss tos ttl udp unclean DNAT DSCP ECN LOG MARK MASQUERADE MIRROR REDIRECT REJECT SAME SNAT TCPMSS TOS ULOG
PF6_EXT_SLIB:=eui64 icmpv6 length limit mac mark multiport owner standard tcp udp LOG MARK
# The following may not be present, but compile them anyway.
diff --git a/extensions/libipt_ecn.c b/extensions/libipt_ecn.c
new file mode 100644
index 0000000..7dcee2c
--- /dev/null
+++ b/extensions/libipt_ecn.c
@@ -0,0 +1,187 @@
+/* Shared library add-on to iptables for ECN matching
+ *
+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ * libipt_ecn.c borrowed heavily from libipt_dscp.c
+ *
+ */
+#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_ecn.h>
+
+static void init(struct ipt_entry_match *m, unsigned int *nfcache)
+{
+ *nfcache |= NFC_IP_TOS;
+}
+
+static void help(void)
+{
+ printf(
+"ECN match v%s options\n"
+"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
+"[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
+"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n",
+ IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+ { "ecn-tcp-cwr", 0, 0, 'F' },
+ { "ecn-tcp-ece", 0, 0, 'G' },
+ { "ecn-ip-ect", 1, 0, 'H' },
+ { 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)
+{
+ unsigned int result;
+ struct ipt_ecn_info *einfo
+ = (struct ipt_ecn_info *)(*match)->data;
+
+ switch (c) {
+ case 'F':
+ if (*flags & IPT_ECN_OP_MATCH_CWR)
+ exit_error(PARAMETER_PROBLEM,
+ "ECN match: can only use parameter ONCE!");
+ check_inverse(optarg, &invert, &optind, 0);
+ einfo->operation |= IPT_ECN_OP_MATCH_CWR;
+ if (invert)
+ einfo->invert |= IPT_ECN_OP_MATCH_CWR;
+ *flags |= IPT_ECN_OP_MATCH_CWR;
+ break;
+
+ case 'G':
+ if (*flags & IPT_ECN_OP_MATCH_ECE)
+ exit_error(PARAMETER_PROBLEM,
+ "ECN match: can only use parameter ONCE!");
+ check_inverse(optarg, &invert, &optind, 0);
+ einfo->operation |= IPT_ECN_OP_MATCH_ECE;
+ if (invert)
+ einfo->invert |= IPT_ECN_OP_MATCH_ECE;
+ *flags |= IPT_ECN_OP_MATCH_ECE;
+ break;
+
+ case 'H':
+ if (*flags & IPT_ECN_OP_MATCH_IP)
+ exit_error(PARAMETER_PROBLEM,
+ "ECN match: can only use parameter ONCE!");
+ check_inverse(optarg, &invert, &optind, 0);
+ if (invert)
+ einfo->invert |= IPT_ECN_OP_MATCH_IP;
+ *flags |= IPT_ECN_OP_MATCH_IP;
+ einfo->operation |= IPT_ECN_OP_MATCH_IP;
+ if (string_to_number(optarg, 0, 3, &result))
+ exit_error(PARAMETER_PROBLEM,
+ "ECN match: Value out of range");
+ einfo->ip_ect = result;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+final_check(unsigned int flags)
+{
+ if (!flags)
+ exit_error(PARAMETER_PROBLEM,
+ "ECN match: some option required");
+}
+
+static void
+print_dscp(u_int8_t dscp, int invert, int numeric)
+{
+ if (invert)
+ fputc('!', stdout);
+
+ printf("0x%02x ", dscp);
+}
+
+/* Prints out the matchinfo. */
+static void
+print(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match,
+ int numeric)
+{
+ const struct ipt_ecn_info *einfo =
+ (const struct ipt_ecn_info *)match->data;
+
+ printf("ECN match ");
+
+ if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
+ if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
+ fputc('!', stdout);
+ printf("ECE ");
+ }
+
+ if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
+ if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
+ fputc('!', stdout);
+ printf("CWR ");
+ }
+
+ if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
+ if (einfo->invert & IPT_ECN_OP_MATCH_IP)
+ fputc('!', stdout);
+ printf("ECT=%d ", einfo->ip_ect);
+ }
+}
+
+/* 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_ecn_info *einfo =
+ (const struct ipt_ecn_info *)match->data;
+
+ if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
+ if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
+ printf("! ");
+ printf("--ecn-tcp-ece ");
+ }
+
+ if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
+ if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
+ printf("! ");
+ printf("--ecn-tcp-cwr ");
+ }
+
+ if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
+ if (einfo->invert & IPT_ECN_OP_MATCH_IP)
+ printf("! ");
+ printf("--ecn-ip-ect %d", einfo->ip_ect);
+ }
+}
+
+static
+struct iptables_match ecn
+= { NULL,
+ "ecn",
+ IPTABLES_VERSION,
+ IPT_ALIGN(sizeof(struct ipt_ecn_info)),
+ IPT_ALIGN(sizeof(struct ipt_ecn_info)),
+ &help,
+ &init,
+ &parse,
+ &final_check,
+ &print,
+ &save,
+ opts
+};
+
+void _init(void)
+{
+ register_match(&ecn);
+}