• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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