1daa1ef354deee764484c1494073b075859701971Harald Welte/* Shared library add-on to iptables for NFQ 2daa1ef354deee764484c1494073b075859701971Harald Welte * 3daa1ef354deee764484c1494073b075859701971Harald Welte * (C) 2005 by Harald Welte <laforge@netfilter.org> 4daa1ef354deee764484c1494073b075859701971Harald Welte * 5daa1ef354deee764484c1494073b075859701971Harald Welte * This program is distributed under the terms of GNU GPL v2, 1991 6daa1ef354deee764484c1494073b075859701971Harald Welte * 7daa1ef354deee764484c1494073b075859701971Harald Welte */ 8daa1ef354deee764484c1494073b075859701971Harald Welte#include <stdio.h> 9a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI#include <xtables.h> 10a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI#include <linux/netfilter/xt_NFQUEUE.h> 11daa1ef354deee764484c1494073b075859701971Harald Welte 12478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardtenum { 13478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt O_QUEUE_NUM = 0, 14478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt O_QUEUE_BALANCE, 15478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt O_QUEUE_BYPASS, 16d8784613a5be2821ff910cd4c2bfe889a9b306c5Jan Engelhardt F_QUEUE_NUM = 1 << O_QUEUE_NUM, 17d8784613a5be2821ff910cd4c2bfe889a9b306c5Jan Engelhardt F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE, 18478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt}; 19478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt 20932e648f38ac16b1ea14c1f66f23951388448c5aJan Engelhardtstatic void NFQUEUE_help(void) 21daa1ef354deee764484c1494073b075859701971Harald Welte{ 22daa1ef354deee764484c1494073b075859701971Harald Welte printf( 23daa1ef354deee764484c1494073b075859701971Harald Welte"NFQUEUE target options\n" 24daa1ef354deee764484c1494073b075859701971Harald Welte" --queue-num value Send packet to QUEUE number <value>.\n" 25daa1ef354deee764484c1494073b075859701971Harald Welte" Valid queue numbers are 0-65535\n" 26daa1ef354deee764484c1494073b075859701971Harald Welte); 27daa1ef354deee764484c1494073b075859701971Harald Welte} 28daa1ef354deee764484c1494073b075859701971Harald Welte 294282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphalstatic void NFQUEUE_help_v1(void) 304282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal{ 314282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal NFQUEUE_help(); 324282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal printf( 334282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal" --queue-balance first:last Balance flows between queues <value> to <value>.\n"); 344282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal} 354282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 366924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphalstatic void NFQUEUE_help_v2(void) 376924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal{ 386924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal NFQUEUE_help_v1(); 396924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal printf( 406924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal" --queue-bypass Bypass Queueing if no queue instance exists.\n"); 416924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal} 426924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal 43478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt#define s struct xt_NFQ_info 44478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardtstatic const struct xt_option_entry NFQUEUE_opts[] = { 45478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt {.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16, 46d8784613a5be2821ff910cd4c2bfe889a9b306c5Jan Engelhardt .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum), 47d8784613a5be2821ff910cd4c2bfe889a9b306c5Jan Engelhardt .excl = F_QUEUE_BALANCE}, 48478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt {.name = "queue-balance", .id = O_QUEUE_BALANCE, 49d8784613a5be2821ff910cd4c2bfe889a9b306c5Jan Engelhardt .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM}, 50478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt {.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE}, 51478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt XTOPT_TABLEEND, 52daa1ef354deee764484c1494073b075859701971Harald Welte}; 53478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt#undef s 54daa1ef354deee764484c1494073b075859701971Harald Welte 55478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardtstatic void NFQUEUE_parse(struct xt_option_call *cb) 56daa1ef354deee764484c1494073b075859701971Harald Welte{ 57478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt xtables_option_parse(cb); 58478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt if (cb->entry->id == O_QUEUE_BALANCE) 594282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: " 604282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal "--queue-balance not supported (kernel too old?)"); 614282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal} 624282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 63478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardtstatic void NFQUEUE_parse_v1(struct xt_option_call *cb) 644282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal{ 65478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt struct xt_NFQ_info_v1 *info = cb->data; 66478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt const uint16_t *r = cb->val.u16_range; 674282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 68478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt xtables_option_parse(cb); 69478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt switch (cb->entry->id) { 70478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt case O_QUEUE_BALANCE: 71478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt if (cb->nvals != 2) 72478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 73478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt "Bad range \"%s\"", cb->arg); 74478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt if (r[0] >= r[1]) 754282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal xtables_error(PARAMETER_PROBLEM, "%u should be less than %u", 76478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt r[0], r[1]); 77478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt info->queuenum = r[0]; 78478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt info->queues_total = r[1] - r[0] + 1; 794282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal break; 80daa1ef354deee764484c1494073b075859701971Harald Welte } 81daa1ef354deee764484c1494073b075859701971Harald Welte} 82daa1ef354deee764484c1494073b075859701971Harald Welte 83478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardtstatic void NFQUEUE_parse_v2(struct xt_option_call *cb) 846924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal{ 85478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt struct xt_NFQ_info_v2 *info = cb->data; 86478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt 87089585f14fda80508e26ea019703add07cb72f64Jan Engelhardt NFQUEUE_parse_v1(cb); 88478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt switch (cb->entry->id) { 89478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt case O_QUEUE_BYPASS: 906924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal info->bypass = 1; 91478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt break; 926924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal } 936924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal} 946924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal 95932e648f38ac16b1ea14c1f66f23951388448c5aJan Engelhardtstatic void NFQUEUE_print(const void *ip, 96932e648f38ac16b1ea14c1f66f23951388448c5aJan Engelhardt const struct xt_entry_target *target, int numeric) 97daa1ef354deee764484c1494073b075859701971Harald Welte{ 98a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI const struct xt_NFQ_info *tinfo = 99a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI (const struct xt_NFQ_info *)target->data; 10073866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" NFQUEUE num %u", tinfo->queuenum); 101daa1ef354deee764484c1494073b075859701971Harald Welte} 102daa1ef354deee764484c1494073b075859701971Harald Welte 1034282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphalstatic void NFQUEUE_print_v1(const void *ip, 1044282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal const struct xt_entry_target *target, int numeric) 1054282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal{ 1064282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data; 1074282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal unsigned int last = tinfo->queues_total; 1084282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 1094282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal if (last > 1) { 1104282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal last += tinfo->queuenum - 1; 11173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" NFQUEUE balance %u:%u", tinfo->queuenum, last); 1124282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal } else { 11373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" NFQUEUE num %u", tinfo->queuenum); 1144282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal } 1154282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal} 1164282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 1176924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphalstatic void NFQUEUE_print_v2(const void *ip, 1186924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal const struct xt_entry_target *target, int numeric) 1196924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal{ 1206924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal const struct xt_NFQ_info_v2 *info = (void *) target->data; 1216924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal 1226924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal NFQUEUE_print_v1(ip, target, numeric); 1236924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal if (info->bypass) 1246924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal printf(" bypass"); 1256924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal} 1266924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal 127932e648f38ac16b1ea14c1f66f23951388448c5aJan Engelhardtstatic void NFQUEUE_save(const void *ip, const struct xt_entry_target *target) 128daa1ef354deee764484c1494073b075859701971Harald Welte{ 129a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI const struct xt_NFQ_info *tinfo = 130a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI (const struct xt_NFQ_info *)target->data; 131daa1ef354deee764484c1494073b075859701971Harald Welte 13273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --queue-num %u", tinfo->queuenum); 133daa1ef354deee764484c1494073b075859701971Harald Welte} 134daa1ef354deee764484c1494073b075859701971Harald Welte 1354282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphalstatic void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target) 1364282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal{ 1374282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data; 1384282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal unsigned int last = tinfo->queues_total; 1394282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 1404282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal if (last > 1) { 1414282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal last += tinfo->queuenum - 1; 14273866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --queue-balance %u:%u", tinfo->queuenum, last); 1434282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal } else { 14473866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --queue-num %u", tinfo->queuenum); 1454282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal } 1464282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal} 1474282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 1486924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphalstatic void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target) 1496924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal{ 1506924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal const struct xt_NFQ_info_v2 *info = (void *) target->data; 1516924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal 1526924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal NFQUEUE_save_v1(ip, target); 1536924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal 1546924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal if (info->bypass) 1556924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal printf("--queue-bypass "); 1566924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal} 1576924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal 1584282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphalstatic void NFQUEUE_init_v1(struct xt_entry_target *t) 1594282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal{ 1604282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal struct xt_NFQ_info_v1 *tinfo = (void *)t->data; 1614282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal tinfo->queues_total = 1; 1624282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal} 1634282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 1646924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphalstatic struct xtables_target nfqueue_targets[] = { 1656924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal{ 166c5e85736c207f211d82d2878a5781f512327dfceJan Engelhardt .family = NFPROTO_UNSPEC, 167daa1ef354deee764484c1494073b075859701971Harald Welte .name = "NFQUEUE", 1688b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 169a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_NFQ_info)), 170a2e89ccf65e8c881e77674cd2b15b9704b0c6822Yasuyuki KOZAKAI .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)), 171932e648f38ac16b1ea14c1f66f23951388448c5aJan Engelhardt .help = NFQUEUE_help, 172932e648f38ac16b1ea14c1f66f23951388448c5aJan Engelhardt .print = NFQUEUE_print, 173932e648f38ac16b1ea14c1f66f23951388448c5aJan Engelhardt .save = NFQUEUE_save, 174478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt .x6_parse = NFQUEUE_parse, 175478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt .x6_options = NFQUEUE_opts 1766924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal},{ 1774282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .family = NFPROTO_UNSPEC, 1784282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .revision = 1, 1794282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .name = "NFQUEUE", 1804282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .version = XTABLES_VERSION, 1814282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)), 1824282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)), 1834282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .help = NFQUEUE_help_v1, 1844282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .init = NFQUEUE_init_v1, 1854282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .print = NFQUEUE_print_v1, 1864282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal .save = NFQUEUE_save_v1, 187478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt .x6_parse = NFQUEUE_parse_v1, 188478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt .x6_options = NFQUEUE_opts, 1896924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal},{ 1906924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .family = NFPROTO_UNSPEC, 1916924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .revision = 2, 1926924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .name = "NFQUEUE", 1936924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .version = XTABLES_VERSION, 1946924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)), 1956924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)), 1966924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .help = NFQUEUE_help_v2, 1976924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .init = NFQUEUE_init_v1, 1986924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .print = NFQUEUE_print_v2, 1996924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal .save = NFQUEUE_save_v2, 200478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt .x6_parse = NFQUEUE_parse_v2, 201478be25c3b64e0f2ddbd2aa97ebe78df7ca00c0aJan Engelhardt .x6_options = NFQUEUE_opts, 2026924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal} 2034282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal}; 2044282d89a798adcf50973a22c5a17563b5e9421cbFlorian Westphal 205daa1ef354deee764484c1494073b075859701971Harald Weltevoid _init(void) 206daa1ef354deee764484c1494073b075859701971Harald Welte{ 2076924b4987d88fbe383bec4da4cf331cc466c245eFlorian Westphal xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets)); 208daa1ef354deee764484c1494073b075859701971Harald Welte} 209