blob: bf1f8a5a4c5474601a1ee650f1996bc024a6c258 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* Shared library add-on to iptables for ECN, $Version$
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 * $Id$
10 */
11#include <stdio.h>
12#include <string.h>
13#include <stdlib.h>
14#include <getopt.h>
15
16#include <xtables.h>
17#include <linux/netfilter_ipv4/ipt_ECN.h>
18
19static void ECN_help(void)
20{
21 printf(
22"ECN target options\n"
23" --ecn-tcp-remove Remove all ECN bits from TCP header\n");
24}
25
26#if 0
27"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
28" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n"
29" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n"
30" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n",
31#endif
32
33
34static const struct option ECN_opts[] = {
35 { "ecn-tcp-remove", 0, NULL, 'F' },
36 { "ecn-tcp-cwr", 1, NULL, 'G' },
37 { "ecn-tcp-ece", 1, NULL, 'H' },
38 { "ecn-ip-ect", 1, NULL, '9' },
39 { .name = NULL }
40};
41
42static int ECN_parse(int c, char **argv, int invert, unsigned int *flags,
43 const void *entry, struct xt_entry_target **target)
44{
45 unsigned int result;
46 struct ipt_ECN_info *einfo
47 = (struct ipt_ECN_info *)(*target)->data;
48
49 switch (c) {
50 case 'F':
51 if (*flags)
52 xtables_error(PARAMETER_PROBLEM,
53 "ECN target: Only use --ecn-tcp-remove ONCE!");
54 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
55 einfo->proto.tcp.ece = 0;
56 einfo->proto.tcp.cwr = 0;
57 *flags = 1;
58 break;
59 case 'G':
60 if (*flags & IPT_ECN_OP_SET_CWR)
61 xtables_error(PARAMETER_PROBLEM,
62 "ECN target: Only use --ecn-tcp-cwr ONCE!");
63 if (!xtables_strtoui(optarg, NULL, &result, 0, 1))
64 xtables_error(PARAMETER_PROBLEM,
65 "ECN target: Value out of range");
66 einfo->operation |= IPT_ECN_OP_SET_CWR;
67 einfo->proto.tcp.cwr = result;
68 *flags |= IPT_ECN_OP_SET_CWR;
69 break;
70 case 'H':
71 if (*flags & IPT_ECN_OP_SET_ECE)
72 xtables_error(PARAMETER_PROBLEM,
73 "ECN target: Only use --ecn-tcp-ece ONCE!");
74 if (!xtables_strtoui(optarg, NULL, &result, 0, 1))
75 xtables_error(PARAMETER_PROBLEM,
76 "ECN target: Value out of range");
77 einfo->operation |= IPT_ECN_OP_SET_ECE;
78 einfo->proto.tcp.ece = result;
79 *flags |= IPT_ECN_OP_SET_ECE;
80 break;
81 case '9':
82 if (*flags & IPT_ECN_OP_SET_IP)
83 xtables_error(PARAMETER_PROBLEM,
84 "ECN target: Only use --ecn-ip-ect ONCE!");
85 if (!xtables_strtoui(optarg, NULL, &result, 0, 3))
86 xtables_error(PARAMETER_PROBLEM,
87 "ECN target: Value out of range");
88 einfo->operation |= IPT_ECN_OP_SET_IP;
89 einfo->ip_ect = result;
90 *flags |= IPT_ECN_OP_SET_IP;
91 break;
92 default:
93 return 0;
94 }
95
96 return 1;
97}
98
99static void ECN_check(unsigned int flags)
100{
101 if (!flags)
102 xtables_error(PARAMETER_PROBLEM,
103 "ECN target: Parameter --ecn-tcp-remove is required");
104}
105
106static void ECN_print(const void *ip, const struct xt_entry_target *target,
107 int numeric)
108{
109 const struct ipt_ECN_info *einfo =
110 (const struct ipt_ECN_info *)target->data;
111
112 printf("ECN ");
113
114 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
115 && einfo->proto.tcp.ece == 0
116 && einfo->proto.tcp.cwr == 0)
117 printf("TCP remove ");
118 else {
119 if (einfo->operation & IPT_ECN_OP_SET_ECE)
120 printf("ECE=%u ", einfo->proto.tcp.ece);
121
122 if (einfo->operation & IPT_ECN_OP_SET_CWR)
123 printf("CWR=%u ", einfo->proto.tcp.cwr);
124
125 if (einfo->operation & IPT_ECN_OP_SET_IP)
126 printf("ECT codepoint=%u ", einfo->ip_ect);
127 }
128}
129
130static void ECN_save(const void *ip, const struct xt_entry_target *target)
131{
132 const struct ipt_ECN_info *einfo =
133 (const struct ipt_ECN_info *)target->data;
134
135 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
136 && einfo->proto.tcp.ece == 0
137 && einfo->proto.tcp.cwr == 0)
138 printf("--ecn-tcp-remove ");
139 else {
140
141 if (einfo->operation & IPT_ECN_OP_SET_ECE)
142 printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece);
143
144 if (einfo->operation & IPT_ECN_OP_SET_CWR)
145 printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr);
146
147 if (einfo->operation & IPT_ECN_OP_SET_IP)
148 printf("--ecn-ip-ect %d ", einfo->ip_ect);
149 }
150}
151
152static struct xtables_target ecn_tg_reg = {
153 .name = "ECN",
154 .version = XTABLES_VERSION,
155 .family = NFPROTO_IPV4,
156 .size = XT_ALIGN(sizeof(struct ipt_ECN_info)),
157 .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)),
158 .help = ECN_help,
159 .parse = ECN_parse,
160 .final_check = ECN_check,
161 .print = ECN_print,
162 .save = ECN_save,
163 .extra_opts = ECN_opts,
164};
165
166void _init(void)
167{
168 xtables_register_target(&ecn_tg_reg);
169}