libxt_DSCP.c revision 500f483fff529dcd88ec96b9d5054be6cd6363a0
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 <stdio.h>
13#include <string.h>
14#include <stdlib.h>
15#include <getopt.h>
16
17#include <xtables.h>
18#include <linux/netfilter/x_tables.h>
19#include <linux/netfilter/xt_DSCP.h>
20
21/* This is evil, but it's my code - HW*/
22#include "libipt_dscp_helper.c"
23
24
25static void init(struct xt_entry_target *t)
26{
27}
28
29static void help(void)
30{
31	printf(
32"DSCP target options\n"
33"  --set-dscp value		Set DSCP field in packet header to value\n"
34"  		                This value can be in decimal (ex: 32)\n"
35"               		or in hex (ex: 0x20)\n"
36"  --set-dscp-class class	Set the DSCP field in packet header to the\n"
37"				value represented by the DiffServ class value.\n"
38"				This class may be EF,BE or any of the CSxx\n"
39"				or AFxx classes.\n"
40"\n"
41"				These two options are mutually exclusive !\n"
42);
43}
44
45static const struct option opts[] = {
46	{ "set-dscp", 1, NULL, 'F' },
47	{ "set-dscp-class", 1, NULL, 'G' },
48	{ }
49};
50
51static void
52parse_dscp(const char *s, struct xt_DSCP_info *dinfo)
53{
54	unsigned int dscp;
55
56	if (string_to_number(s, 0, 255, &dscp) == -1)
57		exit_error(PARAMETER_PROBLEM,
58			   "Invalid dscp `%s'\n", s);
59
60	if (dscp > XT_DSCP_MAX)
61		exit_error(PARAMETER_PROBLEM,
62			   "DSCP `%d` out of range\n", dscp);
63
64    	dinfo->dscp = (u_int8_t )dscp;
65    	return;
66}
67
68
69static void
70parse_class(const char *s, struct xt_DSCP_info *dinfo)
71{
72	unsigned int dscp = class_to_dscp(s);
73
74	/* Assign the value */
75	dinfo->dscp = (u_int8_t)dscp;
76}
77
78
79static int
80parse(int c, char **argv, int invert, unsigned int *flags,
81      const void *entry,
82      struct xt_entry_target **target)
83{
84	struct xt_DSCP_info *dinfo
85		= (struct xt_DSCP_info *)(*target)->data;
86
87	switch (c) {
88	case 'F':
89		if (*flags)
90			exit_error(PARAMETER_PROBLEM,
91			           "DSCP target: Only use --set-dscp ONCE!");
92		parse_dscp(optarg, dinfo);
93		*flags = 1;
94		break;
95	case 'G':
96		if (*flags)
97			exit_error(PARAMETER_PROBLEM,
98				   "DSCP target: Only use --set-dscp-class ONCE!");
99		parse_class(optarg, dinfo);
100		*flags = 1;
101		break;
102
103	default:
104		return 0;
105	}
106
107	return 1;
108}
109
110static void
111final_check(unsigned int flags)
112{
113	if (!flags)
114		exit_error(PARAMETER_PROBLEM,
115		           "DSCP target: Parameter --set-dscp is required");
116}
117
118static void
119print_dscp(u_int8_t dscp, int numeric)
120{
121 	printf("0x%02x ", dscp);
122}
123
124/* Prints out the targinfo. */
125static void
126print(const void *ip,
127      const struct xt_entry_target *target,
128      int numeric)
129{
130	const struct xt_DSCP_info *dinfo =
131		(const struct xt_DSCP_info *)target->data;
132	printf("DSCP set ");
133	print_dscp(dinfo->dscp, numeric);
134}
135
136/* Saves the union ipt_targinfo in parsable form to stdout. */
137static void
138save(const void *ip, const struct xt_entry_target *target)
139{
140	const struct xt_DSCP_info *dinfo =
141		(const struct xt_DSCP_info *)target->data;
142
143	printf("--set-dscp 0x%02x ", dinfo->dscp);
144}
145
146static struct xtables_target dscp = {
147	.family		= AF_INET,
148	.name		= "DSCP",
149	.version	= IPTABLES_VERSION,
150	.size		= XT_ALIGN(sizeof(struct xt_DSCP_info)),
151	.userspacesize	= XT_ALIGN(sizeof(struct xt_DSCP_info)),
152	.help		= &help,
153	.init		= &init,
154	.parse		= &parse,
155	.final_check	= &final_check,
156	.print		= &print,
157	.save		= &save,
158	.extra_opts	= opts,
159};
160
161static struct xtables_target dscp6 = {
162	.family		= AF_INET6,
163	.name		= "DSCP",
164	.version	= IPTABLES_VERSION,
165	.size		= XT_ALIGN(sizeof(struct xt_DSCP_info)),
166	.userspacesize	= XT_ALIGN(sizeof(struct xt_DSCP_info)),
167	.help		= &help,
168	.init		= &init,
169	.parse		= &parse,
170	.final_check	= &final_check,
171	.print		= &print,
172	.save		= &save,
173	.extra_opts	= opts,
174};
175
176void _init(void)
177{
178	xtables_register_target(&dscp);
179	xtables_register_target(&dscp6);
180}
181