Blame view
net/netfilter/xt_NFQUEUE.c
3.82 KB
2e4e6a17a
|
1 2 3 4 5 |
/* iptables module for using new netfilter netlink queue * * (C) 2005 by Harald Welte <laforge@netfilter.org> * * This program is free software; you can redistribute it and/or modify |
601e68e10
|
6 |
* it under the terms of the GNU General Public License version 2 as |
2e4e6a17a
|
7 |
* published by the Free Software Foundation. |
601e68e10
|
8 |
* |
2e4e6a17a
|
9 10 11 12 |
*/ #include <linux/module.h> #include <linux/skbuff.h> |
10662aa30
|
13 14 15 |
#include <linux/ip.h> #include <linux/ipv6.h> #include <linux/jhash.h> |
2e4e6a17a
|
16 17 18 19 20 21 |
#include <linux/netfilter.h> #include <linux/netfilter_arp.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter/xt_NFQUEUE.h> MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
2ae15b64e
|
22 |
MODULE_DESCRIPTION("Xtables: packet forwarding to netlink"); |
2e4e6a17a
|
23 24 25 26 |
MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_NFQUEUE"); MODULE_ALIAS("ip6t_NFQUEUE"); MODULE_ALIAS("arpt_NFQUEUE"); |
10662aa30
|
27 |
static u32 jhash_initval __read_mostly; |
2e4e6a17a
|
28 |
static unsigned int |
7eb355865
|
29 |
nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par) |
2e4e6a17a
|
30 |
{ |
7eb355865
|
31 |
const struct xt_NFQ_info *tinfo = par->targinfo; |
2e4e6a17a
|
32 33 34 |
return NF_QUEUE_NR(tinfo->queuenum); } |
10662aa30
|
35 36 37 |
static u32 hash_v4(const struct sk_buff *skb) { const struct iphdr *iph = ip_hdr(skb); |
f9ffc3125
|
38 |
__be32 ipaddr; |
10662aa30
|
39 40 41 |
/* packets in either direction go into same queue */ ipaddr = iph->saddr ^ iph->daddr; |
f9ffc3125
|
42 |
return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval); |
10662aa30
|
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
} static unsigned int nfqueue_tg4_v1(struct sk_buff *skb, const struct xt_target_param *par) { const struct xt_NFQ_info_v1 *info = par->targinfo; u32 queue = info->queuenum; if (info->queues_total > 1) queue = hash_v4(skb) % info->queues_total + queue; return NF_QUEUE_NR(queue); } #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) static u32 hash_v6(const struct sk_buff *skb) { const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
f9ffc3125
|
60 |
__be32 addr[4]; |
10662aa30
|
61 62 63 64 65 |
addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0]; addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1]; addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2]; addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3]; |
f9ffc3125
|
66 |
return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval); |
10662aa30
|
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
} static unsigned int nfqueue_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par) { const struct xt_NFQ_info_v1 *info = par->targinfo; u32 queue = info->queuenum; if (info->queues_total > 1) queue = hash_v6(skb) % info->queues_total + queue; return NF_QUEUE_NR(queue); } #endif static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par) { const struct xt_NFQ_info_v1 *info = par->targinfo; u32 maxid; if (info->queues_total == 0) { pr_err("NFQUEUE: number of total queues is 0 "); return false; } maxid = info->queues_total - 1 + info->queuenum; if (maxid > 0xffff) { pr_err("NFQUEUE: number of queues (%u) out of range (got %u) ", info->queues_total, maxid); return false; } return true; } |
d3c5ee6d5
|
100 |
static struct xt_target nfqueue_tg_reg[] __read_mostly = { |
4470bbc74
|
101 102 |
{ .name = "NFQUEUE", |
61f5abcab
|
103 |
.family = NFPROTO_UNSPEC, |
d3c5ee6d5
|
104 |
.target = nfqueue_tg, |
4470bbc74
|
105 106 107 |
.targetsize = sizeof(struct xt_NFQ_info), .me = THIS_MODULE, }, |
10662aa30
|
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
{ .name = "NFQUEUE", .revision = 1, .family = NFPROTO_IPV4, .checkentry = nfqueue_tg_v1_check, .target = nfqueue_tg4_v1, .targetsize = sizeof(struct xt_NFQ_info_v1), .me = THIS_MODULE, }, #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) { .name = "NFQUEUE", .revision = 1, .family = NFPROTO_IPV6, .checkentry = nfqueue_tg_v1_check, .target = nfqueue_tg6_v1, .targetsize = sizeof(struct xt_NFQ_info_v1), .me = THIS_MODULE, }, #endif |
2e4e6a17a
|
128 |
}; |
d3c5ee6d5
|
129 |
static int __init nfqueue_tg_init(void) |
2e4e6a17a
|
130 |
{ |
10662aa30
|
131 |
get_random_bytes(&jhash_initval, sizeof(jhash_initval)); |
d3c5ee6d5
|
132 |
return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg)); |
2e4e6a17a
|
133 |
} |
d3c5ee6d5
|
134 |
static void __exit nfqueue_tg_exit(void) |
2e4e6a17a
|
135 |
{ |
d3c5ee6d5
|
136 |
xt_unregister_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg)); |
2e4e6a17a
|
137 |
} |
d3c5ee6d5
|
138 139 |
module_init(nfqueue_tg_init); module_exit(nfqueue_tg_exit); |