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