1 /* Shared library add-on to iptables for ECN matching
2 *
3 * (C) 2002 by Harald Welte <laforge@gnumonks.org>
4 *
5 * This program is distributed under the terms of GNU GPL v2, 1991
6 *
7 * libipt_ecn.c borrowed heavily from libipt_dscp.c
8 *
9 */
10 #include <stdio.h>
11 #include <xtables.h>
12 #include <linux/netfilter_ipv4/ipt_ecn.h>
13
14 enum {
15 O_ECN_TCP_CWR = 0,
16 O_ECN_TCP_ECE,
17 O_ECN_IP_ECT,
18 };
19
ecn_help(void)20 static void ecn_help(void)
21 {
22 printf(
23 "ECN match options\n"
24 "[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
25 "[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
26 "[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n");
27 }
28
29 static const struct xt_option_entry ecn_opts[] = {
30 {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_NONE,
31 .flags = XTOPT_INVERT},
32 {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_NONE,
33 .flags = XTOPT_INVERT},
34 {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8,
35 .min = 0, .max = 3, .flags = XTOPT_INVERT},
36 XTOPT_TABLEEND,
37 };
38
ecn_parse(struct xt_option_call * cb)39 static void ecn_parse(struct xt_option_call *cb)
40 {
41 struct ipt_ecn_info *einfo = cb->data;
42
43 xtables_option_parse(cb);
44 switch (cb->entry->id) {
45 case O_ECN_TCP_CWR:
46 einfo->operation |= IPT_ECN_OP_MATCH_CWR;
47 if (cb->invert)
48 einfo->invert |= IPT_ECN_OP_MATCH_CWR;
49 break;
50 case O_ECN_TCP_ECE:
51 einfo->operation |= IPT_ECN_OP_MATCH_ECE;
52 if (cb->invert)
53 einfo->invert |= IPT_ECN_OP_MATCH_ECE;
54 break;
55 case O_ECN_IP_ECT:
56 if (cb->invert)
57 einfo->invert |= IPT_ECN_OP_MATCH_IP;
58 einfo->operation |= IPT_ECN_OP_MATCH_IP;
59 einfo->ip_ect = cb->val.u8;
60 break;
61 }
62 }
63
ecn_check(struct xt_fcheck_call * cb)64 static void ecn_check(struct xt_fcheck_call *cb)
65 {
66 if (cb->xflags == 0)
67 xtables_error(PARAMETER_PROBLEM,
68 "ECN match: some option required");
69 }
70
ecn_print(const void * ip,const struct xt_entry_match * match,int numeric)71 static void ecn_print(const void *ip, const struct xt_entry_match *match,
72 int numeric)
73 {
74 const struct ipt_ecn_info *einfo =
75 (const struct ipt_ecn_info *)match->data;
76
77 printf(" ECN match");
78
79 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
80 printf(" %sECE",
81 (einfo->invert & IPT_ECN_OP_MATCH_ECE) ? "!" : "");
82 }
83
84 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
85 printf(" %sCWR",
86 (einfo->invert & IPT_ECN_OP_MATCH_CWR) ? "!" : "");
87 }
88
89 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
90 printf(" %sECT=%d",
91 (einfo->invert & IPT_ECN_OP_MATCH_IP) ? "!" : "",
92 einfo->ip_ect);
93 }
94 }
95
ecn_save(const void * ip,const struct xt_entry_match * match)96 static void ecn_save(const void *ip, const struct xt_entry_match *match)
97 {
98 const struct ipt_ecn_info *einfo =
99 (const struct ipt_ecn_info *)match->data;
100
101 if (einfo->operation & IPT_ECN_OP_MATCH_ECE) {
102 if (einfo->invert & IPT_ECN_OP_MATCH_ECE)
103 printf(" !");
104 printf(" --ecn-tcp-ece");
105 }
106
107 if (einfo->operation & IPT_ECN_OP_MATCH_CWR) {
108 if (einfo->invert & IPT_ECN_OP_MATCH_CWR)
109 printf(" !");
110 printf(" --ecn-tcp-cwr");
111 }
112
113 if (einfo->operation & IPT_ECN_OP_MATCH_IP) {
114 if (einfo->invert & IPT_ECN_OP_MATCH_IP)
115 printf(" !");
116 printf(" --ecn-ip-ect %d", einfo->ip_ect);
117 }
118 }
119
120 static struct xtables_match ecn_mt_reg = {
121 .name = "ecn",
122 .version = XTABLES_VERSION,
123 .family = NFPROTO_IPV4,
124 .size = XT_ALIGN(sizeof(struct ipt_ecn_info)),
125 .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)),
126 .help = ecn_help,
127 .print = ecn_print,
128 .save = ecn_save,
129 .x6_parse = ecn_parse,
130 .x6_fcheck = ecn_check,
131 .x6_options = ecn_opts,
132 };
133
_init(void)134 void _init(void)
135 {
136 xtables_register_match(&ecn_mt_reg);
137 }
138