1 /*
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@medozas.de>
6 */
7 #include <getopt.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <netinet/in.h>
13
14 #include <xtables.h>
15 #include <linux/netfilter/xt_DSCP.h>
16 #include "tos_values.c"
17
18 struct ipt_tos_target_info {
19 uint8_t tos;
20 };
21
22 enum {
23 O_SET_TOS = 0,
24 O_AND_TOS,
25 O_OR_TOS,
26 O_XOR_TOS,
27 F_SET_TOS = 1 << O_SET_TOS,
28 F_AND_TOS = 1 << O_AND_TOS,
29 F_OR_TOS = 1 << O_OR_TOS,
30 F_XOR_TOS = 1 << O_XOR_TOS,
31 F_ANY = F_SET_TOS | F_AND_TOS | F_OR_TOS | F_XOR_TOS,
32 };
33
34 static const struct xt_option_entry tos_tg_opts_v0[] = {
35 {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK,
36 .excl = F_ANY, .max = 0xFF},
37 XTOPT_TABLEEND,
38 };
39
40 static const struct xt_option_entry tos_tg_opts[] = {
41 {.name = "set-tos", .id = O_SET_TOS, .type = XTTYPE_TOSMASK,
42 .excl = F_ANY, .max = 0x3F},
43 {.name = "and-tos", .id = O_AND_TOS, .type = XTTYPE_UINT8,
44 .excl = F_ANY},
45 {.name = "or-tos", .id = O_OR_TOS, .type = XTTYPE_UINT8,
46 .excl = F_ANY},
47 {.name = "xor-tos", .id = O_XOR_TOS, .type = XTTYPE_UINT8,
48 .excl = F_ANY},
49 XTOPT_TABLEEND,
50 };
51
tos_tg_help_v0(void)52 static void tos_tg_help_v0(void)
53 {
54 const struct tos_symbol_info *symbol;
55
56 printf(
57 "TOS target options:\n"
58 " --set-tos value Set Type of Service/Priority field to value\n"
59 " --set-tos symbol Set TOS field (IPv4 only) by symbol\n"
60 " Accepted symbolic names for value are:\n");
61
62 for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
63 printf(" (0x%02x) %2u %s\n",
64 symbol->value, symbol->value, symbol->name);
65
66 printf("\n");
67 }
68
tos_tg_help(void)69 static void tos_tg_help(void)
70 {
71 const struct tos_symbol_info *symbol;
72
73 printf(
74 "TOS target v%s options:\n"
75 " --set-tos value[/mask] Set Type of Service/Priority field to value\n"
76 " (Zero out bits in mask and XOR value into TOS)\n"
77 " --set-tos symbol Set TOS field (IPv4 only) by symbol\n"
78 " (this zeroes the 4-bit Precedence part!)\n"
79 " Accepted symbolic names for value are:\n",
80 XTABLES_VERSION);
81
82 for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
83 printf(" (0x%02x) %2u %s\n",
84 symbol->value, symbol->value, symbol->name);
85
86 printf(
87 "\n"
88 " --and-tos bits Binary AND the TOS value with bits\n"
89 " --or-tos bits Binary OR the TOS value with bits\n"
90 " --xor-tos bits Binary XOR the TOS value with bits\n"
91 );
92 }
93
tos_tg_parse_v0(struct xt_option_call * cb)94 static void tos_tg_parse_v0(struct xt_option_call *cb)
95 {
96 struct ipt_tos_target_info *info = cb->data;
97
98 xtables_option_parse(cb);
99 if (cb->val.tos_mask != 0xFF)
100 xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel "
101 "is too old to support anything besides "
102 "/0xFF as a mask.");
103 info->tos = cb->val.tos_value;
104 }
105
tos_tg_parse(struct xt_option_call * cb)106 static void tos_tg_parse(struct xt_option_call *cb)
107 {
108 struct xt_tos_target_info *info = cb->data;
109
110 xtables_option_parse(cb);
111 switch (cb->entry->id) {
112 case O_SET_TOS:
113 info->tos_value = cb->val.tos_value;
114 info->tos_mask = cb->val.tos_mask;
115 break;
116 case O_AND_TOS:
117 info->tos_value = 0;
118 info->tos_mask = ~cb->val.u8;
119 break;
120 case O_OR_TOS:
121 info->tos_value = cb->val.u8;
122 info->tos_mask = cb->val.u8;
123 break;
124 case O_XOR_TOS:
125 info->tos_value = cb->val.u8;
126 info->tos_mask = 0;
127 break;
128 }
129 }
130
tos_tg_check(struct xt_fcheck_call * cb)131 static void tos_tg_check(struct xt_fcheck_call *cb)
132 {
133 if (!(cb->xflags & F_ANY))
134 xtables_error(PARAMETER_PROBLEM,
135 "TOS: An action is required");
136 }
137
tos_tg_print_v0(const void * ip,const struct xt_entry_target * target,int numeric)138 static void tos_tg_print_v0(const void *ip,
139 const struct xt_entry_target *target, int numeric)
140 {
141 const struct ipt_tos_target_info *info = (const void *)target->data;
142
143 printf(" TOS set ");
144 if (numeric || !tos_try_print_symbolic("", info->tos, 0xFF))
145 printf("0x%02x", info->tos);
146 }
147
tos_tg_print(const void * ip,const struct xt_entry_target * target,int numeric)148 static void tos_tg_print(const void *ip, const struct xt_entry_target *target,
149 int numeric)
150 {
151 const struct xt_tos_target_info *info = (const void *)target->data;
152
153 if (numeric)
154 printf(" TOS set 0x%02x/0x%02x",
155 info->tos_value, info->tos_mask);
156 else if (tos_try_print_symbolic(" TOS set",
157 info->tos_value, info->tos_mask))
158 /* already printed by call */
159 return;
160 else if (info->tos_value == 0)
161 printf(" TOS and 0x%02x",
162 (unsigned int)(uint8_t)~info->tos_mask);
163 else if (info->tos_value == info->tos_mask)
164 printf(" TOS or 0x%02x", info->tos_value);
165 else if (info->tos_mask == 0)
166 printf(" TOS xor 0x%02x", info->tos_value);
167 else
168 printf(" TOS set 0x%02x/0x%02x",
169 info->tos_value, info->tos_mask);
170 }
171
tos_tg_save_v0(const void * ip,const struct xt_entry_target * target)172 static void tos_tg_save_v0(const void *ip, const struct xt_entry_target *target)
173 {
174 const struct ipt_tos_target_info *info = (const void *)target->data;
175
176 printf(" --set-tos 0x%02x", info->tos);
177 }
178
tos_tg_save(const void * ip,const struct xt_entry_target * target)179 static void tos_tg_save(const void *ip, const struct xt_entry_target *target)
180 {
181 const struct xt_tos_target_info *info = (const void *)target->data;
182
183 printf(" --set-tos 0x%02x/0x%02x", info->tos_value, info->tos_mask);
184 }
185
186 static struct xtables_target tos_tg_reg[] = {
187 {
188 .version = XTABLES_VERSION,
189 .name = "TOS",
190 .revision = 0,
191 .family = NFPROTO_IPV4,
192 .size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
193 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
194 .help = tos_tg_help_v0,
195 .print = tos_tg_print_v0,
196 .save = tos_tg_save_v0,
197 .x6_parse = tos_tg_parse_v0,
198 .x6_fcheck = tos_tg_check,
199 .x6_options = tos_tg_opts_v0,
200 },
201 {
202 .version = XTABLES_VERSION,
203 .name = "TOS",
204 .revision = 1,
205 .family = NFPROTO_UNSPEC,
206 .size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
207 .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
208 .help = tos_tg_help,
209 .print = tos_tg_print,
210 .save = tos_tg_save,
211 .x6_parse = tos_tg_parse,
212 .x6_fcheck = tos_tg_check,
213 .x6_options = tos_tg_opts,
214 },
215 };
216
_init(void)217 void _init(void)
218 {
219 xtables_register_targets(tos_tg_reg, ARRAY_SIZE(tos_tg_reg));
220 }
221