blob: ee09f2990367c17233877cbcaff9c3dc6dd5c3d7 [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 */
9#include <stdio.h>
Jan Engelhardt5d9678a2008-11-20 10:15:35 +010010#include <xtables.h>
Harald Welte385a1dd2002-02-17 21:32:32 +000011#include <linux/netfilter_ipv4/ipt_ECN.h>
12
Jan Engelhardte3646322011-03-03 00:51:16 +010013enum {
14 O_ECN_TCP_REMOVE = 0,
15 O_ECN_TCP_CWR,
16 O_ECN_TCP_ECE,
17 O_ECN_IP_ECT,
18 F_ECN_TCP_REMOVE = 1 << O_ECN_TCP_REMOVE,
19 F_ECN_TCP_CWR = 1 << O_ECN_TCP_CWR,
20 F_ECN_TCP_ECE = 1 << O_ECN_TCP_ECE,
21};
22
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000023static void ECN_help(void)
Harald Welte385a1dd2002-02-17 21:32:32 +000024{
25 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020026"ECN target options\n"
27" --ecn-tcp-remove Remove all ECN bits from TCP header\n");
Harald Welte31d12a52002-08-06 18:46:18 +000028}
29
30#if 0
Harald Welte1c8fa732002-05-29 12:43:34 +000031"ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
Harald Weltec980a242002-05-29 12:26:13 +000032" --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n"
33" --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n"
Harald Welte92cad5f2002-08-06 06:50:04 +000034" --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n",
Harald Welte31d12a52002-08-06 18:46:18 +000035#endif
36
Jan Engelhardte3646322011-03-03 00:51:16 +010037static const struct xt_option_entry ECN_opts[] = {
38 {.name = "ecn-tcp-remove", .id = O_ECN_TCP_REMOVE, .type = XTTYPE_NONE,
39 .excl = F_ECN_TCP_CWR | F_ECN_TCP_ECE},
40 {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_UINT8,
41 .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE},
42 {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_UINT8,
43 .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE},
44 {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8,
45 .min = 0, .max = 3},
46 XTOPT_TABLEEND,
Harald Welte385a1dd2002-02-17 21:32:32 +000047};
48
Jan Engelhardte3646322011-03-03 00:51:16 +010049static void ECN_parse(struct xt_option_call *cb)
Harald Welte385a1dd2002-02-17 21:32:32 +000050{
Jan Engelhardte3646322011-03-03 00:51:16 +010051 struct ipt_ECN_info *einfo = cb->data;
Harald Welte385a1dd2002-02-17 21:32:32 +000052
Jan Engelhardte3646322011-03-03 00:51:16 +010053 xtables_option_parse(cb);
54 switch (cb->entry->id) {
55 case O_ECN_TCP_REMOVE:
Harald Weltec980a242002-05-29 12:26:13 +000056 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
57 einfo->proto.tcp.ece = 0;
58 einfo->proto.tcp.cwr = 0;
Harald Welte385a1dd2002-02-17 21:32:32 +000059 break;
Jan Engelhardte3646322011-03-03 00:51:16 +010060 case O_ECN_TCP_CWR:
Harald Weltec980a242002-05-29 12:26:13 +000061 einfo->operation |= IPT_ECN_OP_SET_CWR;
Jan Engelhardte3646322011-03-03 00:51:16 +010062 einfo->proto.tcp.cwr = cb->val.u8;
Harald Weltec980a242002-05-29 12:26:13 +000063 break;
Jan Engelhardte3646322011-03-03 00:51:16 +010064 case O_ECN_TCP_ECE:
Harald Weltec980a242002-05-29 12:26:13 +000065 einfo->operation |= IPT_ECN_OP_SET_ECE;
Jan Engelhardte3646322011-03-03 00:51:16 +010066 einfo->proto.tcp.ece = cb->val.u8;
Harald Weltec980a242002-05-29 12:26:13 +000067 break;
Jan Engelhardte3646322011-03-03 00:51:16 +010068 case O_ECN_IP_ECT:
Harald Weltec980a242002-05-29 12:26:13 +000069 einfo->operation |= IPT_ECN_OP_SET_IP;
Jan Engelhardte3646322011-03-03 00:51:16 +010070 einfo->ip_ect = cb->val.u8;
Harald Weltec05c44f2002-08-05 19:36:15 +000071 break;
Harald Welte385a1dd2002-02-17 21:32:32 +000072 }
Harald Welte385a1dd2002-02-17 21:32:32 +000073}
74
Jan Engelhardte3646322011-03-03 00:51:16 +010075static void ECN_check(struct xt_fcheck_call *cb)
Harald Welte385a1dd2002-02-17 21:32:32 +000076{
Jan Engelhardte3646322011-03-03 00:51:16 +010077 if (cb->xflags == 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010078 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardt4e5d4bf2011-02-19 19:37:53 +010079 "ECN target: An operation is required");
Harald Welte385a1dd2002-02-17 21:32:32 +000080}
81
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +000082static void ECN_print(const void *ip, const struct xt_entry_target *target,
83 int numeric)
Harald Welte385a1dd2002-02-17 21:32:32 +000084{
85 const struct ipt_ECN_info *einfo =
86 (const struct ipt_ECN_info *)target->data;
87
Jan Engelhardt73866352010-12-18 02:04:59 +010088 printf(" ECN");
Harald Welte385a1dd2002-02-17 21:32:32 +000089
Harald Welte7b49af42002-05-29 15:11:36 +000090 if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
91 && einfo->proto.tcp.ece == 0
92 && einfo->proto.tcp.cwr == 0)
Jan Engelhardt73866352010-12-18 02:04:59 +010093 printf(" TCP remove");
Harald Welte7b49af42002-05-29 15:11:36 +000094 else {
95 if (einfo->operation & IPT_ECN_OP_SET_ECE)
Jan Engelhardt73866352010-12-18 02:04:59 +010096 printf(" ECE=%u", einfo->proto.tcp.ece);
Harald Welte7b49af42002-05-29 15:11:36 +000097
98 if (einfo->operation & IPT_ECN_OP_SET_CWR)
Jan Engelhardt73866352010-12-18 02:04:59 +010099 printf(" CWR=%u", einfo->proto.tcp.cwr);
Harald Welte7b49af42002-05-29 15:11:36 +0000100
101 if (einfo->operation & IPT_ECN_OP_SET_IP)
Jan Engelhardt73866352010-12-18 02:04:59 +0100102 printf(" ECT codepoint=%u", einfo->ip_ect);
Harald Welte385a1dd2002-02-17 21:32:32 +0000103 }
104}
105
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000106static void ECN_save(const void *ip, const struct xt_entry_target *target)
Harald Welte385a1dd2002-02-17 21:32:32 +0000107{
108 const struct ipt_ECN_info *einfo =
109 (const struct ipt_ECN_info *)target->data;
110
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(" --ecn-tcp-remove");
Harald Welte7b49af42002-05-29 15:11:36 +0000115 else {
Harald Weltec980a242002-05-29 12:26:13 +0000116
Harald Welte7b49af42002-05-29 15:11:36 +0000117 if (einfo->operation & IPT_ECN_OP_SET_ECE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100118 printf(" --ecn-tcp-ece %d", einfo->proto.tcp.ece);
Harald Weltec980a242002-05-29 12:26:13 +0000119
Harald Welte7b49af42002-05-29 15:11:36 +0000120 if (einfo->operation & IPT_ECN_OP_SET_CWR)
Jan Engelhardt73866352010-12-18 02:04:59 +0100121 printf(" --ecn-tcp-cwr %d", einfo->proto.tcp.cwr);
Harald Welte7b49af42002-05-29 15:11:36 +0000122
123 if (einfo->operation & IPT_ECN_OP_SET_IP)
Jan Engelhardt73866352010-12-18 02:04:59 +0100124 printf(" --ecn-ip-ect %d", einfo->ip_ect);
Harald Welte385a1dd2002-02-17 21:32:32 +0000125 }
126}
127
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200128static struct xtables_target ecn_tg_reg = {
Pablo Neira8caee8b2004-12-28 13:11:59 +0000129 .name = "ECN",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200130 .version = XTABLES_VERSION,
Jan Engelhardt03d99482008-11-18 12:27:54 +0100131 .family = NFPROTO_IPV4,
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200132 .size = XT_ALIGN(sizeof(struct ipt_ECN_info)),
133 .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)),
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000134 .help = ECN_help,
Jan Engelhardt1d5b63d2007-10-04 16:29:00 +0000135 .print = ECN_print,
136 .save = ECN_save,
Jan Engelhardte3646322011-03-03 00:51:16 +0100137 .x6_parse = ECN_parse,
138 .x6_fcheck = ECN_check,
139 .x6_options = ECN_opts,
Harald Welte385a1dd2002-02-17 21:32:32 +0000140};
141
142void _init(void)
143{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200144 xtables_register_target(&ecn_tg_reg);
Harald Welte385a1dd2002-02-17 21:32:32 +0000145}