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 <xtables.h>
10 #include <linux/netfilter/xt_NFQUEUE.h>
11
12 enum {
13 O_QUEUE_NUM = 0,
14 O_QUEUE_BALANCE,
15 O_QUEUE_BYPASS,
16 O_QUEUE_CPU_FANOUT,
17 F_QUEUE_NUM = 1 << O_QUEUE_NUM,
18 F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE,
19 F_QUEUE_CPU_FANOUT = 1 << O_QUEUE_CPU_FANOUT,
20 };
21
NFQUEUE_help(void)22 static void NFQUEUE_help(void)
23 {
24 printf(
25 "NFQUEUE target options\n"
26 " --queue-num value Send packet to QUEUE number <value>.\n"
27 " Valid queue numbers are 0-65535\n"
28 );
29 }
30
NFQUEUE_help_v1(void)31 static void NFQUEUE_help_v1(void)
32 {
33 NFQUEUE_help();
34 printf(
35 " --queue-balance first:last Balance flows between queues <value> to <value>.\n");
36 }
37
NFQUEUE_help_v2(void)38 static void NFQUEUE_help_v2(void)
39 {
40 NFQUEUE_help_v1();
41 printf(
42 " --queue-bypass Bypass Queueing if no queue instance exists.\n"
43 " --queue-cpu-fanout Use current CPU (no hashing)\n");
44 }
45
NFQUEUE_help_v3(void)46 static void NFQUEUE_help_v3(void)
47 {
48 NFQUEUE_help_v2();
49 printf(
50 " --queue-cpu-fanout Use current CPU (no hashing)\n");
51 }
52
53 #define s struct xt_NFQ_info
54 static const struct xt_option_entry NFQUEUE_opts[] = {
55 {.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
56 .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum),
57 .excl = F_QUEUE_BALANCE},
58 {.name = "queue-balance", .id = O_QUEUE_BALANCE,
59 .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM},
60 {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
61 {.name = "queue-cpu-fanout", .id = O_QUEUE_CPU_FANOUT,
62 .type = XTTYPE_NONE, .also = F_QUEUE_BALANCE},
63 XTOPT_TABLEEND,
64 };
65 #undef s
66
NFQUEUE_parse(struct xt_option_call * cb)67 static void NFQUEUE_parse(struct xt_option_call *cb)
68 {
69 xtables_option_parse(cb);
70 if (cb->entry->id == O_QUEUE_BALANCE)
71 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
72 "--queue-balance not supported (kernel too old?)");
73 }
74
NFQUEUE_parse_v1(struct xt_option_call * cb)75 static void NFQUEUE_parse_v1(struct xt_option_call *cb)
76 {
77 struct xt_NFQ_info_v1 *info = cb->data;
78 const uint16_t *r = cb->val.u16_range;
79
80 xtables_option_parse(cb);
81 switch (cb->entry->id) {
82 case O_QUEUE_BALANCE:
83 if (cb->nvals != 2)
84 xtables_error(PARAMETER_PROBLEM,
85 "Bad range \"%s\"", cb->arg);
86 if (r[0] >= r[1])
87 xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
88 r[0], r[1]);
89 info->queuenum = r[0];
90 info->queues_total = r[1] - r[0] + 1;
91 break;
92 }
93 }
94
NFQUEUE_parse_v2(struct xt_option_call * cb)95 static void NFQUEUE_parse_v2(struct xt_option_call *cb)
96 {
97 struct xt_NFQ_info_v2 *info = cb->data;
98
99 NFQUEUE_parse_v1(cb);
100 switch (cb->entry->id) {
101 case O_QUEUE_BYPASS:
102 info->bypass = 1;
103 break;
104 }
105 }
106
NFQUEUE_parse_v3(struct xt_option_call * cb)107 static void NFQUEUE_parse_v3(struct xt_option_call *cb)
108 {
109 struct xt_NFQ_info_v3 *info = cb->data;
110
111 NFQUEUE_parse_v2(cb);
112 switch (cb->entry->id) {
113 case O_QUEUE_CPU_FANOUT:
114 info->flags |= NFQ_FLAG_CPU_FANOUT;
115 break;
116 }
117 }
118
NFQUEUE_print(const void * ip,const struct xt_entry_target * target,int numeric)119 static void NFQUEUE_print(const void *ip,
120 const struct xt_entry_target *target, int numeric)
121 {
122 const struct xt_NFQ_info *tinfo =
123 (const struct xt_NFQ_info *)target->data;
124 printf(" NFQUEUE num %u", tinfo->queuenum);
125 }
126
NFQUEUE_print_v1(const void * ip,const struct xt_entry_target * target,int numeric)127 static void NFQUEUE_print_v1(const void *ip,
128 const struct xt_entry_target *target, int numeric)
129 {
130 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
131 unsigned int last = tinfo->queues_total;
132
133 if (last > 1) {
134 last += tinfo->queuenum - 1;
135 printf(" NFQUEUE balance %u:%u", tinfo->queuenum, last);
136 } else {
137 printf(" NFQUEUE num %u", tinfo->queuenum);
138 }
139 }
140
NFQUEUE_print_v2(const void * ip,const struct xt_entry_target * target,int numeric)141 static void NFQUEUE_print_v2(const void *ip,
142 const struct xt_entry_target *target, int numeric)
143 {
144 const struct xt_NFQ_info_v2 *info = (void *) target->data;
145
146 NFQUEUE_print_v1(ip, target, numeric);
147 if (info->bypass & NFQ_FLAG_BYPASS)
148 printf(" bypass");
149 }
150
NFQUEUE_print_v3(const void * ip,const struct xt_entry_target * target,int numeric)151 static void NFQUEUE_print_v3(const void *ip,
152 const struct xt_entry_target *target, int numeric)
153 {
154 const struct xt_NFQ_info_v3 *info = (void *)target->data;
155
156 NFQUEUE_print_v2(ip, target, numeric);
157 if (info->flags & NFQ_FLAG_CPU_FANOUT)
158 printf(" cpu-fanout");
159 }
160
NFQUEUE_save(const void * ip,const struct xt_entry_target * target)161 static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target)
162 {
163 const struct xt_NFQ_info *tinfo =
164 (const struct xt_NFQ_info *)target->data;
165
166 printf(" --queue-num %u", tinfo->queuenum);
167 }
168
NFQUEUE_save_v1(const void * ip,const struct xt_entry_target * target)169 static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target)
170 {
171 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
172 unsigned int last = tinfo->queues_total;
173
174 if (last > 1) {
175 last += tinfo->queuenum - 1;
176 printf(" --queue-balance %u:%u", tinfo->queuenum, last);
177 } else {
178 printf(" --queue-num %u", tinfo->queuenum);
179 }
180 }
181
NFQUEUE_save_v2(const void * ip,const struct xt_entry_target * target)182 static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target)
183 {
184 const struct xt_NFQ_info_v2 *info = (void *) target->data;
185
186 NFQUEUE_save_v1(ip, target);
187
188 if (info->bypass & NFQ_FLAG_BYPASS)
189 printf(" --queue-bypass");
190 }
191
NFQUEUE_save_v3(const void * ip,const struct xt_entry_target * target)192 static void NFQUEUE_save_v3(const void *ip,
193 const struct xt_entry_target *target)
194 {
195 const struct xt_NFQ_info_v3 *info = (void *)target->data;
196
197 NFQUEUE_save_v2(ip, target);
198 if (info->flags & NFQ_FLAG_CPU_FANOUT)
199 printf(" --queue-cpu-fanout");
200 }
201
NFQUEUE_init_v1(struct xt_entry_target * t)202 static void NFQUEUE_init_v1(struct xt_entry_target *t)
203 {
204 struct xt_NFQ_info_v1 *tinfo = (void *)t->data;
205 tinfo->queues_total = 1;
206 }
207
208 static struct xtables_target nfqueue_targets[] = {
209 {
210 .family = NFPROTO_UNSPEC,
211 .name = "NFQUEUE",
212 .version = XTABLES_VERSION,
213 .size = XT_ALIGN(sizeof(struct xt_NFQ_info)),
214 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)),
215 .help = NFQUEUE_help,
216 .print = NFQUEUE_print,
217 .save = NFQUEUE_save,
218 .x6_parse = NFQUEUE_parse,
219 .x6_options = NFQUEUE_opts
220 },{
221 .family = NFPROTO_UNSPEC,
222 .revision = 1,
223 .name = "NFQUEUE",
224 .version = XTABLES_VERSION,
225 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
226 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
227 .help = NFQUEUE_help_v1,
228 .init = NFQUEUE_init_v1,
229 .print = NFQUEUE_print_v1,
230 .save = NFQUEUE_save_v1,
231 .x6_parse = NFQUEUE_parse_v1,
232 .x6_options = NFQUEUE_opts,
233 },{
234 .family = NFPROTO_UNSPEC,
235 .revision = 2,
236 .name = "NFQUEUE",
237 .version = XTABLES_VERSION,
238 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
239 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
240 .help = NFQUEUE_help_v2,
241 .init = NFQUEUE_init_v1,
242 .print = NFQUEUE_print_v2,
243 .save = NFQUEUE_save_v2,
244 .x6_parse = NFQUEUE_parse_v2,
245 .x6_options = NFQUEUE_opts,
246 },{
247 .family = NFPROTO_UNSPEC,
248 .revision = 3,
249 .name = "NFQUEUE",
250 .version = XTABLES_VERSION,
251 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)),
252 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)),
253 .help = NFQUEUE_help_v3,
254 .init = NFQUEUE_init_v1,
255 .print = NFQUEUE_print_v3,
256 .save = NFQUEUE_save_v3,
257 .x6_parse = NFQUEUE_parse_v3,
258 .x6_options = NFQUEUE_opts,
259 }
260 };
261
_init(void)262 void _init(void)
263 {
264 xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets));
265 }
266