Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libxt_dscp.c
1 /* Shared library add-on to iptables for DSCP
2  *
3  * (C) 2002 by Harald Welte <laforge@gnumonks.org>
4  *
5  * This program is distributed under the terms of GNU GPL v2, 1991
6  *
7  * libipt_dscp.c borrowed heavily from libipt_tos.c
8  *
9  * --class support added by Iain Barnes
10  * 
11  * For a list of DSCP codepoints see 
12  * http://www.iana.org/assignments/dscp-registry
13  *
14  */
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <getopt.h>
19
20 #include <xtables.h>
21 #include <linux/netfilter/x_tables.h>
22 #include <linux/netfilter/xt_dscp.h>
23
24 /* This is evil, but it's my code - HW*/
25 #include "dscp_helper.c"
26
27 static void dscp_help(void)
28 {
29         printf(
30 "dscp match options\n"
31 "[!] --dscp value               Match DSCP codepoint with numerical value\n"
32 "                               This value can be in decimal (ex: 32)\n"
33 "                               or in hex (ex: 0x20)\n"
34 "[!] --dscp-class name          Match the DiffServ class. This value may\n"
35 "                               be any of the BE,EF, AFxx or CSx classes\n"
36 "\n"
37 "                               These two options are mutually exclusive !\n");
38 }
39
40 static const struct option dscp_opts[] = {
41         { "dscp", 1, NULL, 'F' },
42         { "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 (!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
63 static void
64 parse_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
73 static int
74 dscp_parse(int c, char **argv, int invert, unsigned int *flags,
75            const void *entry, struct xt_entry_match **match)
76 {
77         struct xt_dscp_info *dinfo
78                 = (struct xt_dscp_info *)(*match)->data;
79
80         switch (c) {
81         case 'F':
82                 if (*flags)
83                         xtables_error(PARAMETER_PROBLEM,
84                                    "DSCP match: Only use --dscp ONCE!");
85                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
86                 parse_dscp(optarg, dinfo);
87                 if (invert)
88                         dinfo->invert = 1;
89                 *flags = 1;
90                 break;
91
92         case 'G':
93                 if (*flags)
94                         xtables_error(PARAMETER_PROBLEM,
95                                         "DSCP match: Only use --dscp-class ONCE!");
96                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
97                 parse_class(optarg, dinfo);
98                 if (invert)
99                         dinfo->invert = 1;
100                 *flags = 1;
101                 break;
102
103         default:
104                 return 0;
105         }
106
107         return 1;
108 }
109
110 static void dscp_check(unsigned int flags)
111 {
112         if (!flags)
113                 xtables_error(PARAMETER_PROBLEM,
114                            "DSCP match: Parameter --dscp is required");
115 }
116
117 static void
118 dscp_print(const void *ip, const struct xt_entry_match *match, int numeric)
119 {
120         const struct xt_dscp_info *dinfo =
121                 (const struct xt_dscp_info *)match->data;
122         printf("DSCP match %s0x%02x", dinfo->invert ? "!" : "", dinfo->dscp);
123 }
124
125 static void dscp_save(const void *ip, const struct xt_entry_match *match)
126 {
127         const struct xt_dscp_info *dinfo =
128                 (const struct xt_dscp_info *)match->data;
129
130         printf("%s--dscp 0x%02x ", dinfo->invert ? "! " : "", dinfo->dscp);
131 }
132
133 static struct xtables_match dscp_match = {
134         .family         = NFPROTO_UNSPEC,
135         .name           = "dscp",
136         .version        = XTABLES_VERSION,
137         .size           = XT_ALIGN(sizeof(struct xt_dscp_info)),
138         .userspacesize  = XT_ALIGN(sizeof(struct xt_dscp_info)),
139         .help           = dscp_help,
140         .parse          = dscp_parse,
141         .final_check    = dscp_check,
142         .print          = dscp_print,
143         .save           = dscp_save,
144         .extra_opts     = dscp_opts,
145 };
146
147 void _init(void)
148 {
149         xtables_register_match(&dscp_match);
150 }