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 	F_QUEUE_NUM     = 1 << O_QUEUE_NUM,
     17 	F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE,
     18 };
     19 
     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 
     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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    205 void _init(void)
    206 {
    207 	xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets));
    208 }
    209