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 F_QUEUE_NUM = 1 << O_QUEUE_NUM,
17 F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE,
18 };
19
NFQUEUE_help(void)20 static void NFQUEUE_help(void)
21 {
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
NFQUEUE_help_v1(void)29 static 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
NFQUEUE_help_v2(void)36 static 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
43 #define s struct xt_NFQ_info
44 static const struct xt_option_entry NFQUEUE_opts[] = {
45 {.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
46 .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum),
47 .excl = F_QUEUE_BALANCE},
48 {.name = "queue-balance", .id = O_QUEUE_BALANCE,
49 .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM},
50 {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
51 XTOPT_TABLEEND,
52 };
53 #undef s
54
NFQUEUE_parse(struct xt_option_call * cb)55 static void NFQUEUE_parse(struct xt_option_call *cb)
56 {
57 xtables_option_parse(cb);
58 if (cb->entry->id == O_QUEUE_BALANCE)
59 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
60 "--queue-balance not supported (kernel too old?)");
61 }
62
NFQUEUE_parse_v1(struct xt_option_call * cb)63 static void NFQUEUE_parse_v1(struct xt_option_call *cb)
64 {
65 struct xt_NFQ_info_v1 *info = cb->data;
66 const uint16_t *r = cb->val.u16_range;
67
68 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])
75 xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
76 r[0], r[1]);
77 info->queuenum = r[0];
78 info->queues_total = r[1] - r[0] + 1;
79 break;
80 }
81 }
82
NFQUEUE_parse_v2(struct xt_option_call * cb)83 static void NFQUEUE_parse_v2(struct xt_option_call *cb)
84 {
85 struct xt_NFQ_info_v2 *info = cb->data;
86
87 NFQUEUE_parse_v1(cb);
88 switch (cb->entry->id) {
89 case O_QUEUE_BYPASS:
90 info->bypass = 1;
91 break;
92 }
93 }
94
NFQUEUE_print(const void * ip,const struct xt_entry_target * target,int numeric)95 static void NFQUEUE_print(const void *ip,
96 const struct xt_entry_target *target, int numeric)
97 {
98 const struct xt_NFQ_info *tinfo =
99 (const struct xt_NFQ_info *)target->data;
100 printf(" NFQUEUE num %u", tinfo->queuenum);
101 }
102
NFQUEUE_print_v1(const void * ip,const struct xt_entry_target * target,int numeric)103 static 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;
111 printf(" NFQUEUE balance %u:%u", tinfo->queuenum, last);
112 } else {
113 printf(" NFQUEUE num %u", tinfo->queuenum);
114 }
115 }
116
NFQUEUE_print_v2(const void * ip,const struct xt_entry_target * target,int numeric)117 static 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
NFQUEUE_save(const void * ip,const struct xt_entry_target * target)127 static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target)
128 {
129 const struct xt_NFQ_info *tinfo =
130 (const struct xt_NFQ_info *)target->data;
131
132 printf(" --queue-num %u", tinfo->queuenum);
133 }
134
NFQUEUE_save_v1(const void * ip,const struct xt_entry_target * target)135 static 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;
142 printf(" --queue-balance %u:%u", tinfo->queuenum, last);
143 } else {
144 printf(" --queue-num %u", tinfo->queuenum);
145 }
146 }
147
NFQUEUE_save_v2(const void * ip,const struct xt_entry_target * target)148 static 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
NFQUEUE_init_v1(struct xt_entry_target * t)158 static 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
164 static struct xtables_target nfqueue_targets[] = {
165 {
166 .family = NFPROTO_UNSPEC,
167 .name = "NFQUEUE",
168 .version = XTABLES_VERSION,
169 .size = XT_ALIGN(sizeof(struct xt_NFQ_info)),
170 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)),
171 .help = NFQUEUE_help,
172 .print = NFQUEUE_print,
173 .save = NFQUEUE_save,
174 .x6_parse = NFQUEUE_parse,
175 .x6_options = NFQUEUE_opts
176 },{
177 .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,
185 .print = NFQUEUE_print_v1,
186 .save = NFQUEUE_save_v1,
187 .x6_parse = NFQUEUE_parse_v1,
188 .x6_options = NFQUEUE_opts,
189 },{
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,
198 .print = NFQUEUE_print_v2,
199 .save = NFQUEUE_save_v2,
200 .x6_parse = NFQUEUE_parse_v2,
201 .x6_options = NFQUEUE_opts,
202 }
203 };
204
_init(void)205 void _init(void)
206 {
207 xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets));
208 }
209