1*a71a9546SAutomerger Merge Worker /* Shared library add-on to iptables for ECN, $Version$
2*a71a9546SAutomerger Merge Worker *
3*a71a9546SAutomerger Merge Worker * (C) 2002 by Harald Welte <[email protected]>
4*a71a9546SAutomerger Merge Worker *
5*a71a9546SAutomerger Merge Worker * This program is distributed under the terms of GNU GPL v2, 1991
6*a71a9546SAutomerger Merge Worker *
7*a71a9546SAutomerger Merge Worker * libipt_ECN.c borrowed heavily from libipt_DSCP.c
8*a71a9546SAutomerger Merge Worker */
9*a71a9546SAutomerger Merge Worker #include <stdio.h>
10*a71a9546SAutomerger Merge Worker #include <xtables.h>
11*a71a9546SAutomerger Merge Worker #include <linux/netfilter_ipv4/ipt_ECN.h>
12*a71a9546SAutomerger Merge Worker
13*a71a9546SAutomerger Merge Worker enum {
14*a71a9546SAutomerger Merge Worker O_ECN_TCP_REMOVE = 0,
15*a71a9546SAutomerger Merge Worker O_ECN_TCP_CWR,
16*a71a9546SAutomerger Merge Worker O_ECN_TCP_ECE,
17*a71a9546SAutomerger Merge Worker O_ECN_IP_ECT,
18*a71a9546SAutomerger Merge Worker F_ECN_TCP_REMOVE = 1 << O_ECN_TCP_REMOVE,
19*a71a9546SAutomerger Merge Worker F_ECN_TCP_CWR = 1 << O_ECN_TCP_CWR,
20*a71a9546SAutomerger Merge Worker F_ECN_TCP_ECE = 1 << O_ECN_TCP_ECE,
21*a71a9546SAutomerger Merge Worker };
22*a71a9546SAutomerger Merge Worker
ECN_help(void)23*a71a9546SAutomerger Merge Worker static void ECN_help(void)
24*a71a9546SAutomerger Merge Worker {
25*a71a9546SAutomerger Merge Worker printf(
26*a71a9546SAutomerger Merge Worker "ECN target options\n"
27*a71a9546SAutomerger Merge Worker " --ecn-tcp-remove Remove all ECN bits from TCP header\n");
28*a71a9546SAutomerger Merge Worker }
29*a71a9546SAutomerger Merge Worker
30*a71a9546SAutomerger Merge Worker #if 0
31*a71a9546SAutomerger Merge Worker "ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
32*a71a9546SAutomerger Merge Worker " --ecn-ip-ect Set the IPv4 ECT codepoint (0 to 3)\n"
33*a71a9546SAutomerger Merge Worker " --ecn-tcp-cwr Set the IPv4 CWR bit (0 or 1)\n"
34*a71a9546SAutomerger Merge Worker " --ecn-tcp-ece Set the IPv4 ECE bit (0 or 1)\n",
35*a71a9546SAutomerger Merge Worker #endif
36*a71a9546SAutomerger Merge Worker
37*a71a9546SAutomerger Merge Worker static const struct xt_option_entry ECN_opts[] = {
38*a71a9546SAutomerger Merge Worker {.name = "ecn-tcp-remove", .id = O_ECN_TCP_REMOVE, .type = XTTYPE_NONE,
39*a71a9546SAutomerger Merge Worker .excl = F_ECN_TCP_CWR | F_ECN_TCP_ECE},
40*a71a9546SAutomerger Merge Worker {.name = "ecn-tcp-cwr", .id = O_ECN_TCP_CWR, .type = XTTYPE_UINT8,
41*a71a9546SAutomerger Merge Worker .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE},
42*a71a9546SAutomerger Merge Worker {.name = "ecn-tcp-ece", .id = O_ECN_TCP_ECE, .type = XTTYPE_UINT8,
43*a71a9546SAutomerger Merge Worker .min = 0, .max = 1, .excl = F_ECN_TCP_REMOVE},
44*a71a9546SAutomerger Merge Worker {.name = "ecn-ip-ect", .id = O_ECN_IP_ECT, .type = XTTYPE_UINT8,
45*a71a9546SAutomerger Merge Worker .min = 0, .max = 3},
46*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
47*a71a9546SAutomerger Merge Worker };
48*a71a9546SAutomerger Merge Worker
ECN_parse(struct xt_option_call * cb)49*a71a9546SAutomerger Merge Worker static void ECN_parse(struct xt_option_call *cb)
50*a71a9546SAutomerger Merge Worker {
51*a71a9546SAutomerger Merge Worker struct ipt_ECN_info *einfo = cb->data;
52*a71a9546SAutomerger Merge Worker
53*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
54*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
55*a71a9546SAutomerger Merge Worker case O_ECN_TCP_REMOVE:
56*a71a9546SAutomerger Merge Worker einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
57*a71a9546SAutomerger Merge Worker einfo->proto.tcp.ece = 0;
58*a71a9546SAutomerger Merge Worker einfo->proto.tcp.cwr = 0;
59*a71a9546SAutomerger Merge Worker break;
60*a71a9546SAutomerger Merge Worker case O_ECN_TCP_CWR:
61*a71a9546SAutomerger Merge Worker einfo->operation |= IPT_ECN_OP_SET_CWR;
62*a71a9546SAutomerger Merge Worker einfo->proto.tcp.cwr = cb->val.u8;
63*a71a9546SAutomerger Merge Worker break;
64*a71a9546SAutomerger Merge Worker case O_ECN_TCP_ECE:
65*a71a9546SAutomerger Merge Worker einfo->operation |= IPT_ECN_OP_SET_ECE;
66*a71a9546SAutomerger Merge Worker einfo->proto.tcp.ece = cb->val.u8;
67*a71a9546SAutomerger Merge Worker break;
68*a71a9546SAutomerger Merge Worker case O_ECN_IP_ECT:
69*a71a9546SAutomerger Merge Worker einfo->operation |= IPT_ECN_OP_SET_IP;
70*a71a9546SAutomerger Merge Worker einfo->ip_ect = cb->val.u8;
71*a71a9546SAutomerger Merge Worker break;
72*a71a9546SAutomerger Merge Worker }
73*a71a9546SAutomerger Merge Worker }
74*a71a9546SAutomerger Merge Worker
ECN_check(struct xt_fcheck_call * cb)75*a71a9546SAutomerger Merge Worker static void ECN_check(struct xt_fcheck_call *cb)
76*a71a9546SAutomerger Merge Worker {
77*a71a9546SAutomerger Merge Worker if (cb->xflags == 0)
78*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
79*a71a9546SAutomerger Merge Worker "ECN target: An operation is required");
80*a71a9546SAutomerger Merge Worker }
81*a71a9546SAutomerger Merge Worker
ECN_print(const void * ip,const struct xt_entry_target * target,int numeric)82*a71a9546SAutomerger Merge Worker static void ECN_print(const void *ip, const struct xt_entry_target *target,
83*a71a9546SAutomerger Merge Worker int numeric)
84*a71a9546SAutomerger Merge Worker {
85*a71a9546SAutomerger Merge Worker const struct ipt_ECN_info *einfo =
86*a71a9546SAutomerger Merge Worker (const struct ipt_ECN_info *)target->data;
87*a71a9546SAutomerger Merge Worker
88*a71a9546SAutomerger Merge Worker printf(" ECN");
89*a71a9546SAutomerger Merge Worker
90*a71a9546SAutomerger Merge Worker if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
91*a71a9546SAutomerger Merge Worker && einfo->proto.tcp.ece == 0
92*a71a9546SAutomerger Merge Worker && einfo->proto.tcp.cwr == 0)
93*a71a9546SAutomerger Merge Worker printf(" TCP remove");
94*a71a9546SAutomerger Merge Worker else {
95*a71a9546SAutomerger Merge Worker if (einfo->operation & IPT_ECN_OP_SET_ECE)
96*a71a9546SAutomerger Merge Worker printf(" ECE=%u", einfo->proto.tcp.ece);
97*a71a9546SAutomerger Merge Worker
98*a71a9546SAutomerger Merge Worker if (einfo->operation & IPT_ECN_OP_SET_CWR)
99*a71a9546SAutomerger Merge Worker printf(" CWR=%u", einfo->proto.tcp.cwr);
100*a71a9546SAutomerger Merge Worker
101*a71a9546SAutomerger Merge Worker if (einfo->operation & IPT_ECN_OP_SET_IP)
102*a71a9546SAutomerger Merge Worker printf(" ECT codepoint=%u", einfo->ip_ect);
103*a71a9546SAutomerger Merge Worker }
104*a71a9546SAutomerger Merge Worker }
105*a71a9546SAutomerger Merge Worker
ECN_save(const void * ip,const struct xt_entry_target * target)106*a71a9546SAutomerger Merge Worker static void ECN_save(const void *ip, const struct xt_entry_target *target)
107*a71a9546SAutomerger Merge Worker {
108*a71a9546SAutomerger Merge Worker const struct ipt_ECN_info *einfo =
109*a71a9546SAutomerger Merge Worker (const struct ipt_ECN_info *)target->data;
110*a71a9546SAutomerger Merge Worker
111*a71a9546SAutomerger Merge Worker if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
112*a71a9546SAutomerger Merge Worker && einfo->proto.tcp.ece == 0
113*a71a9546SAutomerger Merge Worker && einfo->proto.tcp.cwr == 0)
114*a71a9546SAutomerger Merge Worker printf(" --ecn-tcp-remove");
115*a71a9546SAutomerger Merge Worker else {
116*a71a9546SAutomerger Merge Worker
117*a71a9546SAutomerger Merge Worker if (einfo->operation & IPT_ECN_OP_SET_ECE)
118*a71a9546SAutomerger Merge Worker printf(" --ecn-tcp-ece %d", einfo->proto.tcp.ece);
119*a71a9546SAutomerger Merge Worker
120*a71a9546SAutomerger Merge Worker if (einfo->operation & IPT_ECN_OP_SET_CWR)
121*a71a9546SAutomerger Merge Worker printf(" --ecn-tcp-cwr %d", einfo->proto.tcp.cwr);
122*a71a9546SAutomerger Merge Worker
123*a71a9546SAutomerger Merge Worker if (einfo->operation & IPT_ECN_OP_SET_IP)
124*a71a9546SAutomerger Merge Worker printf(" --ecn-ip-ect %d", einfo->ip_ect);
125*a71a9546SAutomerger Merge Worker }
126*a71a9546SAutomerger Merge Worker }
127*a71a9546SAutomerger Merge Worker
128*a71a9546SAutomerger Merge Worker static struct xtables_target ecn_tg_reg = {
129*a71a9546SAutomerger Merge Worker .name = "ECN",
130*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
131*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
132*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct ipt_ECN_info)),
133*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)),
134*a71a9546SAutomerger Merge Worker .help = ECN_help,
135*a71a9546SAutomerger Merge Worker .print = ECN_print,
136*a71a9546SAutomerger Merge Worker .save = ECN_save,
137*a71a9546SAutomerger Merge Worker .x6_parse = ECN_parse,
138*a71a9546SAutomerger Merge Worker .x6_fcheck = ECN_check,
139*a71a9546SAutomerger Merge Worker .x6_options = ECN_opts,
140*a71a9546SAutomerger Merge Worker };
141*a71a9546SAutomerger Merge Worker
_init(void)142*a71a9546SAutomerger Merge Worker void _init(void)
143*a71a9546SAutomerger Merge Worker {
144*a71a9546SAutomerger Merge Worker xtables_register_target(&ecn_tg_reg);
145*a71a9546SAutomerger Merge Worker }
146