changing trunk/trunk to trunk
[iptables.git] / extensions / libxt_DSCP.c
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
24 static 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
40 static const struct option DSCP_opts[] = {
41         { "set-dscp", 1, NULL, 'F' },
42         { "set-dscp-class", 1, NULL, 'G' },
43         { .name = NULL }
44 };
45
46 static void
47 parse_dscp(const char *s, struct xt_DSCP_info *dinfo)
48 {
49         unsigned int dscp;
50        
51         if (string_to_number(s, 0, 255, &dscp) == -1)
52                 exit_error(PARAMETER_PROBLEM,
53                            "Invalid dscp `%s'\n", s);
54
55         if (dscp > XT_DSCP_MAX)
56                 exit_error(PARAMETER_PROBLEM,
57                            "DSCP `%d` out of range\n", dscp);
58
59         dinfo->dscp = (u_int8_t )dscp;
60         return;
61 }
62
63
64 static void
65 parse_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 = (u_int8_t)dscp;
71 }
72
73
74 static 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                         exit_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                         exit_error(PARAMETER_PROBLEM,
91                                    "DSCP target: Only use --set-dscp-class ONCE!");
92                 parse_class(optarg, dinfo);
93                 *flags = 1;
94                 break;
95
96         default:
97                 return 0;
98         }
99
100         return 1;
101 }
102
103 static void DSCP_check(unsigned int flags)
104 {
105         if (!flags)
106                 exit_error(PARAMETER_PROBLEM,
107                            "DSCP target: Parameter --set-dscp is required");
108 }
109
110 static void
111 print_dscp(u_int8_t dscp, int numeric)
112 {
113         printf("0x%02x ", dscp);
114 }
115
116 /* Prints out the targinfo. */
117 static void DSCP_print(const void *ip, const struct xt_entry_target *target,
118                        int numeric)
119 {
120         const struct xt_DSCP_info *dinfo =
121                 (const struct xt_DSCP_info *)target->data;
122         printf("DSCP set ");
123         print_dscp(dinfo->dscp, numeric);
124 }
125
126 /* Saves the union ipt_targinfo in parsable form to stdout. */
127 static void DSCP_save(const void *ip, const struct xt_entry_target *target)
128 {
129         const struct xt_DSCP_info *dinfo =
130                 (const struct xt_DSCP_info *)target->data;
131
132         printf("--set-dscp 0x%02x ", dinfo->dscp);
133 }
134
135 static struct xtables_target dscp_target = {
136         .family         = AF_INET,
137         .name           = "DSCP",
138         .version        = XTABLES_VERSION,
139         .size           = XT_ALIGN(sizeof(struct xt_DSCP_info)),
140         .userspacesize  = XT_ALIGN(sizeof(struct xt_DSCP_info)),
141         .help           = DSCP_help,
142         .parse          = DSCP_parse,
143         .final_check    = DSCP_check,
144         .print          = DSCP_print,
145         .save           = DSCP_save,
146         .extra_opts     = DSCP_opts,
147 };
148
149 static struct xtables_target dscp_target6 = {
150         .family         = AF_INET6,
151         .name           = "DSCP",
152         .version        = XTABLES_VERSION,
153         .size           = XT_ALIGN(sizeof(struct xt_DSCP_info)),
154         .userspacesize  = XT_ALIGN(sizeof(struct xt_DSCP_info)),
155         .help           = DSCP_help,
156         .parse          = DSCP_parse,
157         .final_check    = DSCP_check,
158         .print          = DSCP_print,
159         .save           = DSCP_save,
160         .extra_opts     = DSCP_opts,
161 };
162
163 void _init(void)
164 {
165         xtables_register_target(&dscp_target);
166         xtables_register_target(&dscp_target6);
167 }