/* * This is a module which is used for queueing packets and communicating with * userspace via nfnetlink. * * (C) 2005 by Harald Welte <laforge@netfilter.org> * (C) 2007 by Patrick McHardy <kaber@trash.net> * * Based on the old ipv4-only ip_queue.c: * (C) 2000-2002 James Morris <jmorris@intercode.com.au> * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#include<linux/module.h>#include<linux/skbuff.h>#include<linux/init.h>#include<linux/spinlock.h>#include<linux/slab.h>#include<linux/notifier.h>#include<linux/netdevice.h>#include<linux/netfilter.h>#include<linux/proc_fs.h>#include<linux/netfilter_ipv4.h>#include<linux/netfilter_ipv6.h>#include<linux/netfilter/nfnetlink.h>#include<linux/netfilter/nfnetlink_queue.h>#include<linux/list.h>#include<net/sock.h>#include<net/netfilter/nf_queue.h>#include<net/netns/generic.h>#include<net/netfilter/nfnetlink_queue.h>#include<linux/atomic.h>#ifdef CONFIG_BRIDGE_NETFILTER#include"../bridge/br_private.h"#endif#define NFQNL_QMAX_DEFAULT 1024structnfqnl_instance{structhlist_nodehlist;/* global list of queues */structrcu_headrcu;intpeer_portid;unsignedintqueue_maxlen;unsignedintcopy_range;unsignedintqueue_dropped;unsignedintqueue_user_dropped;u_int16_tqueue_num;/* number of this queue */u_int8_tcopy_mode;u_int32_tflags;/* Set using NFQA_CFG_FLAGS *//* * Following fields are dirtied for each queued packet, * keep them in same cache line if possible. */spinlock_tlock;unsignedintqueue_total;unsignedintid_sequence;/* 'sequence' of pkt ids */structlist_headqueue_list;/* packets in queue */};typedefint(*nfqnl_cmpfn)(structnf_queue_entry*,unsignedlong);staticintnfnl_queue_net_id__read_mostly;#define INSTANCE_BUCKETS 16structnfnl_queue_net{spinlock_tinstances_lock;structhlist_headinstance_table[INSTANCE_BUCKETS];};staticstructnfnl_queue_net*nfnl_queue_pernet(structnet*net){returnnet_generic(net,nfnl_queue_net_id);}staticinlineu_int8_tinstance_hashfn(u_int16_tqueue_num){return((queue_num>>8)^queue_num)%INSTANCE_BUCKETS;}staticstructnfqnl_instance*instance_lookup(structnfnl_queue_net*q,u_int16_tqueue_num){structhlist