blob: 6c448425d12cec699150ccc68c9eaa6528a863a9 [file] [log] [blame]
Harald Weltedaa1ef32005-07-19 21:44:58 +00001/* 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 */
Jan Engelhardt32b8e612010-07-23 21:16:14 +02008#include <stdbool.h>
Harald Weltedaa1ef32005-07-19 21:44:58 +00009#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <getopt.h>
13
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +000014#include <xtables.h>
15#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter/xt_NFQUEUE.h>
Harald Weltedaa1ef32005-07-19 21:44:58 +000017
Jan Engelhardt932e6482007-10-04 16:27:30 +000018static void NFQUEUE_help(void)
Harald Weltedaa1ef32005-07-19 21:44:58 +000019{
20 printf(
21"NFQUEUE target options\n"
22" --queue-num value Send packet to QUEUE number <value>.\n"
23" Valid queue numbers are 0-65535\n"
24);
25}
26
Florian Westphal4282d892009-08-20 16:39:05 +020027static void NFQUEUE_help_v1(void)
28{
29 NFQUEUE_help();
30 printf(
31" --queue-balance first:last Balance flows between queues <value> to <value>.\n");
32}
33
Florian Westphal6924b492011-01-20 11:27:42 +010034static void NFQUEUE_help_v2(void)
35{
36 NFQUEUE_help_v1();
37 printf(
38" --queue-bypass Bypass Queueing if no queue instance exists.\n");
39}
40
Jan Engelhardt932e6482007-10-04 16:27:30 +000041static const struct option NFQUEUE_opts[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020042 {.name = "queue-num", .has_arg = true, .val = 'F'},
43 {.name = "queue-balance", .has_arg = true, .val = 'B'},
Florian Westphal6924b492011-01-20 11:27:42 +010044 {.name = "queue-bypass", .has_arg = false,.val = 'P'},
Jan Engelhardt32b8e612010-07-23 21:16:14 +020045 XT_GETOPT_TABLEEND,
Harald Weltedaa1ef32005-07-19 21:44:58 +000046};
47
Florian Westphal4282d892009-08-20 16:39:05 +020048static void exit_badqueue(const char *s)
49{
50 xtables_error(PARAMETER_PROBLEM, "Invalid queue number `%s'\n", s);
51}
52
Harald Weltedaa1ef32005-07-19 21:44:58 +000053static void
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +000054parse_num(const char *s, struct xt_NFQ_info *tinfo)
Harald Weltedaa1ef32005-07-19 21:44:58 +000055{
56 unsigned int num;
Harald Weltedaa1ef32005-07-19 21:44:58 +000057
Florian Westphal4282d892009-08-20 16:39:05 +020058 if (!xtables_strtoui(s, NULL, &num, 0, UINT16_MAX))
59 exit_badqueue(s);
60
61 tinfo->queuenum = num;
Harald Weltedaa1ef32005-07-19 21:44:58 +000062}
63
64static int
Jan Engelhardt932e6482007-10-04 16:27:30 +000065NFQUEUE_parse(int c, char **argv, int invert, unsigned int *flags,
66 const void *entry, struct xt_entry_target **target)
Harald Weltedaa1ef32005-07-19 21:44:58 +000067{
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +000068 struct xt_NFQ_info *tinfo
69 = (struct xt_NFQ_info *)(*target)->data;
Harald Weltedaa1ef32005-07-19 21:44:58 +000070
71 switch (c) {
72 case 'F':
73 if (*flags)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010074 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
Harald Weltedaa1ef32005-07-19 21:44:58 +000075 "Only use --queue-num ONCE!");
76 parse_num(optarg, tinfo);
Eric Leblond6fdefcf2005-08-05 18:35:09 +000077 break;
Florian Westphal4282d892009-08-20 16:39:05 +020078 case 'B':
79 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
80 "--queue-balance not supported (kernel too old?)");
Florian Westphal4282d892009-08-20 16:39:05 +020081 }
82
83 return 1;
84}
85
86static int
87NFQUEUE_parse_v1(int c, char **argv, int invert, unsigned int *flags,
88 const void *entry, struct xt_entry_target **target)
89{
90 struct xt_NFQ_info_v1 *info = (void *)(*target)->data;
91 char *colon;
92 unsigned int firstqueue, lastqueue;
93
94 switch (c) {
95 case 'F': /* fallthrough */
96 case 'B':
97 if (*flags)
98 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
99 "Only use --queue-num ONCE!");
100
101 if (!xtables_strtoui(optarg, &colon, &firstqueue, 0, UINT16_MAX))
102 exit_badqueue(optarg);
103
104 info->queuenum = firstqueue;
105
106 if (c == 'F') {
107 if (*colon)
108 exit_badqueue(optarg);
109 break;
110 }
111
112 if (*colon != ':')
113 xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", optarg);
114
115 if (!xtables_strtoui(colon + 1, NULL, &lastqueue, 1, UINT16_MAX))
116 exit_badqueue(optarg);
117
118 if (firstqueue >= lastqueue)
119 xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
120 firstqueue, lastqueue);
121 info->queues_total = lastqueue - firstqueue + 1;
122 break;
Harald Weltedaa1ef32005-07-19 21:44:58 +0000123 }
124
125 return 1;
126}
127
Florian Westphal6924b492011-01-20 11:27:42 +0100128static int
129NFQUEUE_parse_v2(int c, char **argv, int invert, unsigned int *flags,
130 const void *entry, struct xt_entry_target **target)
131{
132 if (c == 'P') {
133 struct xt_NFQ_info_v2 *info = (void *)(*target)->data;
134 info->bypass = 1;
135 return 1;
136 }
137 return NFQUEUE_parse_v1(c, argv, invert, flags, entry, target);
138}
139
Jan Engelhardt932e6482007-10-04 16:27:30 +0000140static void NFQUEUE_print(const void *ip,
141 const struct xt_entry_target *target, int numeric)
Harald Weltedaa1ef32005-07-19 21:44:58 +0000142{
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +0000143 const struct xt_NFQ_info *tinfo =
144 (const struct xt_NFQ_info *)target->data;
Harald Weltedaa1ef32005-07-19 21:44:58 +0000145 printf("NFQUEUE num %u", tinfo->queuenum);
146}
147
Florian Westphal4282d892009-08-20 16:39:05 +0200148static void NFQUEUE_print_v1(const void *ip,
149 const struct xt_entry_target *target, int numeric)
150{
151 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
152 unsigned int last = tinfo->queues_total;
153
154 if (last > 1) {
155 last += tinfo->queuenum - 1;
156 printf("NFQUEUE balance %u:%u", tinfo->queuenum, last);
157 } else {
158 printf("NFQUEUE num %u", tinfo->queuenum);
159 }
160}
161
Florian Westphal6924b492011-01-20 11:27:42 +0100162static void NFQUEUE_print_v2(const void *ip,
163 const struct xt_entry_target *target, int numeric)
164{
165 const struct xt_NFQ_info_v2 *info = (void *) target->data;
166
167 NFQUEUE_print_v1(ip, target, numeric);
168 if (info->bypass)
169 printf(" bypass");
170}
171
Jan Engelhardt932e6482007-10-04 16:27:30 +0000172static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target)
Harald Weltedaa1ef32005-07-19 21:44:58 +0000173{
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +0000174 const struct xt_NFQ_info *tinfo =
175 (const struct xt_NFQ_info *)target->data;
Harald Weltedaa1ef32005-07-19 21:44:58 +0000176
177 printf("--queue-num %u ", tinfo->queuenum);
178}
179
Florian Westphal4282d892009-08-20 16:39:05 +0200180static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target)
181{
182 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
183 unsigned int last = tinfo->queues_total;
184
185 if (last > 1) {
186 last += tinfo->queuenum - 1;
187 printf("--queue-balance %u:%u ", tinfo->queuenum, last);
188 } else {
189 printf("--queue-num %u ", tinfo->queuenum);
190 }
191}
192
Florian Westphal6924b492011-01-20 11:27:42 +0100193static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target)
194{
195 const struct xt_NFQ_info_v2 *info = (void *) target->data;
196
197 NFQUEUE_save_v1(ip, target);
198
199 if (info->bypass)
200 printf("--queue-bypass ");
201}
202
Florian Westphal4282d892009-08-20 16:39:05 +0200203static void NFQUEUE_init_v1(struct xt_entry_target *t)
204{
205 struct xt_NFQ_info_v1 *tinfo = (void *)t->data;
206 tinfo->queues_total = 1;
207}
208
Florian Westphal6924b492011-01-20 11:27:42 +0100209static struct xtables_target nfqueue_targets[] = {
210{
Jan Engelhardtc5e85732009-06-12 20:55:44 +0200211 .family = NFPROTO_UNSPEC,
Harald Weltedaa1ef32005-07-19 21:44:58 +0000212 .name = "NFQUEUE",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200213 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +0000214 .size = XT_ALIGN(sizeof(struct xt_NFQ_info)),
215 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)),
Jan Engelhardt932e6482007-10-04 16:27:30 +0000216 .help = NFQUEUE_help,
217 .parse = NFQUEUE_parse,
218 .print = NFQUEUE_print,
219 .save = NFQUEUE_save,
220 .extra_opts = NFQUEUE_opts
Florian Westphal6924b492011-01-20 11:27:42 +0100221},{
Florian Westphal4282d892009-08-20 16:39:05 +0200222 .family = NFPROTO_UNSPEC,
223 .revision = 1,
224 .name = "NFQUEUE",
225 .version = XTABLES_VERSION,
226 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
227 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
228 .help = NFQUEUE_help_v1,
229 .init = NFQUEUE_init_v1,
230 .parse = NFQUEUE_parse_v1,
231 .print = NFQUEUE_print_v1,
232 .save = NFQUEUE_save_v1,
233 .extra_opts = NFQUEUE_opts,
Florian Westphal6924b492011-01-20 11:27:42 +0100234},{
235 .family = NFPROTO_UNSPEC,
236 .revision = 2,
237 .name = "NFQUEUE",
238 .version = XTABLES_VERSION,
239 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
240 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
241 .help = NFQUEUE_help_v2,
242 .init = NFQUEUE_init_v1,
243 .parse = NFQUEUE_parse_v2,
244 .print = NFQUEUE_print_v2,
245 .save = NFQUEUE_save_v2,
246 .extra_opts = NFQUEUE_opts,
247}
Florian Westphal4282d892009-08-20 16:39:05 +0200248};
249
Harald Weltedaa1ef32005-07-19 21:44:58 +0000250void _init(void)
251{
Florian Westphal6924b492011-01-20 11:27:42 +0100252 xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets));
Harald Weltedaa1ef32005-07-19 21:44:58 +0000253}