OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / iptables / 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$
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
19 static 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
34 static 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
42 static 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
99 static 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
106 static 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
130 static 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
152 static 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
166 void _init(void)
167 {
168         xtables_register_target(&ecn_tg_reg);
169 }