fix for f12, gcc4.4
[iptables.git] / extensions / libipt_CLASSIFY.c
1 /* Shared library add-on to iptables to add CLASSIFY 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_CLASSIFY.h>
10 #include <linux/types.h>
11 #include <linux/pkt_sched.h>
12
13 /* Function which prints out usage message. */
14 static void
15 help(void)
16 {
17         printf(
18 "CLASSIFY target v%s options:\n"
19 "  --set-class [MAJOR:MINOR]    Set skb->priority value\n"
20 "  --add-mark                   Add value of skb->mark to skb->priority (PlanetLab specific)\n"
21 "\n",
22 IPTABLES_VERSION);
23 }
24
25 static struct option opts[] = {
26         { "set-class", 1, 0, '1' },
27         { "add-mark", 0, 0, '2' },
28         { 0 }
29 };
30
31 /* Initialize the target. */
32 static void
33 init(struct ipt_entry_target *t, unsigned int *nfcache)
34 {
35 }
36
37 int string_to_priority(const char *s, unsigned int *p)
38 {
39         unsigned int i, j;
40
41         if (sscanf(s, "%x:%x", &i, &j) != 2)
42                 return 1;
43         
44         *p = TC_H_MAKE(i<<16, j);
45         return 0;
46 }
47
48 /* Function which parses command options; returns true if it
49    ate an option */
50 static int
51 parse(int c, char **argv, int invert, unsigned int *flags,
52       const struct ipt_entry *entry,
53       struct ipt_entry_target **target)
54 {
55         struct ipt_classify_target_info *clinfo
56                 = (struct ipt_classify_target_info *)(*target)->data;
57
58         clinfo->add_mark = 0;
59
60         switch (c) {
61         case '1':
62                 if (string_to_priority(optarg, &clinfo->priority))
63                         exit_error(PARAMETER_PROBLEM,
64                                    "Bad class value `%s'", optarg);
65                 if (*flags)
66                         exit_error(PARAMETER_PROBLEM,
67                                    "CLASSIFY: Can't specify --set-class twice");
68                 *flags = 1;
69                 break;
70
71         case '2':
72                 clinfo->add_mark = 1;
73                 break;
74
75         default:
76                 return 0;
77         }
78
79         return 1;
80 }
81
82 static void
83 final_check(unsigned int flags)
84 {
85         if (!flags)
86                 exit_error(PARAMETER_PROBLEM,
87                            "CLASSIFY: Parameter --set-class is required");
88 }
89
90 static void
91 print_class(unsigned int priority, int numeric)
92 {
93         printf("%x:%x ", TC_H_MAJ(priority)>>16, TC_H_MIN(priority));
94 }
95
96 /* Prints out the targinfo. */
97 static void
98 print(const struct ipt_ip *ip,
99       const struct ipt_entry_target *target,
100       int numeric)
101 {
102         const struct ipt_classify_target_info *clinfo =
103                 (const struct ipt_classify_target_info *)target->data;
104         printf("CLASSIFY set ");
105         print_class(clinfo->priority, numeric);
106         if (clinfo->add_mark)
107                printf ("add-mark ");
108 }
109
110 /* Saves the union ipt_targinfo in parsable form to stdout. */
111 static void
112 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
113 {
114         const struct ipt_classify_target_info *clinfo =
115                 (const struct ipt_classify_target_info *)target->data;
116
117         printf("--set-class %.4x:%.4x ",
118                TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
119
120         if (clinfo->add_mark)
121                printf("--add-mark ");
122 }
123
124 static struct iptables_target classify = { 
125         .next           = NULL,
126         .name           = "CLASSIFY",
127         .version        = IPTABLES_VERSION,
128         .size           = IPT_ALIGN(sizeof(struct ipt_classify_target_info)),
129         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_classify_target_info)),
130         .help           = &help,
131         .init           = &init,
132         .parse          = &parse,
133         .final_check    = &final_check,
134         .print          = &print,
135         .save           = &save,
136         .extra_opts     = opts
137 };
138
139 void _init(void)
140 {
141         register_target(&classify);
142 }