Skip to content

Commit 12a7cf9

Browse files
committed
Add support for DSCP matches and target
Signed-off-by: Jo-Philipp Wich <[email protected]>
1 parent aa8846b commit 12a7cf9

File tree

5 files changed

+126
-18
lines changed

5 files changed

+126
-18
lines changed

iptables.c

+14
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,20 @@ fw3_ipt_rule_mark(struct fw3_ipt_rule *r, struct fw3_mark *mark)
11401140
fw3_ipt_rule_addarg(r, mark->invert, "--mark", buf);
11411141
}
11421142

1143+
void
1144+
fw3_ipt_rule_dscp(struct fw3_ipt_rule *r, struct fw3_dscp *dscp)
1145+
{
1146+
char buf[sizeof("0xFF\0")];
1147+
1148+
if (!dscp || !dscp->set)
1149+
return;
1150+
1151+
sprintf(buf, "0x%x", dscp->dscp);
1152+
1153+
fw3_ipt_rule_addarg(r, false, "-m", "dscp");
1154+
fw3_ipt_rule_addarg(r, dscp->invert, "--dscp", buf);
1155+
}
1156+
11431157
void
11441158
fw3_ipt_rule_comment(struct fw3_ipt_rule *r, const char *fmt, ...)
11451159
{

iptables.h

+2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ void fw3_ipt_rule_time(struct fw3_ipt_rule *r, struct fw3_time *time);
9393

9494
void fw3_ipt_rule_mark(struct fw3_ipt_rule *r, struct fw3_mark *mark);
9595

96+
void fw3_ipt_rule_dscp(struct fw3_ipt_rule *r, struct fw3_dscp *dscp);
97+
9698
void fw3_ipt_rule_comment(struct fw3_ipt_rule *r, const char *fmt, ...);
9799

98100
void fw3_ipt_rule_extra(struct fw3_ipt_rule *r, const char *extra);

options.c

+59
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const char *fw3_flag_names[__FW3_FLAG_MAX] = {
7777
"NOTRACK",
7878
"HELPER",
7979
"MARK",
80+
"DSCP",
8081
"DNAT",
8182
"SNAT",
8283
"MASQUERADE",
@@ -135,6 +136,31 @@ static const char *reflection_sources[] = {
135136
"external",
136137
};
137138

139+
static const struct { const char *name; uint8_t dscp; } dscp_classes[] = {
140+
{ "CS0", 0x00 },
141+
{ "CS1", 0x08 },
142+
{ "CS2", 0x10 },
143+
{ "CS3", 0x18 },
144+
{ "CS4", 0x20 },
145+
{ "CS5", 0x28 },
146+
{ "CS6", 0x30 },
147+
{ "CS7", 0x38 },
148+
{ "BE", 0x00 },
149+
{ "AF11", 0x0a },
150+
{ "AF12", 0x0c },
151+
{ "AF13", 0x0e },
152+
{ "AF21", 0x12 },
153+
{ "AF22", 0x14 },
154+
{ "AF23", 0x16 },
155+
{ "AF31", 0x1a },
156+
{ "AF32", 0x1c },
157+
{ "AF33", 0x1e },
158+
{ "AF41", 0x22 },
159+
{ "AF42", 0x24 },
160+
{ "AF43", 0x26 },
161+
{ "EF", 0x2e }
162+
};
163+
138164

139165
bool
140166
fw3_parse_bool(void *ptr, const char *val, bool is_list)
@@ -858,6 +884,39 @@ fw3_parse_mark(void *ptr, const char *val, bool is_list)
858884
return true;
859885
}
860886

887+
bool
888+
fw3_parse_dscp(void *ptr, const char *val, bool is_list)
889+
{
890+
uint32_t n;
891+
char *e;
892+
struct fw3_dscp *d = ptr;
893+
894+
if (*val == '!')
895+
{
896+
d->invert = true;
897+
while (isspace(*++val));
898+
}
899+
900+
for (n = 0; n < sizeof(dscp_classes) / sizeof(dscp_classes[0]); n++)
901+
{
902+
if (strcmp(dscp_classes[n].name, val))
903+
continue;
904+
905+
d->set = true;
906+
d->dscp = dscp_classes[n].dscp;
907+
return true;
908+
}
909+
910+
n = strtoul(val, &e, 0);
911+
912+
if (e == val || *e || n > 0x3F)
913+
return false;
914+
915+
d->set = true;
916+
d->dscp = n;
917+
return true;
918+
}
919+
861920
bool
862921
fw3_parse_setmatch(void *ptr, const char *val, bool is_list)
863922
{

options.h

+22-11
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,18 @@ enum fw3_flag
7373
FW3_FLAG_NOTRACK = 9,
7474
FW3_FLAG_HELPER = 10,
7575
FW3_FLAG_MARK = 11,
76-
FW3_FLAG_DNAT = 12,
77-
FW3_FLAG_SNAT = 13,
78-
FW3_FLAG_MASQUERADE = 14,
79-
FW3_FLAG_SRC_ACCEPT = 15,
80-
FW3_FLAG_SRC_REJECT = 16,
81-
FW3_FLAG_SRC_DROP = 17,
82-
FW3_FLAG_CUSTOM_CHAINS = 18,
83-
FW3_FLAG_SYN_FLOOD = 19,
84-
FW3_FLAG_MTU_FIX = 20,
85-
FW3_FLAG_DROP_INVALID = 21,
86-
FW3_FLAG_HOTPLUG = 22,
76+
FW3_FLAG_DSCP = 12,
77+
FW3_FLAG_DNAT = 13,
78+
FW3_FLAG_SNAT = 14,
79+
FW3_FLAG_MASQUERADE = 15,
80+
FW3_FLAG_SRC_ACCEPT = 16,
81+
FW3_FLAG_SRC_REJECT = 17,
82+
FW3_FLAG_SRC_DROP = 18,
83+
FW3_FLAG_CUSTOM_CHAINS = 19,
84+
FW3_FLAG_SYN_FLOOD = 20,
85+
FW3_FLAG_MTU_FIX = 21,
86+
FW3_FLAG_DROP_INVALID = 22,
87+
FW3_FLAG_HOTPLUG = 23,
8788

8889
__FW3_FLAG_MAX
8990
};
@@ -268,6 +269,13 @@ struct fw3_mark
268269
uint32_t mask;
269270
};
270271

272+
struct fw3_dscp
273+
{
274+
bool set;
275+
bool invert;
276+
uint8_t dscp;
277+
};
278+
271279
struct fw3_cthelpermatch
272280
{
273281
struct list_head list;
@@ -382,10 +390,12 @@ struct fw3_rule
382390
struct fw3_limit limit;
383391
struct fw3_time time;
384392
struct fw3_mark mark;
393+
struct fw3_dscp dscp;
385394

386395
enum fw3_flag target;
387396
struct fw3_mark set_mark;
388397
struct fw3_mark set_xmark;
398+
struct fw3_dscp set_dscp;
389399
struct fw3_cthelpermatch set_helper;
390400

391401
const char *extra;
@@ -613,6 +623,7 @@ bool fw3_parse_time(void *ptr, const char *val, bool is_list);
613623
bool fw3_parse_weekdays(void *ptr, const char *val, bool is_list);
614624
bool fw3_parse_monthdays(void *ptr, const char *val, bool is_list);
615625
bool fw3_parse_mark(void *ptr, const char *val, bool is_list);
626+
bool fw3_parse_dscp(void *ptr, const char *val, bool is_list);
616627
bool fw3_parse_setmatch(void *ptr, const char *val, bool is_list);
617628
bool fw3_parse_direction(void *ptr, const char *val, bool is_list);
618629
bool fw3_parse_cthelper(void *ptr, const char *val, bool is_list);

rules.c

+29-7
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ const struct fw3_option fw3_rule_opts[] = {
6262
FW3_OPT("set_mark", mark, rule, set_mark),
6363
FW3_OPT("set_xmark", mark, rule, set_xmark),
6464

65+
FW3_OPT("dscp", dscp, rule, dscp),
66+
FW3_OPT("set_dscp", dscp, rule, set_dscp),
67+
6568
FW3_OPT("target", target, rule, target),
6669

6770
{ }
@@ -156,19 +159,28 @@ check_rule(struct fw3_state *state, struct fw3_rule *r, struct uci_element *e)
156159
r->target == FW3_FLAG_MARK)
157160
{
158161
warn_section("rule", r, e, "is set to target MARK but specifies neither "
159-
"'set_mark' nor 'set_xmark' option");
162+
"'set_mark' nor 'set_xmark' option");
160163
return false;
161164
}
162165

163-
if (r->_dest && r->target == FW3_FLAG_MARK)
166+
if (!r->set_dscp.set && r->target == FW3_FLAG_DSCP)
164167
{
165-
warn_section("rule", r, e, "must not specify 'dest' for MARK target");
168+
warn_section("rule", r, e, "is set to target DSCP but specifies no "
169+
"'set_dscp' option");
166170
return false;
167171
}
168172

169-
if (r->set_mark.invert || r->set_xmark.invert)
173+
if (r->_dest && (r->target == FW3_FLAG_MARK || r->target == FW3_FLAG_DSCP))
170174
{
171-
warn_section("rule", r, e, "must not have inverted 'set_mark' or 'set_xmark'");
175+
warn_section("rule", r, e, "must not specify 'dest' for %s target",
176+
fw3_flag_names[r->target]);
177+
return false;
178+
}
179+
180+
if (r->set_mark.invert || r->set_xmark.invert || r->set_dscp.invert)
181+
{
182+
warn_section("rule", r, e, "must not have inverted 'set_mark', "
183+
"'set_xmark' or 'set_dscp'");
172184
return false;
173185
}
174186

@@ -202,7 +214,7 @@ check_rule(struct fw3_state *state, struct fw3_rule *r, struct uci_element *e)
202214
warn_section("rule", r, e, "has no target specified, defaulting to REJECT");
203215
r->target = FW3_FLAG_REJECT;
204216
}
205-
else if (r->target > FW3_FLAG_MARK)
217+
else if (r->target > FW3_FLAG_DSCP)
206218
{
207219
warn_section("rule", r, e, "has invalid target specified, defaulting to REJECT");
208220
r->target = FW3_FLAG_REJECT;
@@ -297,7 +309,8 @@ append_chain(struct fw3_ipt_rule *r, struct fw3_rule *rule)
297309
{
298310
snprintf(chain, sizeof(chain), "zone_%s_helper", rule->src.name);
299311
}
300-
else if (rule->target == FW3_FLAG_MARK && (rule->_src || rule->src.any))
312+
else if ((rule->target == FW3_FLAG_MARK || rule->target == FW3_FLAG_DSCP) &&
313+
(rule->_src || rule->src.any))
301314
{
302315
snprintf(chain, sizeof(chain), "PREROUTING");
303316
}
@@ -353,6 +366,13 @@ static void set_target(struct fw3_ipt_rule *r, struct fw3_rule *rule)
353366
fw3_ipt_rule_addarg(r, false, name, buf);
354367
return;
355368

369+
case FW3_FLAG_DSCP:
370+
sprintf(buf, "0x%x", rule->set_dscp.dscp);
371+
372+
fw3_ipt_rule_target(r, "DSCP");
373+
fw3_ipt_rule_addarg(r, false, "--set-dscp", buf);
374+
return;
375+
356376
case FW3_FLAG_NOTRACK:
357377
fw3_ipt_rule_target(r, "CT");
358378
fw3_ipt_rule_addarg(r, false, "--notrack", NULL);
@@ -461,6 +481,7 @@ print_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
461481
fw3_ipt_rule_limit(r, &rule->limit);
462482
fw3_ipt_rule_time(r, &rule->time);
463483
fw3_ipt_rule_mark(r, &rule->mark);
484+
fw3_ipt_rule_dscp(r, &rule->dscp);
464485
set_target(r, rule);
465486
fw3_ipt_rule_extra(r, rule->extra);
466487
set_comment(r, rule->name, num);
@@ -492,6 +513,7 @@ expand_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
492513
if ((rule->target == FW3_FLAG_NOTRACK && handle->table != FW3_TABLE_RAW) ||
493514
(rule->target == FW3_FLAG_HELPER && handle->table != FW3_TABLE_RAW) ||
494515
(rule->target == FW3_FLAG_MARK && handle->table != FW3_TABLE_MANGLE) ||
516+
(rule->target == FW3_FLAG_DSCP && handle->table != FW3_TABLE_MANGLE) ||
495517
(rule->target < FW3_FLAG_NOTRACK && handle->table != FW3_TABLE_FILTER))
496518
return;
497519

0 commit comments

Comments
 (0)