blob: 2aa1a00c18976290126ece91c574657553f67d77 [file] [log] [blame]
Harald Welte385a1dd2002-02-17 21:32:32 +00001/* 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
Harald Welte385a1dd2002-02-17 21:32:32 +00008 */
Jan Engelhardt32b8e612010-07-23 21:16:14 +02009#include <stdbool.h>
Harald Welte385a1dd2002-02-17 21:32:32 +000010#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <getopt.h>
14
Jan Engelhardt5d9678a2008-11-20 10:15:35 +010015#include <xtables.h>
Harald Welte385a1dd2002-02-17 21:32:32 +000016#include <linux/netfilter_ipv4/ipt_ECN.h>
17
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000018static void ECN_help(void)
Harald Welte385a1dd2002-02-17 21:32:32 +000019{
20 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020021"ECN target options\n"
22" --ecn-tcp-remove Remove all ECN bits from TCP header\n");
Harald Welte31d12a52002-08-06 18:46:18 +000023}
24
25#if 0
Harald Welte1c8fa732002-05-29 12:43:34 +000026"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
Harald Weltec980a242002-05-29 12:26:13 +000027" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n"
28" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n"
Harald Welte92cad5f2002-08-06 06:50:04 +000029" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n",
Harald Welte31d12a52002-08-06 18:46:18 +000030#endif
31
Harald Welte385a1dd2002-02-17 21:32:32 +000032
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000033static const struct option ECN_opts[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020034 {.name = "ecn-tcp-remove", .has_arg = false, .val = 'F'},
35 {.name = "ecn-tcp-cwr", .has_arg = true, .val = 'G'},
36 {.name = "ecn-tcp-ece", .has_arg = true, .val = 'H'},
37 {.name = "ecn-ip-ect", .has_arg = true, .val = '9'},
38 XT_GETOPT_TABLEEND,
Harald Welte385a1dd2002-02-17 21:32:32 +000039};
40
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000041static int ECN_parse(int c, char **argv, int invert, unsigned int *flags,
42 const void *entry, struct xt_entry_target **target)
Harald Welte385a1dd2002-02-17 21:32:32 +000043{
Harald Weltec980a242002-05-29 12:26:13 +000044 unsigned int result;
Harald Welte5a15c9a2002-02-18 21:32:56 +000045 struct ipt_ECN_info *einfo
Harald Welte385a1dd2002-02-17 21:32:32 +000046 = (struct ipt_ECN_info *)(*target)->data;
47
48 switch (c) {
49 case 'F':
50 if (*flags)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010051 xtables_error(PARAMETER_PROBLEM,
Harald Weltec980a242002-05-29 12:26:13 +000052 "ECN target: Only use --ecn-tcp-remove ONCE!");
53 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
54 einfo->proto.tcp.ece = 0;
55 einfo->proto.tcp.cwr = 0;
Jan Engelhardt094f1042011-02-19 20:00:06 +010056 *flags |= IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
Harald Welte385a1dd2002-02-17 21:32:32 +000057 break;
Harald Weltec980a242002-05-29 12:26:13 +000058 case 'G':
59 if (*flags & IPT_ECN_OP_SET_CWR)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010060 xtables_error(PARAMETER_PROBLEM,
Harald Weltec980a242002-05-29 12:26:13 +000061 "ECN target: Only use --ecn-tcp-cwr ONCE!");
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010062 if (!xtables_strtoui(optarg, NULL, &result, 0, 1))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010063 xtables_error(PARAMETER_PROBLEM,
Harald Weltec980a242002-05-29 12:26:13 +000064 "ECN target: Value out of range");
65 einfo->operation |= IPT_ECN_OP_SET_CWR;
66 einfo->proto.tcp.cwr = result;
67 *flags |= IPT_ECN_OP_SET_CWR;
68 break;
69 case 'H':
70 if (*flags & IPT_ECN_OP_SET_ECE)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010071 xtables_error(PARAMETER_PROBLEM,
Harald Weltec980a242002-05-29 12:26:13 +000072 "ECN target: Only use --ecn-tcp-ece ONCE!");
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010073 if (!xtables_strtoui(optarg, NULL, &result, 0, 1))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010074 xtables_error(PARAMETER_PROBLEM,
Harald Weltec980a242002-05-29 12:26:13 +000075 "ECN target: Value out of range");
76 einfo->operation |= IPT_ECN_OP_SET_ECE;
77 einfo->proto.tcp.ece = result;
78 *flags |= IPT_ECN_OP_SET_ECE;
79 break;
80 case '9':
81 if (*flags & IPT_ECN_OP_SET_IP)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010082 xtables_error(PARAMETER_PROBLEM,
Harald Weltec980a242002-05-29 12:26:13 +000083 "ECN target: Only use --ecn-ip-ect ONCE!");
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010084 if (!xtables_strtoui(optarg, NULL, &result, 0, 3))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010085 xtables_error(PARAMETER_PROBLEM,
Harald Weltec980a242002-05-29 12:26:13 +000086 "ECN target: Value out of range");
87 einfo->operation |= IPT_ECN_OP_SET_IP;
88 einfo->ip_ect = result;
Harald Weltec05c44f2002-08-05 19:36:15 +000089 *flags |= IPT_ECN_OP_SET_IP;
90 break;
Harald Welte385a1dd2002-02-17 21:32:32 +000091 }
92
93 return 1;
94}
95
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000096static void ECN_check(unsigned int flags)
Harald Welte385a1dd2002-02-17 21:32:32 +000097{
98 if (!flags)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010099 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardt4e5d4bf2011-02-19 19:37:53 +0100100 "ECN target: An operation is required");
Harald Welte385a1dd2002-02-17 21:32:32 +0000101}
102
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000103static void ECN_print(const void *ip, const struct xt_entry_target *target,
104 int numeric)
Harald Welte385a1dd2002-02-17 21:32:32 +0000105{
106 const struct ipt_ECN_info *einfo =
107 (const struct ipt_ECN_info *)target->data;
108
Jan Engelhardt73866352010-12-18 02:04:59 +0100109 printf(" ECN");
Harald Welte385a1dd2002-02-17 21:32:32 +0000110
Harald Welte7b49af42002-05-29 15:11:36 +0000111 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
112 && einfo->proto.tcp.ece == 0
113 && einfo->proto.tcp.cwr == 0)
Jan Engelhardt73866352010-12-18 02:04:59 +0100114 printf(" TCP remove");
Harald Welte7b49af42002-05-29 15:11:36 +0000115 else {
116 if (einfo->operation & IPT_ECN_OP_SET_ECE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100117 printf(" ECE=%u", einfo->proto.tcp.ece);
Harald Welte7b49af42002-05-29 15:11:36 +0000118
119 if (einfo->operation & IPT_ECN_OP_SET_CWR)
Jan Engelhardt73866352010-12-18 02:04:59 +0100120 printf(" CWR=%u", einfo->proto.tcp.cwr);
Harald Welte7b49af42002-05-29 15:11:36 +0000121
122 if (einfo->operation & IPT_ECN_OP_SET_IP)
Jan Engelhardt73866352010-12-18 02:04:59 +0100123 printf(" ECT codepoint=%u", einfo->ip_ect);
Harald Welte385a1dd2002-02-17 21:32:32 +0000124 }
125}
126
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000127static void ECN_save(const void *ip, const struct xt_entry_target *target)
Harald Welte385a1dd2002-02-17 21:32:32 +0000128{
129 const struct ipt_ECN_info *einfo =
130 (const struct ipt_ECN_info *)target->data;
131
Harald Welte7b49af42002-05-29 15:11:36 +0000132 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
133 && einfo->proto.tcp.ece == 0
134 && einfo->proto.tcp.cwr == 0)
Jan Engelhardt73866352010-12-18 02:04:59 +0100135 printf(" --ecn-tcp-remove");
Harald Welte7b49af42002-05-29 15:11:36 +0000136 else {
Harald Weltec980a242002-05-29 12:26:13 +0000137
Harald Welte7b49af42002-05-29 15:11:36 +0000138 if (einfo->operation & IPT_ECN_OP_SET_ECE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100139 printf(" --ecn-tcp-ece %d", einfo->proto.tcp.ece);
Harald Weltec980a242002-05-29 12:26:13 +0000140
Harald Welte7b49af42002-05-29 15:11:36 +0000141 if (einfo->operation & IPT_ECN_OP_SET_CWR)
Jan Engelhardt73866352010-12-18 02:04:59 +0100142 printf(" --ecn-tcp-cwr %d", einfo->proto.tcp.cwr);
Harald Welte7b49af42002-05-29 15:11:36 +0000143
144 if (einfo->operation & IPT_ECN_OP_SET_IP)
Jan Engelhardt73866352010-12-18 02:04:59 +0100145 printf(" --ecn-ip-ect %d", einfo->ip_ect);
Harald Welte385a1dd2002-02-17 21:32:32 +0000146 }
147}
148
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200149static struct xtables_target ecn_tg_reg = {
Pablo Neira8caee8b2004-12-28 13:11:59 +0000150 .name = "ECN",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200151 .version = XTABLES_VERSION,
Jan Engelhardt03d99482008-11-18 12:27:54 +0100152 .family = NFPROTO_IPV4,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200153 .size = XT_ALIGN(sizeof(struct ipt_ECN_info)),
154 .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)),
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000155 .help = ECN_help,
156 .parse = ECN_parse,
157 .final_check = ECN_check,
158 .print = ECN_print,
159 .save = ECN_save,
160 .extra_opts = ECN_opts,
Harald Welte385a1dd2002-02-17 21:32:32 +0000161};
162
163void _init(void)
164{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200165 xtables_register_target(&ecn_tg_reg);
Harald Welte385a1dd2002-02-17 21:32:32 +0000166}