Home | History | Annotate | Download | only in extensions
      1 /* Shared library add-on to iptables for NFQ
      2  *
      3  * (C) 2005 by Harald Welte <laforge (at) 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 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    262 void _init(void)
    263 {
    264 	xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets));
    265 }
    266