libxt_DSCP.c revision c5e85736c207f211d82d2878a5781f512327dfce
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 "dscp_helper.c"
23
24static void DSCP_help(void)
25{
26	printf(
27"DSCP target options\n"
28"  --set-dscp value		Set DSCP field in packet header to value\n"
29"  		                This value can be in decimal (ex: 32)\n"
30"               		or in hex (ex: 0x20)\n"
31"  --set-dscp-class class	Set the DSCP field in packet header to the\n"
32"				value represented by the DiffServ class value.\n"
33"				This class may be EF,BE or any of the CSxx\n"
34"				or AFxx classes.\n"
35"\n"
36"				These two options are mutually exclusive !\n"
37);
38}
39
40static const struct option DSCP_opts[] = {
41	{ "set-dscp", 1, NULL, 'F' },
42	{ "set-dscp-class", 1, NULL, 'G' },
43	{ .name = NULL }
44};
45
46static void
47parse_dscp(const char *s, struct xt_DSCP_info *dinfo)
48{
49	unsigned int dscp;
50
51	if (!xtables_strtoui(s, NULL, &dscp, 0, UINT8_MAX))
52		xtables_error(PARAMETER_PROBLEM,
53			   "Invalid dscp `%s'\n", s);
54
55	if (dscp > XT_DSCP_MAX)
56		xtables_error(PARAMETER_PROBLEM,
57			   "DSCP `%d` out of range\n", dscp);
58
59	dinfo->dscp = dscp;
60}
61
62
63static void
64parse_class(const char *s, struct xt_DSCP_info *dinfo)
65{
66	unsigned int dscp = class_to_dscp(s);
67
68	/* Assign the value */
69	dinfo->dscp = dscp;
70}
71
72
73static int DSCP_parse(int c, char **argv, int invert, unsigned int *flags,
74                      const void *entry, struct xt_entry_target **target)
75{
76	struct xt_DSCP_info *dinfo
77		= (struct xt_DSCP_info *)(*target)->data;
78
79	switch (c) {
80	case 'F':
81		if (*flags)
82			xtables_error(PARAMETER_PROBLEM,
83			           "DSCP target: Only use --set-dscp ONCE!");
84		parse_dscp(optarg, dinfo);
85		*flags = 1;
86		break;
87	case 'G':
88		if (*flags)
89			xtables_error(PARAMETER_PROBLEM,
90				   "DSCP target: Only use --set-dscp-class ONCE!");
91		parse_class(optarg, dinfo);
92		*flags = 1;
93		break;
94
95	default:
96		return 0;
97	}
98
99	return 1;
100}
101
102static void DSCP_check(unsigned int flags)
103{
104	if (!flags)
105		xtables_error(PARAMETER_PROBLEM,
106		           "DSCP target: Parameter --set-dscp is required");
107}
108
109static void
110print_dscp(u_int8_t dscp, int numeric)
111{
112 	printf("0x%02x ", dscp);
113}
114
115static void DSCP_print(const void *ip, const struct xt_entry_target *target,
116                       int numeric)
117{
118	const struct xt_DSCP_info *dinfo =
119		(const struct xt_DSCP_info *)target->data;
120	printf("DSCP set ");
121	print_dscp(dinfo->dscp, numeric);
122}
123
124static void DSCP_save(const void *ip, const struct xt_entry_target *target)
125{
126	const struct xt_DSCP_info *dinfo =
127		(const struct xt_DSCP_info *)target->data;
128
129	printf("--set-dscp 0x%02x ", dinfo->dscp);
130}
131
132static struct xtables_target dscp_target = {
133	.family		= NFPROTO_UNSPEC,
134	.name		= "DSCP",
135	.version	= XTABLES_VERSION,
136	.size		= XT_ALIGN(sizeof(struct xt_DSCP_info)),
137	.userspacesize	= XT_ALIGN(sizeof(struct xt_DSCP_info)),
138	.help		= DSCP_help,
139	.parse		= DSCP_parse,
140	.final_check	= DSCP_check,
141	.print		= DSCP_print,
142	.save		= DSCP_save,
143	.extra_opts	= DSCP_opts,
144};
145
146void _init(void)
147{
148	xtables_register_target(&dscp_target);
149}
150