1 /* Shared library add-on to iptables for ECN matching
3 * (C) 2002 by Harald Welte <laforge@gnumonks.org>
5 * This program is distributed under the terms of GNU GPL v2, 1991
7 * libipt_ecn.c borrowed heavily from libipt_dscp.c
16 #include <linux/netfilter_ipv4/ipt_ecn.h>
18 static void ecn_help(void)
22 "[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
23 "[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
24 "[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n");
27 static const struct option ecn_opts[] = {
28 { .name = "ecn-tcp-cwr", .has_arg = 0, .val = 'F' },
29 { .name = "ecn-tcp-ece", .has_arg = 0, .val = 'G' },
30 { .name = "ecn-ip-ect", .has_arg = 1, .val = 'H' },
34 static int ecn_parse(int c, char **argv, int invert, unsigned int *flags,
35 const void *entry, struct xt_entry_match **match)
38 struct ipt_ecn_info *einfo
39 = (struct ipt_ecn_info *)(*match)->data;
43 if (*flags & IPT_ECN_OP_MATCH_CWR)
44 xtables_error(PARAMETER_PROBLEM,
45 "ECN match: can only use parameter ONCE!");
46 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
47 einfo->operation |= IPT_ECN_OP_MATCH_CWR;
49 einfo->invert |= IPT_ECN_OP_MATCH_CWR;
50 *flags |= IPT_ECN_OP_MATCH_CWR;
54 if (*flags & IPT_ECN_OP_MATCH_ECE)
55 xtables_error(PARAMETER_PROBLEM,
56 "ECN match: can only use parameter ONCE!");
57 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
58 einfo->operation |= IPT_ECN_OP_MATCH_ECE;
60 einfo->invert |= IPT_ECN_OP_MATCH_ECE;
61 *flags |= IPT_ECN_OP_MATCH_ECE;
65 if (*flags & IPT_ECN_OP_MATCH_IP)
66 xtables_error(PARAMETER_PROBLEM,
67 "ECN match: can only use parameter ONCE!");
68 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
70 einfo->invert |= IPT_ECN_OP_MATCH_IP;
71 *flags |= IPT_ECN_OP_MATCH_IP;
72 einfo->operation |= IPT_ECN_OP_MATCH_IP;
73 if (!xtables_strtoui(optarg, NULL, &result, 0, 3))
74 xtables_error(PARAMETER_PROBLEM,
75 "ECN match: Value out of range");
76 einfo->ip_ect = result;
85 static void ecn_check(unsigned int flags)
88 xtables_error(PARAMETER_PROBLEM,
89 "ECN match: some option required");
92 static void ecn_print(const void *ip, const struct xt_entry_match *match,
95 const struct ipt_ecn_info *einfo =
96 (const struct ipt_ecn_info *)match->data;
100 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
101 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
106 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
107 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
112 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
113 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
115 printf("ECT=%d ", einfo->ip_ect);
119 static void ecn_save(const void *ip, const struct xt_entry_match *match)
121 const struct ipt_ecn_info *einfo =
122 (const struct ipt_ecn_info *)match->data;
124 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
125 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
127 printf("--ecn-tcp-ece ");
130 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
131 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
133 printf("--ecn-tcp-cwr ");
136 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
137 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
139 printf("--ecn-ip-ect %d", einfo->ip_ect);
143 static struct xtables_match ecn_mt_reg = {
145 .version = XTABLES_VERSION,
146 .family = NFPROTO_IPV4,
147 .size = XT_ALIGN(sizeof(struct ipt_ecn_info)),
148 .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)),
151 .final_check = ecn_check,
154 .extra_opts = ecn_opts,
159 xtables_register_match(&ecn_mt_reg);