blob: e47b586c8175900033c50dd7601be6da120c3b7f [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 */
8#include <stdio.h>
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +00009#include <xtables.h>
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +000010#include <linux/netfilter/xt_NFQUEUE.h>
Harald Weltedaa1ef32005-07-19 21:44:58 +000011
Jan Engelhardt478be252011-03-06 17:54:50 +010012enum {
13 O_QUEUE_NUM = 0,
14 O_QUEUE_BALANCE,
15 O_QUEUE_BYPASS,
Jan Engelhardtd8784612011-05-25 00:26:01 +020016 F_QUEUE_NUM = 1 << O_QUEUE_NUM,
17 F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE,
Jan Engelhardt478be252011-03-06 17:54:50 +010018};
19
Jan Engelhardt932e6482007-10-04 16:27:30 +000020static void NFQUEUE_help(void)
Harald Weltedaa1ef32005-07-19 21:44:58 +000021{
22 printf(
23"NFQUEUE target options\n"
24" --queue-num value Send packet to QUEUE number <value>.\n"
25" Valid queue numbers are 0-65535\n"
26);
27}
28
Florian Westphal4282d892009-08-20 16:39:05 +020029static void NFQUEUE_help_v1(void)
30{
31 NFQUEUE_help();
32 printf(
33" --queue-balance first:last Balance flows between queues <value> to <value>.\n");
34}
35
Florian Westphal6924b492011-01-20 11:27:42 +010036static void NFQUEUE_help_v2(void)
37{
38 NFQUEUE_help_v1();
39 printf(
40" --queue-bypass Bypass Queueing if no queue instance exists.\n");
41}
42
Jan Engelhardt478be252011-03-06 17:54:50 +010043#define s struct xt_NFQ_info
44static const struct xt_option_entry NFQUEUE_opts[] = {
45 {.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
Jan Engelhardtd8784612011-05-25 00:26:01 +020046 .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum),
47 .excl = F_QUEUE_BALANCE},
Jan Engelhardt478be252011-03-06 17:54:50 +010048 {.name = "queue-balance", .id = O_QUEUE_BALANCE,
Jan Engelhardtd8784612011-05-25 00:26:01 +020049 .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM},
Jan Engelhardt478be252011-03-06 17:54:50 +010050 {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
51 XTOPT_TABLEEND,
Harald Weltedaa1ef32005-07-19 21:44:58 +000052};
Jan Engelhardt478be252011-03-06 17:54:50 +010053#undef s
Harald Weltedaa1ef32005-07-19 21:44:58 +000054
Jan Engelhardt478be252011-03-06 17:54:50 +010055static void NFQUEUE_parse(struct xt_option_call *cb)
Florian Westphal4282d892009-08-20 16:39:05 +020056{
Jan Engelhardt478be252011-03-06 17:54:50 +010057 xtables_option_parse(cb);
58 if (cb->entry->id == O_QUEUE_BALANCE)
Florian Westphal4282d892009-08-20 16:39:05 +020059 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
60 "--queue-balance not supported (kernel too old?)");
Florian Westphal4282d892009-08-20 16:39:05 +020061}
62
Jan Engelhardt478be252011-03-06 17:54:50 +010063static void NFQUEUE_parse_v1(struct xt_option_call *cb)
Florian Westphal4282d892009-08-20 16:39:05 +020064{
Jan Engelhardt478be252011-03-06 17:54:50 +010065 struct xt_NFQ_info_v1 *info = cb->data;
66 const uint16_t *r = cb->val.u16_range;
Florian Westphal4282d892009-08-20 16:39:05 +020067
Jan Engelhardt478be252011-03-06 17:54:50 +010068 xtables_option_parse(cb);
69 switch (cb->entry->id) {
70 case O_QUEUE_BALANCE:
71 if (cb->nvals != 2)
72 xtables_error(PARAMETER_PROBLEM,
73 "Bad range \"%s\"", cb->arg);
74 if (r[0] >= r[1])
Florian Westphal4282d892009-08-20 16:39:05 +020075 xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
Jan Engelhardt478be252011-03-06 17:54:50 +010076 r[0], r[1]);
77 info->queuenum = r[0];
78 info->queues_total = r[1] - r[0] + 1;
Florian Westphal4282d892009-08-20 16:39:05 +020079 break;
Harald Weltedaa1ef32005-07-19 21:44:58 +000080 }
Harald Weltedaa1ef32005-07-19 21:44:58 +000081}
82
Jan Engelhardt478be252011-03-06 17:54:50 +010083static void NFQUEUE_parse_v2(struct xt_option_call *cb)
Florian Westphal6924b492011-01-20 11:27:42 +010084{
Jan Engelhardt478be252011-03-06 17:54:50 +010085 struct xt_NFQ_info_v2 *info = cb->data;
86
Jan Engelhardt089585f2011-05-25 00:11:48 +020087 NFQUEUE_parse_v1(cb);
Jan Engelhardt478be252011-03-06 17:54:50 +010088 switch (cb->entry->id) {
89 case O_QUEUE_BYPASS:
Florian Westphal6924b492011-01-20 11:27:42 +010090 info->bypass = 1;
Jan Engelhardt478be252011-03-06 17:54:50 +010091 break;
Florian Westphal6924b492011-01-20 11:27:42 +010092 }
Florian Westphal6924b492011-01-20 11:27:42 +010093}
94
Jan Engelhardt932e6482007-10-04 16:27:30 +000095static void NFQUEUE_print(const void *ip,
96 const struct xt_entry_target *target, int numeric)
Harald Weltedaa1ef32005-07-19 21:44:58 +000097{
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +000098 const struct xt_NFQ_info *tinfo =
99 (const struct xt_NFQ_info *)target->data;
Jan Engelhardt73866352010-12-18 02:04:59 +0100100 printf(" NFQUEUE num %u", tinfo->queuenum);
Harald Weltedaa1ef32005-07-19 21:44:58 +0000101}
102
Florian Westphal4282d892009-08-20 16:39:05 +0200103static void NFQUEUE_print_v1(const void *ip,
104 const struct xt_entry_target *target, int numeric)
105{
106 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
107 unsigned int last = tinfo->queues_total;
108
109 if (last > 1) {
110 last += tinfo->queuenum - 1;
Jan Engelhardt73866352010-12-18 02:04:59 +0100111 printf(" NFQUEUE balance %u:%u", tinfo->queuenum, last);
Florian Westphal4282d892009-08-20 16:39:05 +0200112 } else {
Jan Engelhardt73866352010-12-18 02:04:59 +0100113 printf(" NFQUEUE num %u", tinfo->queuenum);
Florian Westphal4282d892009-08-20 16:39:05 +0200114 }
115}
116
Florian Westphal6924b492011-01-20 11:27:42 +0100117static void NFQUEUE_print_v2(const void *ip,
118 const struct xt_entry_target *target, int numeric)
119{
120 const struct xt_NFQ_info_v2 *info = (void *) target->data;
121
122 NFQUEUE_print_v1(ip, target, numeric);
123 if (info->bypass)
124 printf(" bypass");
125}
126
Jan Engelhardt932e6482007-10-04 16:27:30 +0000127static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target)
Harald Weltedaa1ef32005-07-19 21:44:58 +0000128{
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +0000129 const struct xt_NFQ_info *tinfo =
130 (const struct xt_NFQ_info *)target->data;
Harald Weltedaa1ef32005-07-19 21:44:58 +0000131
Jan Engelhardt73866352010-12-18 02:04:59 +0100132 printf(" --queue-num %u", tinfo->queuenum);
Harald Weltedaa1ef32005-07-19 21:44:58 +0000133}
134
Florian Westphal4282d892009-08-20 16:39:05 +0200135static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target)
136{
137 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
138 unsigned int last = tinfo->queues_total;
139
140 if (last > 1) {
141 last += tinfo->queuenum - 1;
Jan Engelhardt73866352010-12-18 02:04:59 +0100142 printf(" --queue-balance %u:%u", tinfo->queuenum, last);
Florian Westphal4282d892009-08-20 16:39:05 +0200143 } else {
Jan Engelhardt73866352010-12-18 02:04:59 +0100144 printf(" --queue-num %u", tinfo->queuenum);
Florian Westphal4282d892009-08-20 16:39:05 +0200145 }
146}
147
Florian Westphal6924b492011-01-20 11:27:42 +0100148static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target)
149{
150 const struct xt_NFQ_info_v2 *info = (void *) target->data;
151
152 NFQUEUE_save_v1(ip, target);
153
154 if (info->bypass)
155 printf("--queue-bypass ");
156}
157
Florian Westphal4282d892009-08-20 16:39:05 +0200158static void NFQUEUE_init_v1(struct xt_entry_target *t)
159{
160 struct xt_NFQ_info_v1 *tinfo = (void *)t->data;
161 tinfo->queues_total = 1;
162}
163
Florian Westphal6924b492011-01-20 11:27:42 +0100164static struct xtables_target nfqueue_targets[] = {
165{
Jan Engelhardtc5e85732009-06-12 20:55:44 +0200166 .family = NFPROTO_UNSPEC,
Harald Weltedaa1ef32005-07-19 21:44:58 +0000167 .name = "NFQUEUE",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200168 .version = XTABLES_VERSION,
Yasuyuki KOZAKAIa2e89cc2007-07-24 07:29:36 +0000169 .size = XT_ALIGN(sizeof(struct xt_NFQ_info)),
170 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)),
Jan Engelhardt932e6482007-10-04 16:27:30 +0000171 .help = NFQUEUE_help,
Jan Engelhardt932e6482007-10-04 16:27:30 +0000172 .print = NFQUEUE_print,
173 .save = NFQUEUE_save,
Jan Engelhardt478be252011-03-06 17:54:50 +0100174 .x6_parse = NFQUEUE_parse,
175 .x6_options = NFQUEUE_opts
Florian Westphal6924b492011-01-20 11:27:42 +0100176},{
Florian Westphal4282d892009-08-20 16:39:05 +0200177 .family = NFPROTO_UNSPEC,
178 .revision = 1,
179 .name = "NFQUEUE",
180 .version = XTABLES_VERSION,
181 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
182 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
183 .help = NFQUEUE_help_v1,
184 .init = NFQUEUE_init_v1,
Florian Westphal4282d892009-08-20 16:39:05 +0200185 .print = NFQUEUE_print_v1,
186 .save = NFQUEUE_save_v1,
Jan Engelhardt478be252011-03-06 17:54:50 +0100187 .x6_parse = NFQUEUE_parse_v1,
188 .x6_options = NFQUEUE_opts,
Florian Westphal6924b492011-01-20 11:27:42 +0100189},{
190 .family = NFPROTO_UNSPEC,
191 .revision = 2,
192 .name = "NFQUEUE",
193 .version = XTABLES_VERSION,
194 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
195 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
196 .help = NFQUEUE_help_v2,
197 .init = NFQUEUE_init_v1,
Florian Westphal6924b492011-01-20 11:27:42 +0100198 .print = NFQUEUE_print_v2,
199 .save = NFQUEUE_save_v2,
Jan Engelhardt478be252011-03-06 17:54:50 +0100200 .x6_parse = NFQUEUE_parse_v2,
201 .x6_options = NFQUEUE_opts,
Florian Westphal6924b492011-01-20 11:27:42 +0100202}
Florian Westphal4282d892009-08-20 16:39:05 +0200203};
204
Harald Weltedaa1ef32005-07-19 21:44:58 +0000205void _init(void)
206{
Florian Westphal6924b492011-01-20 11:27:42 +0100207 xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets));
Harald Weltedaa1ef32005-07-19 21:44:58 +0000208}