4302950d615d56b58494dba2bd5e7a76d9ccd894
[iptables.git] / extensions / libipt_TOS.c
1 /* Shared library add-on to iptables to add TOS target support. */
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <getopt.h>
6
7 #include <iptables.h>
8 #include <linux/netfilter_ipv4/ip_tables.h>
9 #include <linux/netfilter_ipv4/ipt_TOS.h>
10
11 struct tosinfo {
12         struct ipt_entry_target t;
13         struct ipt_tos_target_info tos;
14 };
15
16 /* TOS names and values. */
17 static
18 struct TOS_value
19 {
20         unsigned char TOS;
21         const char *name;
22 } TOS_values[] = {
23         { IPTOS_LOWDELAY,    "Minimize-Delay" },
24         { IPTOS_THROUGHPUT,  "Maximize-Throughput" },
25         { IPTOS_RELIABILITY, "Maximize-Reliability" },
26         { IPTOS_MINCOST,     "Minimize-Cost" },
27         { IPTOS_NORMALSVC,   "Normal-Service" },
28 };
29
30 /* Function which prints out usage message. */
31 static void
32 help(void)
33 {
34         unsigned int i;
35
36         printf(
37 "TOS target v%s options:\n"
38 "  --set-tos value                   Set Type of Service field to one of the\n"
39 "                                following numeric or descriptive values:\n",
40 IPTABLES_VERSION);
41
42         for (i = 0; i < sizeof(TOS_values)/sizeof(struct TOS_value);i++)
43                 printf("                                     %s %u (0x%02x)\n",
44                        TOS_values[i].name,
45                        TOS_values[i].TOS,
46                        TOS_values[i].TOS);
47         fputc('\n', stdout);
48 }
49
50 static struct option opts[] = {
51         { "set-tos", 1, 0, '1' },
52         { 0 }
53 };
54
55 /* Initialize the target. */
56 static void
57 init(struct ipt_entry_target *t, unsigned int *nfcache)
58 {
59 }
60
61 static void
62 parse_tos(const unsigned char *s, struct ipt_tos_target_info *info)
63 {
64         unsigned int i, tos;
65
66         if (string_to_number(s, 0, 255, &tos) != -1) {
67                 if (tos == IPTOS_LOWDELAY
68                     || tos == IPTOS_THROUGHPUT
69                     || tos == IPTOS_RELIABILITY
70                     || tos == IPTOS_MINCOST
71                     || tos == IPTOS_NORMALSVC) {
72                         info->tos = (u_int8_t )tos;
73                         return;
74                 }
75         } else {
76                 for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
77                         if (strcasecmp(s,TOS_values[i].name) == 0) {
78                                 info->tos = TOS_values[i].TOS;
79                                 return;
80                         }
81         }
82         exit_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s);
83 }
84
85 /* Function which parses command options; returns true if it
86    ate an option */
87 static int
88 parse(int c, char **argv, int invert, unsigned int *flags,
89       const struct ipt_entry *entry,
90       struct ipt_entry_target **target)
91 {
92         struct ipt_tos_target_info *tosinfo
93                 = (struct ipt_tos_target_info *)(*target)->data;
94
95         switch (c) {
96         case '1':
97                 if (*flags)
98                         exit_error(PARAMETER_PROBLEM,
99                                    "TOS target: Cant specify --set-tos twice");
100                 parse_tos(optarg, tosinfo);
101                 *flags = 1;
102                 break;
103
104         default:
105                 return 0;
106         }
107
108         return 1;
109 }
110
111 static void
112 final_check(unsigned int flags)
113 {
114         if (!flags)
115                 exit_error(PARAMETER_PROBLEM,
116                            "TOS target: Parameter --set-tos is required");
117 }
118
119 static void
120 print_tos(u_int8_t tos, int numeric)
121 {
122         unsigned int i;
123
124         if (!numeric) {
125                 for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
126                         if (TOS_values[i].TOS == tos) {
127                                 printf("%s ", TOS_values[i].name);
128                                 return;
129                         }
130         }
131         printf("0x%02x ", tos);
132 }
133
134 /* Prints out the targinfo. */
135 static void
136 print(const struct ipt_ip *ip,
137       const struct ipt_entry_target *target,
138       int numeric)
139 {
140         const struct ipt_tos_target_info *tosinfo =
141                 (const struct ipt_tos_target_info *)target->data;
142         printf("TOS set ");
143         print_tos(tosinfo->tos, numeric);
144 }
145
146 /* Saves the union ipt_targinfo in parsable form to stdout. */
147 static void
148 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
149 {
150         const struct ipt_tos_target_info *tosinfo =
151                 (const struct ipt_tos_target_info *)target->data;
152
153         printf("--set-tos 0x%02x ", tosinfo->tos);
154 }
155
156 static struct iptables_target tos = {
157         .next           = NULL,
158         .name           = "TOS",
159         .version        = IPTABLES_VERSION,
160         .size           = IPT_ALIGN(sizeof(struct ipt_tos_target_info)),
161         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_tos_target_info)),
162         .help           = &help,
163         .init           = &init,
164         .parse          = &parse,
165         .final_check    = &final_check,
166         .print          = &print,
167         .save           = &save,
168         .extra_opts     = opts
169 };
170
171 void _init(void)
172 {
173         register_target(&tos);
174 }