libxt_NFQUEUE.c revision 6924b4987d88fbe383bec4da4cf331cc466c245e
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 <stdbool.h> 9#include <stdio.h> 10#include <string.h> 11#include <stdlib.h> 12#include <getopt.h> 13 14#include <xtables.h> 15#include <linux/netfilter/x_tables.h> 16#include <linux/netfilter/xt_NFQUEUE.h> 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 41static const struct option NFQUEUE_opts[] = { 42 {.name = "queue-num", .has_arg = true, .val = 'F'}, 43 {.name = "queue-balance", .has_arg = true, .val = 'B'}, 44 {.name = "queue-bypass", .has_arg = false,.val = 'P'}, 45 XT_GETOPT_TABLEEND, 46}; 47 48static void exit_badqueue(const char *s) 49{ 50 xtables_error(PARAMETER_PROBLEM, "Invalid queue number `%s'\n", s); 51} 52 53static void 54parse_num(const char *s, struct xt_NFQ_info *tinfo) 55{ 56 unsigned int num; 57 58 if (!xtables_strtoui(s, NULL, &num, 0, UINT16_MAX)) 59 exit_badqueue(s); 60 61 tinfo->queuenum = num; 62} 63 64static int 65NFQUEUE_parse(int c, char **argv, int invert, unsigned int *flags, 66 const void *entry, struct xt_entry_target **target) 67{ 68 struct xt_NFQ_info *tinfo 69 = (struct xt_NFQ_info *)(*target)->data; 70 71 switch (c) { 72 case 'F': 73 if (*flags) 74 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " 75 "Only use --queue-num ONCE!"); 76 parse_num(optarg, tinfo); 77 break; 78 case 'B': 79 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " 80 "--queue-balance not supported (kernel too old?)"); 81 } 82 83 return 1; 84} 85 86static int 87NFQUEUE_parse_v1(int c, char **argv, int invert, unsigned int *flags, 88 const void *entry, struct xt_entry_target **target) 89{ 90 struct xt_NFQ_info_v1 *info = (void *)(*target)->data; 91 char *colon; 92 unsigned int firstqueue, lastqueue; 93 94 switch (c) { 95 case 'F': /* fallthrough */ 96 case 'B': 97 if (*flags) 98 xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " 99 "Only use --queue-num ONCE!"); 100 101 if (!xtables_strtoui(optarg, &colon, &firstqueue, 0, UINT16_MAX)) 102 exit_badqueue(optarg); 103 104 info->queuenum = firstqueue; 105 106 if (c == 'F') { 107 if (*colon) 108 exit_badqueue(optarg); 109 break; 110 } 111 112 if (*colon != ':') 113 xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", optarg); 114 115 if (!xtables_strtoui(colon + 1, NULL, &lastqueue, 1, UINT16_MAX)) 116 exit_badqueue(optarg); 117 118 if (firstqueue >= lastqueue) 119 xtables_error(PARAMETER_PROBLEM, "%u should be less than %u", 120 firstqueue, lastqueue); 121 info->queues_total = lastqueue - firstqueue + 1; 122 break; 123 } 124 125 return 1; 126} 127 128static int 129NFQUEUE_parse_v2(int c, char **argv, int invert, unsigned int *flags, 130 const void *entry, struct xt_entry_target **target) 131{ 132 if (c == 'P') { 133 struct xt_NFQ_info_v2 *info = (void *)(*target)->data; 134 info->bypass = 1; 135 return 1; 136 } 137 return NFQUEUE_parse_v1(c, argv, invert, flags, entry, target); 138} 139 140static void NFQUEUE_print(const void *ip, 141 const struct xt_entry_target *target, int numeric) 142{ 143 const struct xt_NFQ_info *tinfo = 144 (const struct xt_NFQ_info *)target->data; 145 printf("NFQUEUE num %u", tinfo->queuenum); 146} 147 148static void NFQUEUE_print_v1(const void *ip, 149 const struct xt_entry_target *target, int numeric) 150{ 151 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data; 152 unsigned int last = tinfo->queues_total; 153 154 if (last > 1) { 155 last += tinfo->queuenum - 1; 156 printf("NFQUEUE balance %u:%u", tinfo->queuenum, last); 157 } else { 158 printf("NFQUEUE num %u", tinfo->queuenum); 159 } 160} 161 162static void NFQUEUE_print_v2(const void *ip, 163 const struct xt_entry_target *target, int numeric) 164{ 165 const struct xt_NFQ_info_v2 *info = (void *) target->data; 166 167 NFQUEUE_print_v1(ip, target, numeric); 168 if (info->bypass) 169 printf(" bypass"); 170} 171 172static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target) 173{ 174 const struct xt_NFQ_info *tinfo = 175 (const struct xt_NFQ_info *)target->data; 176 177 printf("--queue-num %u ", tinfo->queuenum); 178} 179 180static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target) 181{ 182 const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data; 183 unsigned int last = tinfo->queues_total; 184 185 if (last > 1) { 186 last += tinfo->queuenum - 1; 187 printf("--queue-balance %u:%u ", tinfo->queuenum, last); 188 } else { 189 printf("--queue-num %u ", tinfo->queuenum); 190 } 191} 192 193static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target) 194{ 195 const struct xt_NFQ_info_v2 *info = (void *) target->data; 196 197 NFQUEUE_save_v1(ip, target); 198 199 if (info->bypass) 200 printf("--queue-bypass "); 201} 202 203static void NFQUEUE_init_v1(struct xt_entry_target *t) 204{ 205 struct xt_NFQ_info_v1 *tinfo = (void *)t->data; 206 tinfo->queues_total = 1; 207} 208 209static struct xtables_target nfqueue_targets[] = { 210{ 211 .family = NFPROTO_UNSPEC, 212 .name = "NFQUEUE", 213 .version = XTABLES_VERSION, 214 .size = XT_ALIGN(sizeof(struct xt_NFQ_info)), 215 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)), 216 .help = NFQUEUE_help, 217 .parse = NFQUEUE_parse, 218 .print = NFQUEUE_print, 219 .save = NFQUEUE_save, 220 .extra_opts = NFQUEUE_opts 221},{ 222 .family = NFPROTO_UNSPEC, 223 .revision = 1, 224 .name = "NFQUEUE", 225 .version = XTABLES_VERSION, 226 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)), 227 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)), 228 .help = NFQUEUE_help_v1, 229 .init = NFQUEUE_init_v1, 230 .parse = NFQUEUE_parse_v1, 231 .print = NFQUEUE_print_v1, 232 .save = NFQUEUE_save_v1, 233 .extra_opts = NFQUEUE_opts, 234},{ 235 .family = NFPROTO_UNSPEC, 236 .revision = 2, 237 .name = "NFQUEUE", 238 .version = XTABLES_VERSION, 239 .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)), 240 .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)), 241 .help = NFQUEUE_help_v2, 242 .init = NFQUEUE_init_v1, 243 .parse = NFQUEUE_parse_v2, 244 .print = NFQUEUE_print_v2, 245 .save = NFQUEUE_save_v2, 246 .extra_opts = NFQUEUE_opts, 247} 248}; 249 250void _init(void) 251{ 252 xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets)); 253} 254