libxt_DSCP.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
1/* Shared library add-on to iptables for DSCP
2 *
3 * (C) 2000- 2002 by Matthew G. Marsh <mgm@paktronix.com>,
4 * 		     Harald Welte <laforge@gnumonks.org>
5 *
6 * This program is distributed under the terms of GNU GPL v2, 1991
7 *
8 * libipt_DSCP.c borrowed heavily from libipt_TOS.c
9 *
10 * --set-class added by Iain Barnes
11 */
12#include <stdbool.h>
13#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <getopt.h>
17
18#include <xtables.h>
19#include <linux/netfilter/x_tables.h>
20#include <linux/netfilter/xt_DSCP.h>
21
22/* This is evil, but it's my code - HW*/
23#include "dscp_helper.c"
24
25static void DSCP_help(void)
26{
27	printf(
28"DSCP target options\n"
29"  --set-dscp value		Set DSCP field in packet header to value\n"
30"  		                This value can be in decimal (ex: 32)\n"
31"               		or in hex (ex: 0x20)\n"
32"  --set-dscp-class class	Set the DSCP field in packet header to the\n"
33"				value represented by the DiffServ class value.\n"
34"				This class may be EF,BE or any of the CSxx\n"
35"				or AFxx classes.\n"
36"\n"
37"				These two options are mutually exclusive !\n"
38);
39}
40
41static const struct option DSCP_opts[] = {
42	{.name = "set-dscp",       .has_arg = true, .val = 'F'},
43	{.name = "set-dscp-class", .has_arg = true, .val = 'G'},
44	XT_GETOPT_TABLEEND,
45};
46
47static void
48parse_dscp(const char *s, struct xt_DSCP_info *dinfo)
49{
50	unsigned int dscp;
51
52	if (!xtables_strtoui(s, NULL, &dscp, 0, UINT8_MAX))
53		xtables_error(PARAMETER_PROBLEM,
54			   "Invalid dscp `%s'\n", s);
55
56	if (dscp > XT_DSCP_MAX)
57		xtables_error(PARAMETER_PROBLEM,
58			   "DSCP `%d` out of range\n", dscp);
59
60	dinfo->dscp = dscp;
61}
62
63
64static void
65parse_class(const char *s, struct xt_DSCP_info *dinfo)
66{
67	unsigned int dscp = class_to_dscp(s);
68
69	/* Assign the value */
70	dinfo->dscp = dscp;
71}
72
73
74static int DSCP_parse(int c, char **argv, int invert, unsigned int *flags,
75                      const void *entry, struct xt_entry_target **target)
76{
77	struct xt_DSCP_info *dinfo
78		= (struct xt_DSCP_info *)(*target)->data;
79
80	switch (c) {
81	case 'F':
82		if (*flags)
83			xtables_error(PARAMETER_PROBLEM,
84			           "DSCP target: Only use --set-dscp ONCE!");
85		parse_dscp(optarg, dinfo);
86		*flags = 1;
87		break;
88	case 'G':
89		if (*flags)
90			xtables_error(PARAMETER_PROBLEM,
91				   "DSCP target: Only use --set-dscp-class ONCE!");
92		parse_class(optarg, dinfo);
93		*flags = 1;
94		break;
95	}
96
97	return 1;
98}
99
100static void DSCP_check(unsigned int flags)
101{
102	if (!flags)
103		xtables_error(PARAMETER_PROBLEM,
104		           "DSCP target: Parameter --set-dscp is required");
105}
106
107static void
108print_dscp(uint8_t dscp, int numeric)
109{
110	printf(" 0x%02x", dscp);
111}
112
113static void DSCP_print(const void *ip, const struct xt_entry_target *target,
114                       int numeric)
115{
116	const struct xt_DSCP_info *dinfo =
117		(const struct xt_DSCP_info *)target->data;
118	printf(" DSCP set");
119	print_dscp(dinfo->dscp, numeric);
120}
121
122static void DSCP_save(const void *ip, const struct xt_entry_target *target)
123{
124	const struct xt_DSCP_info *dinfo =
125		(const struct xt_DSCP_info *)target->data;
126
127	printf(" --set-dscp 0x%02x", dinfo->dscp);
128}
129
130static struct xtables_target dscp_target = {
131	.family		= NFPROTO_UNSPEC,
132	.name		= "DSCP",
133	.version	= XTABLES_VERSION,
134	.size		= XT_ALIGN(sizeof(struct xt_DSCP_info)),
135	.userspacesize	= XT_ALIGN(sizeof(struct xt_DSCP_info)),
136	.help		= DSCP_help,
137	.parse		= DSCP_parse,
138	.final_check	= DSCP_check,
139	.print		= DSCP_print,
140	.save		= DSCP_save,
141	.extra_opts	= DSCP_opts,
142};
143
144void _init(void)
145{
146	xtables_register_target(&dscp_target);
147}
148