libxt_NFQUEUE.c revision 089585f14fda80508e26ea019703add07cb72f64
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 12enum { 13 O_QUEUE_NUM = 0, 14 O_QUEUE_BALANCE, 15 O_QUEUE_BYPASS, 16}; 17 18static void NFQUEUE_help(void) 19{ 20 printf( 21"NFQUEUE target options\n" 22" --queue-num value Send packet to QUEUE number <value>.\n" 23" Valid queue numbers are 0-65535\n" 24); 25} 26 27static void NFQUEUE_help_v1(void) 28{ 29 NFQUEUE_help(); 30 printf( 31" --queue-balance first:last Balance flows between queues <value> to <value>.\n"); 32} 33 34static void NFQUEUE_help_v2(void) 35{ 36 NFQUEUE_help_v1(); 37 printf( 38" --queue-bypass Bypass Queueing if no queue instance exists.\n"); 39} 40 41#define s struct xt_NFQ_info 42static const struct xt_option_entry NFQUEUE_opts[] = { 43 {.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16, 44 .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum)}, 45 {.name = "queue-balance", .id = O_QUEUE_BALANCE, 46 .type = XTTYPE_UINT16RC}, 47 {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE}, 48 XTOPT_TABLEEND, 49}; 50#undef s 51 52static void NFQUEUE_parse(struct xt_option_call *cb) 53{ 54 xtables_option_parse(cb); 55 if (cb->entry->id == O_QUEUE_BALANCE) 56 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " 57 "--queue-balance not supported (kernel too old?)"); 58} 59 60static void NFQUEUE_parse_v1(struct xt_option_call *cb) 61{ 62 struct xt_NFQ_info_v1 *info = cb->data; 63 const uint16_t *r = cb->val.u16_range; 64 65 xtables_option_parse(cb); 66 switch (cb->entry->id) { 67 case O_QUEUE_BALANCE: 68 if (cb->nvals != 2) 69 xtables_error(PARAMETER_PROBLEM, 70 "Bad range \"%s\"", cb->arg); 71 if (r[0] >= r[1]) 72 xtables_error(PARAMETER_PROBLEM, "%u should be less than %u", 73 r[0], r[1]); 74 info->queuenum = r[0]; 75 info->queues_total = r[1] - r[0] + 1; 76 break; 77 } 78} 79 80static void NFQUEUE_parse_v2(struct xt_option_call *cb) 81{ 82 struct xt_NFQ_info_v2 *info = cb->data; 83 84 NFQUEUE_parse_v1(cb); 85 switch (cb->entry->id) { 86 case O_QUEUE_BYPASS: 87 info->bypass = 1; 88 break; 89 } 90} 91 92static void NFQUEUE_print(const void *ip, 93 const struct xt_entry_target *target, int numeric) 94{ 95 const struct xt_NFQ_info *tinfo = 96 (const struct xt_NFQ_info *)target->data; 97 printf(" NFQUEUE num %u", tinfo->queuenum); 98} 99 100static void NFQUEUE_print_v1(const void *ip, 101 const struct xt_entry_target *target, int numeric) 102{ 103 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data; 104 unsigned int last = tinfo->queues_total; 105 106 if (last > 1) { 107 last += tinfo->queuenum - 1; 108 printf(" NFQUEUE balance %u:%u", tinfo->queuenum, last); 109 } else { 110 printf(" NFQUEUE num %u", tinfo->queuenum); 111 } 112} 113 114static void NFQUEUE_print_v2(const void *ip, 115 const struct xt_entry_target *target, int numeric) 116{ 117 const struct xt_NFQ_info_v2 *info = (void *) target->data; 118 119 NFQUEUE_print_v1(ip, target, numeric); 120 if (info->bypass) 121 printf(" bypass"); 122} 123 124static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target) 125{ 126 const struct xt_NFQ_info *tinfo = 127 (const struct xt_NFQ_info *)target->data; 128 129 printf(" --queue-num %u", tinfo->queuenum); 130} 131 132static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target) 133{ 134 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data; 135 unsigned int last = tinfo->queues_total; 136 137 if (last > 1) { 138 last += tinfo->queuenum - 1; 139 printf(" --queue-balance %u:%u", tinfo->queuenum, last); 140 } else { 141 printf(" --queue-num %u", tinfo->queuenum); 142 } 143} 144 145static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target) 146{ 147 const struct xt_NFQ_info_v2 *info = (void *) target->data; 148 149 NFQUEUE_save_v1(ip, target); 150 151 if (info->bypass) 152 printf("--queue-bypass "); 153} 154 155static void NFQUEUE_init_v1(struct xt_entry_target *t) 156{ 157 struct xt_NFQ_info_v1 *tinfo = (void *)t->data; 158 tinfo->queues_total = 1; 159} 160 161static struct xtables_target nfqueue_targets[] = { 162{ 163 .family = NFPROTO_UNSPEC, 164 .name = "NFQUEUE", 165 .version = XTABLES_VERSION, 166 .size = XT_ALIGN(sizeof(struct xt_NFQ_info)), 167 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)), 168 .help = NFQUEUE_help, 169 .print = NFQUEUE_print, 170 .save = NFQUEUE_save, 171 .x6_parse = NFQUEUE_parse, 172 .x6_options = NFQUEUE_opts 173},{ 174 .family = NFPROTO_UNSPEC, 175 .revision = 1, 176 .name = "NFQUEUE", 177 .version = XTABLES_VERSION, 178 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)), 179 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)), 180 .help = NFQUEUE_help_v1, 181 .init = NFQUEUE_init_v1, 182 .print = NFQUEUE_print_v1, 183 .save = NFQUEUE_save_v1, 184 .x6_parse = NFQUEUE_parse_v1, 185 .x6_options = NFQUEUE_opts, 186},{ 187 .family = NFPROTO_UNSPEC, 188 .revision = 2, 189 .name = "NFQUEUE", 190 .version = XTABLES_VERSION, 191 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)), 192 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)), 193 .help = NFQUEUE_help_v2, 194 .init = NFQUEUE_init_v1, 195 .print = NFQUEUE_print_v2, 196 .save = NFQUEUE_save_v2, 197 .x6_parse = NFQUEUE_parse_v2, 198 .x6_options = NFQUEUE_opts, 199} 200}; 201 202void _init(void) 203{ 204 xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets)); 205} 206