Linux Audio

Check our new training course

Loading...
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* iptables module for using new netfilter netlink queue
  3 *
  4 * (C) 2005 by Harald Welte <laforge@netfilter.org>
 
 
 
 
 
  5 */
  6
  7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  8
  9#include <linux/module.h>
 10#include <linux/skbuff.h>
 11
 
 
 
 
 12#include <linux/netfilter.h>
 13#include <linux/netfilter_arp.h>
 14#include <linux/netfilter/x_tables.h>
 15#include <linux/netfilter/xt_NFQUEUE.h>
 16
 17#include <net/netfilter/nf_queue.h>
 18
 19MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 20MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
 21MODULE_LICENSE("GPL");
 22MODULE_ALIAS("ipt_NFQUEUE");
 23MODULE_ALIAS("ip6t_NFQUEUE");
 24MODULE_ALIAS("arpt_NFQUEUE");
 25
 26static u32 jhash_initval __read_mostly;
 
 27
 28static unsigned int
 29nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
 30{
 31	const struct xt_NFQ_info *tinfo = par->targinfo;
 32
 33	return NF_QUEUE_NR(tinfo->queuenum);
 34}
 35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 36static unsigned int
 37nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
 38{
 39	const struct xt_NFQ_info_v1 *info = par->targinfo;
 40	u32 queue = info->queuenum;
 41
 42	if (info->queues_total > 1) {
 43		queue = nfqueue_hash(skb, queue, info->queues_total,
 44				     xt_family(par), jhash_initval);
 
 
 
 
 
 
 45	}
 46	return NF_QUEUE_NR(queue);
 47}
 48
 49static unsigned int
 50nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
 51{
 52	const struct xt_NFQ_info_v2 *info = par->targinfo;
 53	unsigned int ret = nfqueue_tg_v1(skb, par);
 54
 55	if (info->bypass)
 56		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
 57	return ret;
 58}
 59
 60static int nfqueue_tg_check(const struct xt_tgchk_param *par)
 61{
 62	const struct xt_NFQ_info_v3 *info = par->targinfo;
 63	u32 maxid;
 64
 65	init_hashrandom(&jhash_initval);
 66
 
 
 67	if (info->queues_total == 0) {
 68		pr_info_ratelimited("number of total queues is 0\n");
 69		return -EINVAL;
 70	}
 71	maxid = info->queues_total - 1 + info->queuenum;
 72	if (maxid > 0xffff) {
 73		pr_info_ratelimited("number of queues (%u) out of range (got %u)\n",
 74				    info->queues_total, maxid);
 75		return -ERANGE;
 76	}
 77	if (par->target->revision == 2 && info->flags > 1)
 78		return -EINVAL;
 79	if (par->target->revision == 3 && info->flags & ~NFQ_FLAG_MASK)
 80		return -EINVAL;
 81
 82	return 0;
 83}
 84
 85static unsigned int
 86nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
 87{
 88	const struct xt_NFQ_info_v3 *info = par->targinfo;
 89	u32 queue = info->queuenum;
 90	int ret;
 91
 92	if (info->queues_total > 1) {
 93		if (info->flags & NFQ_FLAG_CPU_FANOUT) {
 94			int cpu = smp_processor_id();
 95
 96			queue = info->queuenum + cpu % info->queues_total;
 97		} else {
 98			queue = nfqueue_hash(skb, queue, info->queues_total,
 99					     xt_family(par), jhash_initval);
100		}
101	}
102
103	ret = NF_QUEUE_NR(queue);
104	if (info->flags & NFQ_FLAG_BYPASS)
105		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
106
107	return ret;
108}
109
110static struct xt_target nfqueue_tg_reg[] __read_mostly = {
111	{
112		.name		= "NFQUEUE",
113		.family		= NFPROTO_UNSPEC,
114		.target		= nfqueue_tg,
115		.targetsize	= sizeof(struct xt_NFQ_info),
116		.me		= THIS_MODULE,
117	},
118	{
119		.name		= "NFQUEUE",
120		.revision	= 1,
121		.family		= NFPROTO_UNSPEC,
122		.checkentry	= nfqueue_tg_check,
123		.target		= nfqueue_tg_v1,
124		.targetsize	= sizeof(struct xt_NFQ_info_v1),
125		.me		= THIS_MODULE,
126	},
127	{
128		.name		= "NFQUEUE",
129		.revision	= 2,
130		.family		= NFPROTO_UNSPEC,
131		.checkentry	= nfqueue_tg_check,
132		.target		= nfqueue_tg_v2,
133		.targetsize	= sizeof(struct xt_NFQ_info_v2),
134		.me		= THIS_MODULE,
135	},
136	{
137		.name		= "NFQUEUE",
138		.revision	= 3,
139		.family		= NFPROTO_UNSPEC,
140		.checkentry	= nfqueue_tg_check,
141		.target		= nfqueue_tg_v3,
142		.targetsize	= sizeof(struct xt_NFQ_info_v3),
143		.me		= THIS_MODULE,
144	},
145};
146
147static int __init nfqueue_tg_init(void)
148{
149	return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
150}
151
152static void __exit nfqueue_tg_exit(void)
153{
154	xt_unregister_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
155}
156
157module_init(nfqueue_tg_init);
158module_exit(nfqueue_tg_exit);
v3.1
 
  1/* iptables module for using new netfilter netlink queue
  2 *
  3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License version 2 as
  7 * published by the Free Software Foundation.
  8 *
  9 */
 10
 
 
 11#include <linux/module.h>
 12#include <linux/skbuff.h>
 13
 14#include <linux/ip.h>
 15#include <linux/ipv6.h>
 16#include <linux/jhash.h>
 17
 18#include <linux/netfilter.h>
 19#include <linux/netfilter_arp.h>
 20#include <linux/netfilter/x_tables.h>
 21#include <linux/netfilter/xt_NFQUEUE.h>
 22
 
 
 23MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 24MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
 25MODULE_LICENSE("GPL");
 26MODULE_ALIAS("ipt_NFQUEUE");
 27MODULE_ALIAS("ip6t_NFQUEUE");
 28MODULE_ALIAS("arpt_NFQUEUE");
 29
 30static u32 jhash_initval __read_mostly;
 31static bool rnd_inited __read_mostly;
 32
 33static unsigned int
 34nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
 35{
 36	const struct xt_NFQ_info *tinfo = par->targinfo;
 37
 38	return NF_QUEUE_NR(tinfo->queuenum);
 39}
 40
 41static u32 hash_v4(const struct sk_buff *skb)
 42{
 43	const struct iphdr *iph = ip_hdr(skb);
 44	__be32 ipaddr;
 45
 46	/* packets in either direction go into same queue */
 47	ipaddr = iph->saddr ^ iph->daddr;
 48
 49	return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval);
 50}
 51
 52#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
 53static u32 hash_v6(const struct sk_buff *skb)
 54{
 55	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
 56	__be32 addr[4];
 57
 58	addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0];
 59	addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1];
 60	addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2];
 61	addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3];
 62
 63	return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval);
 64}
 65#endif
 66
 67static unsigned int
 68nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
 69{
 70	const struct xt_NFQ_info_v1 *info = par->targinfo;
 71	u32 queue = info->queuenum;
 72
 73	if (info->queues_total > 1) {
 74		if (par->family == NFPROTO_IPV4)
 75			queue = (((u64) hash_v4(skb) * info->queues_total) >>
 76				 32) + queue;
 77#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
 78		else if (par->family == NFPROTO_IPV6)
 79			queue = (((u64) hash_v6(skb) * info->queues_total) >>
 80				 32) + queue;
 81#endif
 82	}
 83	return NF_QUEUE_NR(queue);
 84}
 85
 86static unsigned int
 87nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
 88{
 89	const struct xt_NFQ_info_v2 *info = par->targinfo;
 90	unsigned int ret = nfqueue_tg_v1(skb, par);
 91
 92	if (info->bypass)
 93		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
 94	return ret;
 95}
 96
 97static int nfqueue_tg_check(const struct xt_tgchk_param *par)
 98{
 99	const struct xt_NFQ_info_v2 *info = par->targinfo;
100	u32 maxid;
101
102	if (unlikely(!rnd_inited)) {
103		get_random_bytes(&jhash_initval, sizeof(jhash_initval));
104		rnd_inited = true;
105	}
106	if (info->queues_total == 0) {
107		pr_err("NFQUEUE: number of total queues is 0\n");
108		return -EINVAL;
109	}
110	maxid = info->queues_total - 1 + info->queuenum;
111	if (maxid > 0xffff) {
112		pr_err("NFQUEUE: number of queues (%u) out of range (got %u)\n",
113		       info->queues_total, maxid);
114		return -ERANGE;
115	}
116	if (par->target->revision == 2 && info->bypass > 1)
117		return -EINVAL;
 
 
 
118	return 0;
119}
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121static struct xt_target nfqueue_tg_reg[] __read_mostly = {
122	{
123		.name		= "NFQUEUE",
124		.family		= NFPROTO_UNSPEC,
125		.target		= nfqueue_tg,
126		.targetsize	= sizeof(struct xt_NFQ_info),
127		.me		= THIS_MODULE,
128	},
129	{
130		.name		= "NFQUEUE",
131		.revision	= 1,
132		.family		= NFPROTO_UNSPEC,
133		.checkentry	= nfqueue_tg_check,
134		.target		= nfqueue_tg_v1,
135		.targetsize	= sizeof(struct xt_NFQ_info_v1),
136		.me		= THIS_MODULE,
137	},
138	{
139		.name		= "NFQUEUE",
140		.revision	= 2,
141		.family		= NFPROTO_UNSPEC,
142		.checkentry	= nfqueue_tg_check,
143		.target		= nfqueue_tg_v2,
144		.targetsize	= sizeof(struct xt_NFQ_info_v2),
 
 
 
 
 
 
 
 
 
145		.me		= THIS_MODULE,
146	},
147};
148
149static int __init nfqueue_tg_init(void)
150{
151	return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
152}
153
154static void __exit nfqueue_tg_exit(void)
155{
156	xt_unregister_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
157}
158
159module_init(nfqueue_tg_init);
160module_exit(nfqueue_tg_exit);