iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libipt_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 <iptables.h>
21 #include <linux/netfilter_ipv4/ip_tables.h>
22 #include <linux/netfilter_ipv4/ipt_dscp.h>
23
24 /* This is evil, but it's my code - HW*/
25 #include "libipt_dscp_helper.c"
26
27 static void init(struct ipt_entry_match *m, unsigned int *nfcache) 
28 {
29         *nfcache |= NFC_IP_TOS;
30 }
31
32 static void help(void) 
33 {
34         printf(
35 "DSCP match v%s options\n"
36 "[!] --dscp value               Match DSCP codepoint with numerical value\n"
37 "                               This value can be in decimal (ex: 32)\n"
38 "                               or in hex (ex: 0x20)\n"
39 "[!] --dscp-class name          Match the DiffServ class. This value may\n"
40 "                               be any of the BE,EF, AFxx or CSx classes\n"
41 "\n"
42 "                               These two options are mutually exclusive !\n"
43                                 , IPTABLES_VERSION
44 );
45 }
46
47 static struct option opts[] = {
48         { "dscp", 1, 0, 'F' },
49         { "dscp-class", 1, 0, 'G' },
50         { 0 }
51 };
52
53 static void
54 parse_dscp(const unsigned char *s, struct ipt_dscp_info *dinfo)
55 {
56         unsigned int dscp;
57        
58         if (string_to_number(s, 0, 255, &dscp) == -1)
59                 exit_error(PARAMETER_PROBLEM,
60                            "Invalid dscp `%s'\n", s);
61
62         if (dscp > IPT_DSCP_MAX)
63                 exit_error(PARAMETER_PROBLEM,
64                            "DSCP `%d` out of range\n", dscp);
65
66         dinfo->dscp = (u_int8_t )dscp;
67         return;
68 }
69
70
71 static void
72 parse_class(const char *s, struct ipt_dscp_info *dinfo)
73 {
74         unsigned int dscp = class_to_dscp(s);
75
76         /* Assign the value */
77         dinfo->dscp = (u_int8_t)dscp;
78 }
79
80
81 static int
82 parse(int c, char **argv, int invert, unsigned int *flags,
83       const struct ipt_entry *entry,
84       unsigned int *nfcache,
85       struct ipt_entry_match **match)
86 {
87         struct ipt_dscp_info *dinfo
88                 = (struct ipt_dscp_info *)(*match)->data;
89
90         switch (c) {
91         case 'F':
92                 if (*flags)
93                         exit_error(PARAMETER_PROBLEM,
94                                    "DSCP match: Only use --dscp ONCE!");
95                 check_inverse(optarg, &invert, &optind, 0);
96                 parse_dscp(argv[optind-1], dinfo);
97                 if (invert)
98                         dinfo->invert = 1;
99                 *flags = 1;
100                 break;
101
102         case 'G':
103                 if (*flags)
104                         exit_error(PARAMETER_PROBLEM,
105                                         "DSCP match: Only use --dscp-class ONCE!");
106                 check_inverse(optarg, &invert, &optind, 0);
107                 parse_class(argv[optind - 1], dinfo);
108                 if (invert)
109                         dinfo->invert = 1;
110                 *flags = 1;
111                 break;
112
113         default:
114                 return 0;
115         }
116
117         return 1;
118 }
119
120 static void
121 final_check(unsigned int flags)
122 {
123         if (!flags)
124                 exit_error(PARAMETER_PROBLEM,
125                            "DSCP match: Parameter --dscp is required");
126 }
127
128 static void
129 print_dscp(u_int8_t dscp, int invert, int numeric)
130 {
131         if (invert)
132                 fputc('!', stdout);
133
134         printf("0x%02x ", dscp);
135 }
136
137 /* Prints out the matchinfo. */
138 static void
139 print(const struct ipt_ip *ip,
140       const struct ipt_entry_match *match,
141       int numeric)
142 {
143         const struct ipt_dscp_info *dinfo =
144                 (const struct ipt_dscp_info *)match->data;
145         printf("DSCP match ");
146         print_dscp(dinfo->dscp, dinfo->invert, numeric);
147 }
148
149 /* Saves the union ipt_matchinfo in parsable form to stdout. */
150 static void
151 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
152 {
153         const struct ipt_dscp_info *dinfo =
154                 (const struct ipt_dscp_info *)match->data;
155
156         printf("--dscp ");
157         print_dscp(dinfo->dscp, dinfo->invert, 1);
158 }
159
160 static
161 struct iptables_match dscp
162 = { NULL,
163     "dscp",
164     IPTABLES_VERSION,
165     IPT_ALIGN(sizeof(struct ipt_dscp_info)),
166     IPT_ALIGN(sizeof(struct ipt_dscp_info)),
167     &help,
168     &init,
169     &parse,
170     &final_check,
171     &print,
172     &save,
173     opts
174 };
175
176 void _init(void)
177 {
178         register_match(&dscp);
179 }