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/ip_tables.h>
17 #include <linux/netfilter_ipv4/ipt_ecn.h>
19 static void ecn_help(void)
23 "[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
24 "[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
25 "[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n");
28 static const struct option ecn_opts[] = {
29 { .name = "ecn-tcp-cwr", .has_arg = 0, .val = 'F' },
30 { .name = "ecn-tcp-ece", .has_arg = 0, .val = 'G' },
31 { .name = "ecn-ip-ect", .has_arg = 1, .val = 'H' },
35 static int ecn_parse(int c, char **argv, int invert, unsigned int *flags,
36 const void *entry, struct xt_entry_match **match)
39 struct ipt_ecn_info *einfo
40 = (struct ipt_ecn_info *)(*match)->data;
44 if (*flags & IPT_ECN_OP_MATCH_CWR)
45 exit_error(PARAMETER_PROBLEM,
46 "ECN match: can only use parameter ONCE!");
47 check_inverse(optarg, &invert, &optind, 0);
48 einfo->operation |= IPT_ECN_OP_MATCH_CWR;
50 einfo->invert |= IPT_ECN_OP_MATCH_CWR;
51 *flags |= IPT_ECN_OP_MATCH_CWR;
55 if (*flags & IPT_ECN_OP_MATCH_ECE)
56 exit_error(PARAMETER_PROBLEM,
57 "ECN match: can only use parameter ONCE!");
58 check_inverse(optarg, &invert, &optind, 0);
59 einfo->operation |= IPT_ECN_OP_MATCH_ECE;
61 einfo->invert |= IPT_ECN_OP_MATCH_ECE;
62 *flags |= IPT_ECN_OP_MATCH_ECE;
66 if (*flags & IPT_ECN_OP_MATCH_IP)
67 exit_error(PARAMETER_PROBLEM,
68 "ECN match: can only use parameter ONCE!");
69 check_inverse(optarg, &invert, &optind, 0);
71 einfo->invert |= IPT_ECN_OP_MATCH_IP;
72 *flags |= IPT_ECN_OP_MATCH_IP;
73 einfo->operation |= IPT_ECN_OP_MATCH_IP;
74 if (string_to_number(optarg, 0, 3, &result))
75 exit_error(PARAMETER_PROBLEM,
76 "ECN match: Value out of range");
77 einfo->ip_ect = result;
86 static void ecn_check(unsigned int flags)
89 exit_error(PARAMETER_PROBLEM,
90 "ECN match: some option required");
93 /* Prints out the matchinfo. */
94 static void ecn_print(const void *ip, const struct xt_entry_match *match,
97 const struct ipt_ecn_info *einfo =
98 (const struct ipt_ecn_info *)match->data;
100 printf("ECN match ");
102 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
103 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
108 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
109 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
114 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
115 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
117 printf("ECT=%d ", einfo->ip_ect);
121 /* Saves the union ipt_matchinfo in parsable form to stdout. */
122 static void ecn_save(const void *ip, const struct xt_entry_match *match)
124 const struct ipt_ecn_info *einfo =
125 (const struct ipt_ecn_info *)match->data;
127 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
128 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
130 printf("--ecn-tcp-ece ");
133 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
134 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
136 printf("--ecn-tcp-cwr ");
139 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
140 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
142 printf("--ecn-ip-ect %d", einfo->ip_ect);
146 static struct xtables_match ecn_mt_reg = {
148 .version = XTABLES_VERSION,
150 .size = XT_ALIGN(sizeof(struct ipt_ecn_info)),
151 .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)),
154 .final_check = ecn_check,
157 .extra_opts = ecn_opts,
162 xtables_register_match(&ecn_mt_reg);