blob: 777d7cfbc269d6b4bf25bae945c1f0523a910659 [file] [log] [blame]
Jan Engelhardt36f2ead2008-01-20 13:25:08 +00001/*
2 * Shared library add-on to iptables to add TOS target support
3 *
4 * Copyright © CC Computer Consultants GmbH, 2007
5 * Contact: Jan Engelhardt <jengelh@computergmbh.de>
6 */
7#include <getopt.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include <xtables.h>
13#include <linux/netfilter/xt_DSCP.h>
14#include <linux/netfilter_ipv4/ipt_TOS.h>
15#include "tos_values.c"
16
17enum {
18 FLAG_TOS = 1 << 0,
19};
20
21static const struct option tos_tg_opts_v0[] = {
22 {.name = "set-tos", .has_arg = true, .val = '='},
Max Kellermann9ee386a2008-01-29 13:48:05 +000023 { .name = NULL }
Jan Engelhardt36f2ead2008-01-20 13:25:08 +000024};
25
26static const struct option tos_tg_opts[] = {
27 {.name = "set-tos", .has_arg = true, .val = '='},
28 {.name = "and-tos", .has_arg = true, .val = '&'},
29 {.name = "or-tos", .has_arg = true, .val = '|'},
30 {.name = "xor-tos", .has_arg = true, .val = '^'},
Max Kellermann9ee386a2008-01-29 13:48:05 +000031 { .name = NULL }
Jan Engelhardt36f2ead2008-01-20 13:25:08 +000032};
33
34static void tos_tg_help_v0(void)
35{
36 const struct tos_symbol_info *symbol;
37
38 printf(
39"TOS target options:\n"
40" --set-tos value Set Type of Service/Priority field to value\n"
41" --set-tos symbol Set TOS field (IPv4 only) by symbol\n"
42" Accepted symbolic names for value are:\n");
43
44 for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
45 printf(" (0x%02x) %2u %s\n",
46 symbol->value, symbol->value, symbol->name);
47
48 printf("\n");
49}
50
51static void tos_tg_help(void)
52{
53 const struct tos_symbol_info *symbol;
54
55 printf(
56"TOS target v%s options:\n"
57" --set-tos value[/mask] Set Type of Service/Priority field to value\n"
58" (Zero out bits in mask and XOR value into TOS)\n"
59" --set-tos symbol Set TOS field (IPv4 only) by symbol\n"
60" (this zeroes the 4-bit Precedence part!)\n"
61" Accepted symbolic names for value are:\n",
62IPTABLES_VERSION);
63
64 for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
65 printf(" (0x%02x) %2u %s\n",
66 symbol->value, symbol->value, symbol->name);
67
68 printf(
69"\n"
70" --and-tos bits Binary AND the TOS value with bits\n"
71" --or-tos bits Binary OR the TOS value with bits\n"
72" --xor-tos bits Binary XOR the TOS value with bits\n"
73);
74}
75
76static int tos_tg_parse_v0(int c, char **argv, int invert, unsigned int *flags,
77 const void *entry, struct xt_entry_target **target)
78{
79 struct ipt_tos_target_info *info = (void *)(*target)->data;
80 struct tos_value_mask tvm;
81
82 switch (c) {
83 case '=':
84 param_act(P_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
85 param_act(P_NO_INVERT, "TOS", "--set-tos", invert);
86 if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
87 param_act(P_BAD_VALUE, "TOS", "--set-tos", optarg);
88 if (tvm.mask != 0xFF)
89 exit_error(PARAMETER_PROBLEM, "tos match: Your kernel "
90 "is too old to support anything besides "
91 "/0xFF as a mask.");
92 info->tos = tvm.value;
93 *flags |= FLAG_TOS;
94 return true;
95 }
96
97 return false;
98}
99
100static int tos_tg_parse(int c, char **argv, int invert, unsigned int *flags,
101 const void *entry, struct xt_entry_target **target)
102{
103 struct xt_tos_target_info *info = (void *)(*target)->data;
104 struct tos_value_mask tvm;
105 unsigned int bits;
106
107 switch (c) {
108 case '=': /* --set-tos */
109 param_act(P_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
110 param_act(P_NO_INVERT, "TOS", "--set-tos", invert);
111 if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
112 param_act(P_BAD_VALUE, "TOS", "--set-tos", optarg);
113 info->tos_value = tvm.value;
114 info->tos_mask = tvm.mask;
115 break;
116
117 case '&': /* --and-tos */
118 param_act(P_ONLY_ONCE, "TOS", "--and-tos", *flags & FLAG_TOS);
119 param_act(P_NO_INVERT, "TOS", "--and-tos", invert);
120 if (!strtonum(optarg, NULL, &bits, 0, 0xFF))
121 param_act(P_BAD_VALUE, "TOS", "--and-tos", optarg);
122 info->tos_value = 0;
123 info->tos_mask = ~bits;
124 break;
125
126 case '|': /* --or-tos */
127 param_act(P_ONLY_ONCE, "TOS", "--or-tos", *flags & FLAG_TOS);
128 param_act(P_NO_INVERT, "TOS", "--or-tos", invert);
129 if (!strtonum(optarg, NULL, &bits, 0, 0xFF))
130 param_act(P_BAD_VALUE, "TOS", "--or-tos", optarg);
131 info->tos_value = bits;
132 info->tos_mask = bits;
133 break;
134
135 case '^': /* --xor-tos */
136 param_act(P_ONLY_ONCE, "TOS", "--xor-tos", *flags & FLAG_TOS);
137 param_act(P_NO_INVERT, "TOS", "--xor-tos", invert);
138 if (!strtonum(optarg, NULL, &bits, 0, 0xFF))
139 param_act(P_BAD_VALUE, "TOS", "--xor-tos", optarg);
140 info->tos_value = bits;
141 info->tos_mask = 0;
142 break;
143
144 default:
145 return false;
146 }
147
148 *flags |= FLAG_TOS;
149 return true;
150}
151
152static void tos_tg_check(unsigned int flags)
153{
154 if (flags == 0)
155 exit_error(PARAMETER_PROBLEM,
156 "TOS: The --set-tos parameter is required");
157}
158
159static void tos_tg_print_v0(const void *ip,
160 const struct xt_entry_target *target, int numeric)
161{
162 const struct ipt_tos_target_info *info = (const void *)target->data;
163
164 printf("TOS set ");
165 if (numeric || !tos_try_print_symbolic("", info->tos, 0xFF))
166 printf("0x%02x ", info->tos);
167}
168
169static void tos_tg_print(const void *ip, const struct xt_entry_target *target,
170 int numeric)
171{
172 const struct xt_tos_target_info *info = (const void *)target->data;
173
174 if (numeric)
175 printf("TOS set 0x%02x/0x%02x ",
176 info->tos_value, info->tos_mask);
177 else if (tos_try_print_symbolic("TOS set ",
178 info->tos_value, info->tos_mask))
179 /* already printed by call */
180 return;
181 else if (info->tos_value == 0)
182 printf("TOS and 0x%02x ",
183 (unsigned int)(u_int8_t)~info->tos_mask);
184 else if (info->tos_value == info->tos_mask)
185 printf("TOS or 0x%02x ", info->tos_value);
186 else if (info->tos_mask == 0)
187 printf("TOS xor 0x%02x ", info->tos_value);
188 else
189 printf("TOS set 0x%02x/0x%02x ",
190 info->tos_value, info->tos_mask);
191}
192
193static void tos_tg_save_v0(const void *ip, const struct xt_entry_target *target)
194{
195 const struct ipt_tos_target_info *info = (const void *)target->data;
196
197 printf("--set-tos 0x%02x ", info->tos);
198}
199
200static void tos_tg_save(const void *ip, const struct xt_entry_target *target)
201{
202 const struct xt_tos_target_info *info = (const void *)target->data;
203
204 printf("--set-tos 0x%02x/0x%02x ", info->tos_value, info->tos_mask);
205}
206
207static struct xtables_target tos_tg_reg_v0 = {
208 .version = IPTABLES_VERSION,
209 .name = "TOS",
210 .revision = 0,
211 .family = AF_INET,
212 .size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
213 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
214 .help = tos_tg_help_v0,
215 .parse = tos_tg_parse_v0,
216 .final_check = tos_tg_check,
217 .print = tos_tg_print_v0,
218 .save = tos_tg_save_v0,
219 .extra_opts = tos_tg_opts_v0,
220};
221
222static struct xtables_target tos_tg_reg = {
223 .version = IPTABLES_VERSION,
224 .name = "TOS",
225 .revision = 1,
226 .family = AF_INET,
227 .size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
228 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
229 .help = tos_tg_help,
230 .parse = tos_tg_parse,
231 .final_check = tos_tg_check,
232 .print = tos_tg_print,
233 .save = tos_tg_save,
234 .extra_opts = tos_tg_opts,
235};
236
237static struct xtables_target tos_tg6_reg = {
238 .version = IPTABLES_VERSION,
239 .name = "TOS",
240 .family = AF_INET6,
241 .revision = 1,
242 .size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
243 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
244 .help = tos_tg_help,
245 .parse = tos_tg_parse,
246 .final_check = tos_tg_check,
247 .print = tos_tg_print,
248 .save = tos_tg_save,
249 .extra_opts = tos_tg_opts,
250};
251
252void _init(void)
253{
254 xtables_register_target(&tos_tg_reg_v0);
255 xtables_register_target(&tos_tg_reg);
256 xtables_register_target(&tos_tg6_reg);
257}