fix for f12, gcc4.4
[iptables.git] / extensions / libipt_ECN.c
1 /* 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: libipt_ECN.c 3507 2004-12-28 13:11:59Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=rusty/emailAddress=rusty@netfilter.org $
10  */
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <getopt.h>
15
16 #include <iptables.h>
17 #include <linux/netfilter_ipv4/ip_tables.h>
18 #include <linux/netfilter_ipv4/ipt_ECN.h>
19
20 static void init(struct ipt_entry_target *t, unsigned int *nfcache) 
21 {
22 }
23
24 static void help(void) 
25 {
26         printf(
27 "ECN target v%s options\n"
28 "  --ecn-tcp-remove             Remove all ECN bits from TCP header\n",
29                 IPTABLES_VERSION);
30 }
31
32 #if 0
33 "ECN target v%s EXPERIMENTAL options (use with extreme care!)\n"
34 "  --ecn-ip-ect                 Set the IPv4 ECT codepoint (0 to 3)\n"
35 "  --ecn-tcp-cwr                Set the IPv4 CWR bit (0 or 1)\n"
36 "  --ecn-tcp-ece                Set the IPv4 ECE bit (0 or 1)\n",
37 #endif
38
39
40 static struct option opts[] = {
41         { "ecn-tcp-remove", 0, 0, 'F' },
42         { "ecn-tcp-cwr", 1, 0, 'G' },
43         { "ecn-tcp-ece", 1, 0, 'H' },
44         { "ecn-ip-ect", 1, 0, '9' },
45         { 0 }
46 };
47
48 static int
49 parse(int c, char **argv, int invert, unsigned int *flags,
50       const struct ipt_entry *entry,
51       struct ipt_entry_target **target)
52 {
53         unsigned int result;
54         struct ipt_ECN_info *einfo
55                 = (struct ipt_ECN_info *)(*target)->data;
56
57         switch (c) {
58         case 'F':
59                 if (*flags)
60                         exit_error(PARAMETER_PROBLEM,
61                                 "ECN target: Only use --ecn-tcp-remove ONCE!");
62                 einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
63                 einfo->proto.tcp.ece = 0;
64                 einfo->proto.tcp.cwr = 0;
65                 *flags = 1;
66                 break;
67         case 'G':
68                 if (*flags & IPT_ECN_OP_SET_CWR)
69                         exit_error(PARAMETER_PROBLEM,
70                                 "ECN target: Only use --ecn-tcp-cwr ONCE!");
71                 if (string_to_number(optarg, 0, 1, &result))
72                         exit_error(PARAMETER_PROBLEM,
73                                    "ECN target: Value out of range");
74                 einfo->operation |= IPT_ECN_OP_SET_CWR;
75                 einfo->proto.tcp.cwr = result;
76                 *flags |= IPT_ECN_OP_SET_CWR;
77                 break;
78         case 'H':
79                 if (*flags & IPT_ECN_OP_SET_ECE)
80                         exit_error(PARAMETER_PROBLEM,
81                                 "ECN target: Only use --ecn-tcp-ece ONCE!");
82                 if (string_to_number(optarg, 0, 1, &result))
83                         exit_error(PARAMETER_PROBLEM,
84                                    "ECN target: Value out of range");
85                 einfo->operation |= IPT_ECN_OP_SET_ECE;
86                 einfo->proto.tcp.ece = result;
87                 *flags |= IPT_ECN_OP_SET_ECE;
88                 break;
89         case '9':
90                 if (*flags & IPT_ECN_OP_SET_IP)
91                         exit_error(PARAMETER_PROBLEM,
92                                 "ECN target: Only use --ecn-ip-ect ONCE!");
93                 if (string_to_number(optarg, 0, 3, &result))
94                         exit_error(PARAMETER_PROBLEM,
95                                    "ECN target: Value out of range");
96                 einfo->operation |= IPT_ECN_OP_SET_IP;
97                 einfo->ip_ect = result;
98                 *flags |= IPT_ECN_OP_SET_IP;
99                 break;
100         default:
101                 return 0;
102         }
103
104         return 1;
105 }
106
107 static void
108 final_check(unsigned int flags)
109 {
110         if (!flags)
111                 exit_error(PARAMETER_PROBLEM,
112                            "ECN target: Parameter --ecn-tcp-remove is required");
113 }
114
115 /* Prints out the targinfo. */
116 static void
117 print(const struct ipt_ip *ip,
118       const struct ipt_entry_target *target,
119       int numeric)
120 {
121         const struct ipt_ECN_info *einfo =
122                 (const struct ipt_ECN_info *)target->data;
123
124         printf("ECN ");
125
126         if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
127             && einfo->proto.tcp.ece == 0
128             && einfo->proto.tcp.cwr == 0)
129                 printf("TCP remove ");
130         else {
131                 if (einfo->operation & IPT_ECN_OP_SET_ECE)
132                         printf("ECE=%u ", einfo->proto.tcp.ece);
133
134                 if (einfo->operation & IPT_ECN_OP_SET_CWR)
135                         printf("CWR=%u ", einfo->proto.tcp.cwr);
136
137                 if (einfo->operation & IPT_ECN_OP_SET_IP)
138                         printf("ECT codepoint=%u ", einfo->ip_ect);
139         }
140 }
141
142 /* Saves the union ipt_targinfo in parsable form to stdout. */
143 static void
144 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
145 {
146         const struct ipt_ECN_info *einfo =
147                 (const struct ipt_ECN_info *)target->data;
148
149         if (einfo->operation == (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)
150             && einfo->proto.tcp.ece == 0
151             && einfo->proto.tcp.cwr == 0)
152                 printf("--ecn-tcp-remove ");
153         else {
154
155                 if (einfo->operation & IPT_ECN_OP_SET_ECE)
156                         printf("--ecn-tcp-ece %d ", einfo->proto.tcp.ece);
157
158                 if (einfo->operation & IPT_ECN_OP_SET_CWR)
159                         printf("--ecn-tcp-cwr %d ", einfo->proto.tcp.cwr);
160
161                 if (einfo->operation & IPT_ECN_OP_SET_IP)
162                         printf("--ecn-ip-ect %d ", einfo->ip_ect);
163         }
164 }
165
166 static
167 struct iptables_target ecn = { 
168         .next           = NULL,
169         .name           = "ECN",
170         .version        = IPTABLES_VERSION,
171         .size           = IPT_ALIGN(sizeof(struct ipt_ECN_info)),
172         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_ECN_info)),
173         .help           = &help,
174         .init           = &init,
175         .parse          = &parse,
176         .final_check    = &final_check,
177         .print          = &print,
178         .save           = &save,
179         .extra_opts     = opts
180 };
181
182 void _init(void)
183 {
184         register_target(&ecn);
185 }