Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libxt_NFQUEUE.c
1 /* Shared library add-on to iptables for NFQ
2  *
3  * (C) 2005 by Harald Welte <laforge@netfilter.org>
4  *
5  * This program is distributed under the terms of GNU GPL v2, 1991
6  *
7  */
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <getopt.h>
12
13 #include <xtables.h>
14 #include <linux/netfilter/x_tables.h>
15 #include <linux/netfilter/xt_NFQUEUE.h>
16
17 static void NFQUEUE_help(void)
18 {
19         printf(
20 "NFQUEUE target options\n"
21 "  --queue-num value            Send packet to QUEUE number <value>.\n"
22 "                               Valid queue numbers are 0-65535\n"
23 );
24 }
25
26 static void NFQUEUE_help_v1(void)
27 {
28         NFQUEUE_help();
29         printf(
30 "  --queue-balance first:last   Balance flows between queues <value> to <value>.\n");
31 }
32
33 static const struct option NFQUEUE_opts[] = {
34         { "queue-num", 1, NULL, 'F' },
35         { "queue-balance", 1, NULL, 'B' },
36         { .name = NULL }
37 };
38
39 static void exit_badqueue(const char *s)
40 {
41         xtables_error(PARAMETER_PROBLEM, "Invalid queue number `%s'\n", s);
42 }
43
44 static void
45 parse_num(const char *s, struct xt_NFQ_info *tinfo)
46 {
47         unsigned int num;
48
49         if (!xtables_strtoui(s, NULL, &num, 0, UINT16_MAX))
50                 exit_badqueue(s);
51
52         tinfo->queuenum = num;
53 }
54
55 static int
56 NFQUEUE_parse(int c, char **argv, int invert, unsigned int *flags,
57               const void *entry, struct xt_entry_target **target)
58 {
59         struct xt_NFQ_info *tinfo
60                 = (struct xt_NFQ_info *)(*target)->data;
61
62         switch (c) {
63         case 'F':
64                 if (*flags)
65                         xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
66                                    "Only use --queue-num ONCE!");
67                 parse_num(optarg, tinfo);
68                 break;
69         case 'B':
70                 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
71                                    "--queue-balance not supported (kernel too old?)");
72         default:
73                 return 0;
74         }
75
76         return 1;
77 }
78
79 static int
80 NFQUEUE_parse_v1(int c, char **argv, int invert, unsigned int *flags,
81                  const void *entry, struct xt_entry_target **target)
82 {
83         struct xt_NFQ_info_v1 *info = (void *)(*target)->data;
84         char *colon;
85         unsigned int firstqueue, lastqueue;
86
87         switch (c) {
88         case 'F': /* fallthrough */
89         case 'B':
90                 if (*flags)
91                         xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
92                                    "Only use --queue-num ONCE!");
93
94                 if (!xtables_strtoui(optarg, &colon, &firstqueue, 0, UINT16_MAX))
95                         exit_badqueue(optarg);
96
97                 info->queuenum = firstqueue;
98
99                 if (c == 'F') {
100                         if (*colon)
101                                 exit_badqueue(optarg);
102                         break;
103                 }
104
105                 if (*colon != ':')
106                         xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", optarg);
107
108                 if (!xtables_strtoui(colon + 1, NULL, &lastqueue, 1, UINT16_MAX))
109                         exit_badqueue(optarg);
110
111                 if (firstqueue >= lastqueue)
112                         xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
113                                                         firstqueue, lastqueue);
114                 info->queues_total = lastqueue - firstqueue + 1;
115                 break;
116         default:
117                 return 0;
118         }
119
120         return 1;
121 }
122
123 static void NFQUEUE_print(const void *ip,
124                           const struct xt_entry_target *target, int numeric)
125 {
126         const struct xt_NFQ_info *tinfo =
127                 (const struct xt_NFQ_info *)target->data;
128         printf("NFQUEUE num %u", tinfo->queuenum);
129 }
130
131 static void NFQUEUE_print_v1(const void *ip,
132                              const struct xt_entry_target *target, int numeric)
133 {
134         const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
135         unsigned int last = tinfo->queues_total;
136
137         if (last > 1) {
138                 last += tinfo->queuenum - 1;
139                 printf("NFQUEUE balance %u:%u", tinfo->queuenum, last);
140         } else {
141                 printf("NFQUEUE num %u", tinfo->queuenum);
142         }
143 }
144
145 static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target)
146 {
147         const struct xt_NFQ_info *tinfo =
148                 (const struct xt_NFQ_info *)target->data;
149
150         printf("--queue-num %u ", tinfo->queuenum);
151 }
152
153 static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target)
154 {
155         const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
156         unsigned int last = tinfo->queues_total;
157
158         if (last > 1) {
159                 last += tinfo->queuenum - 1;
160                 printf("--queue-balance %u:%u ", tinfo->queuenum, last);
161         } else {
162                 printf("--queue-num %u ", tinfo->queuenum);
163         }
164 }
165
166 static void NFQUEUE_init_v1(struct xt_entry_target *t)
167 {
168         struct xt_NFQ_info_v1 *tinfo = (void *)t->data;
169         tinfo->queues_total = 1;
170 }
171
172 static struct xtables_target nfqueue_target = {
173         .family         = NFPROTO_UNSPEC,
174         .name           = "NFQUEUE",
175         .version        = XTABLES_VERSION,
176         .size           = XT_ALIGN(sizeof(struct xt_NFQ_info)),
177         .userspacesize  = XT_ALIGN(sizeof(struct xt_NFQ_info)),
178         .help           = NFQUEUE_help,
179         .parse          = NFQUEUE_parse,
180         .print          = NFQUEUE_print,
181         .save           = NFQUEUE_save,
182         .extra_opts     = NFQUEUE_opts
183 };
184
185 static struct xtables_target nfqueue_target_v1 = {
186         .family         = NFPROTO_UNSPEC,
187         .revision       = 1,
188         .name           = "NFQUEUE",
189         .version        = XTABLES_VERSION,
190         .size           = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
191         .userspacesize  = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
192         .help           = NFQUEUE_help_v1,
193         .init           = NFQUEUE_init_v1,
194         .parse          = NFQUEUE_parse_v1,
195         .print          = NFQUEUE_print_v1,
196         .save           = NFQUEUE_save_v1,
197         .extra_opts     = NFQUEUE_opts,
198 };
199
200 void _init(void)
201 {
202         xtables_register_target(&nfqueue_target);
203         xtables_register_target(&nfqueue_target_v1);
204 }