1c4e6c7aluigi/*-
278a6b08pfg * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
378a6b08pfg *
4c4e6c7aluigi * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
5c4e6c7aluigi *
6c4e6c7aluigi * Redistribution and use in source and binary forms, with or without
7c4e6c7aluigi * modification, are permitted provided that the following conditions
8c4e6c7aluigi * are met:
9c4e6c7aluigi * 1. Redistributions of source code must retain the above copyright
10c4e6c7aluigi *    notice, this list of conditions and the following disclaimer.
11c4e6c7aluigi * 2. Redistributions in binary form must reproduce the above copyright
12c4e6c7aluigi *    notice, this list of conditions and the following disclaimer in the
13c4e6c7aluigi *    documentation and/or other materials provided with the distribution.
14c4e6c7aluigi *
15c4e6c7aluigi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16c4e6c7aluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17c4e6c7aluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18c4e6c7aluigi * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c4e6c7aluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c4e6c7aluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21c4e6c7aluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c4e6c7aluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c4e6c7aluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c4e6c7aluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c4e6c7aluigi * SUCH DAMAGE.
26c4e6c7aluigi *
27c4e6c7aluigi * $FreeBSD$
28c4e6c7aluigi */
29c4e6c7aluigi
30c4e6c7aluigi#ifndef _IPFW2_PRIVATE_H
31c4e6c7aluigi#define _IPFW2_PRIVATE_H
32c4e6c7aluigi
33c4e6c7aluigi/*
34c4e6c7aluigi * Internal constants and data structures used by ipfw components
35c4e6c7aluigi * and not meant to be exported outside the kernel.
36c4e6c7aluigi */
37c4e6c7aluigi
38c4e6c7aluigi#ifdef _KERNEL
39c4e6c7aluigi
405ceeac4luigi/*
415ceeac4luigi * For platforms that do not have SYSCTL support, we wrap the
425ceeac4luigi * SYSCTL_* into a function (one per file) to collect the values
435ceeac4luigi * into an array at module initialization. The wrapping macros,
445ceeac4luigi * SYSBEGIN() and SYSEND, are empty in the default case.
455ceeac4luigi */
465ceeac4luigi#ifndef SYSBEGIN
475ceeac4luigi#define SYSBEGIN(x)
485ceeac4luigi#endif
495ceeac4luigi#ifndef SYSEND
505ceeac4luigi#define SYSEND
515ceeac4luigi#endif
52c4e6c7aluigi
5346b1e41melifaro/* Return values from ipfw_chk() */
5446b1e41melifaroenum {
5546b1e41melifaro	IP_FW_PASS = 0,
5646b1e41melifaro	IP_FW_DENY,
5746b1e41melifaro	IP_FW_DIVERT,
5846b1e41melifaro	IP_FW_TEE,
5946b1e41melifaro	IP_FW_DUMMYNET,
6046b1e41melifaro	IP_FW_NETGRAPH,
6146b1e41melifaro	IP_FW_NGTEE,
6246b1e41melifaro	IP_FW_NAT,
6346b1e41melifaro	IP_FW_REASS,
64f666b9eae	IP_FW_NAT64,
6546b1e41melifaro};
6646b1e41melifaro
6746b1e41melifaro/*
6846b1e41melifaro * Structure for collecting parameters to dummynet for ip6_output forwarding
6946b1e41melifaro */
7046b1e41melifarostruct _ip6dn_args {
7146b1e41melifaro       struct ip6_pktopts *opt_or;
7246b1e41melifaro       int flags_or;
7346b1e41melifaro       struct ip6_moptions *im6o_or;
7446b1e41melifaro       struct ifnet *origifp_or;
7546b1e41melifaro       struct ifnet *ifp_or;
7646b1e41melifaro       struct sockaddr_in6 dst_or;
7746b1e41melifaro       u_long mtu_or;
7846b1e41melifaro};
7946b1e41melifaro
8046b1e41melifaro
8146b1e41melifaro/*
8246b1e41melifaro * Arguments for calling ipfw_chk() and dummynet_io(). We put them
8346b1e41melifaro * all into a structure because this way it is easier and more
8446b1e41melifaro * efficient to pass variables around and extend the interface.
8546b1e41melifaro */
8646b1e41melifarostruct ip_fw_args {
873ad6a52ae	uint32_t		flags;
88d751747glebius#define	IPFW_ARGS_ETHER		0x00010000	/* valid ethernet header */
89d751747glebius#define	IPFW_ARGS_NH4		0x00020000	/* IPv4 next hop in hopstore */
90d751747glebius#define	IPFW_ARGS_NH6		0x00040000	/* IPv6 next hop in hopstore */
91d751747glebius#define	IPFW_ARGS_NH4PTR	0x00080000	/* IPv4 next hop in next_hop */
92d751747glebius#define	IPFW_ARGS_NH6PTR	0x00100000	/* IPv6 next hop in next_hop6 */
93d751747glebius#define	IPFW_ARGS_REF		0x00200000	/* valid ipfw_rule_ref	*/
94d751747glebius#define	IPFW_ARGS_IN		0x00400000	/* called on input */
95d751747glebius#define	IPFW_ARGS_OUT		0x00800000	/* called on output */
96d751747glebius#define	IPFW_ARGS_IP4		0x01000000	/* belongs to v4 ISR */
97d751747glebius#define	IPFW_ARGS_IP6		0x02000000	/* belongs to v6 ISR */
98d751747glebius#define	IPFW_ARGS_DROP		0x04000000	/* drop it (dummynet) */
99d751747glebius#define	IPFW_ARGS_LENMASK	0x0000ffff	/* length of data in *mem */
100d751747glebius#define	IPFW_ARGS_LENGTH(f)	((f) & IPFW_ARGS_LENMASK)
10146b1e41melifaro	/*
10246b1e41melifaro	 * On return, it points to the matching rule.
10346b1e41melifaro	 * On entry, rule.slot > 0 means the info is valid and
10446b1e41melifaro	 * contains the starting rule for an ipfw search.
10546b1e41melifaro	 * If chain_id == chain->id && slot >0 then jump to that slot.
10646b1e41melifaro	 * Otherwise, we locate the first rule >= rulenum:rule_id
10746b1e41melifaro	 */
1083ad6a52ae	struct ipfw_rule_ref	rule;	/* match/restart info		*/
10946b1e41melifaro
110d751747glebius	struct ifnet		*ifp;	/* input/output interface	*/
1113ad6a52ae	struct inpcb		*inp;
1123ad6a52ae	union {
1133ad6a52ae		/*
1143ad6a52ae		 * next_hop[6] pointers can be used to point to next hop
1153ad6a52ae		 * stored in rule's opcode to avoid copying into hopstore.
1163ad6a52ae		 * Also, it is expected that all 0x1-0x10 flags are mutually
1173ad6a52ae		 * exclusive.
1183ad6a52ae		 */
1193ad6a52ae		struct sockaddr_in	*next_hop;
1203ad6a52ae		struct sockaddr_in6	*next_hop6;
1213ad6a52ae		/* ipfw next hop storage */
1223ad6a52ae		struct sockaddr_in	hopstore;
1233ad6a52ae		struct ip_fw_nh6 {
1243ad6a52ae			struct in6_addr sin6_addr;
1253ad6a52ae			uint32_t	sin6_scope_id;
1263ad6a52ae			uint16_t	sin6_port;
1273ad6a52ae		} hopstore6;
1288ee4f19ae	};
1294ac8998glebius	union {
1304ac8998glebius		struct mbuf	*m;	/* the mbuf chain		*/
1314ac8998glebius		void		*mem;	/* or memory pointer		*/
1324ac8998glebius	};
1333ad6a52ae	struct ipfw_flow_id	f_id;	/* grabbed from IP header	*/
13446b1e41melifaro};
13546b1e41melifaro
136c4e6c7aluigiMALLOC_DECLARE(M_IPFW);
137c4e6c7aluigi
13840024ffluigi/* wrapper for freeing a packet, in case we need to do more work */
1395ceeac4luigi#ifndef FREE_PKT
1405ceeac4luigi#if defined(__linux__) || defined(_WIN32)
1415ceeac4luigi#define FREE_PKT(m)	netisr_dispatch(-1, m)
1425ceeac4luigi#else
14340024ffluigi#define FREE_PKT(m)	m_freem(m)
1445ceeac4luigi#endif
1455ceeac4luigi#endif /* !FREE_PKT */
14640024ffluigi
147483862aluigi/*
148483862aluigi * Function definitions.
149483862aluigi */
150285cf94aeint ipfw_chk(struct ip_fw_args *args);
151285cf94aestruct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *,
152285cf94ae    u_int32_t, u_int32_t, int);
153c4e6c7aluigi
15441a70f9glebiusint ipfw_attach_hooks(void);
15541a70f9glebiusvoid ipfw_detach_hooks(void);
156c4e6c7aluigi#ifdef NOTYET
157c4e6c7aluigivoid ipfw_nat_destroy(void);
158c4e6c7aluigi#endif
159c4e6c7aluigi
160c4e6c7aluigi/* In ip_fw_log.c */
161c4e6c7aluigistruct ip;
162a1eca3cmelifarostruct ip_fw_chain;
163285cf94ae
164c71d3d8aevoid ipfw_bpf_init(int);
165c71d3d8aevoid ipfw_bpf_uninit(int);
1664ac8998glebiusvoid ipfw_bpf_tap(u_char *, u_int);
1674ac8998glebiusvoid ipfw_bpf_mtap(struct mbuf *);
168c71d3d8aevoid ipfw_bpf_mtap2(void *, u_int, struct mbuf *);
169a1eca3cmelifarovoid ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen,
1704ac8998glebius    struct ip_fw_args *args, u_short offset, uint32_t tablearg, struct ip *ip);
171c4e6c7aluigiVNET_DECLARE(u_int64_t, norule_counter);
172c4e6c7aluigi#define	V_norule_counter	VNET(norule_counter)
173c4e6c7aluigiVNET_DECLARE(int, verbose_limit);
174c4e6c7aluigi#define	V_verbose_limit		VNET(verbose_limit)
175c4e6c7aluigi
176c4e6c7aluigi/* In ip_fw_dynamic.c */
177285cf94aestruct sockopt_data;
178c4e6c7aluigi
179c4e6c7aluigienum { /* result for matching dynamic rules */
180c4e6c7aluigi	MATCH_REVERSE = 0,
181c4e6c7aluigi	MATCH_FORWARD,
182c4e6c7aluigi	MATCH_NONE,
183c4e6c7aluigi	MATCH_UNKNOWN,
184c4e6c7aluigi};
185c4e6c7aluigi
186c4e6c7aluigi/*
187545ce70ae * Macro to determine that we need to do or redo dynamic state lookup.
188545ce70ae * direction == MATCH_UNKNOWN means that this is first lookup, then we need
189545ce70ae * to do lookup.
190545ce70ae * Otherwise check the state name, if previous lookup was for "any" name,
191545ce70ae * this means there is no state with specific name. Thus no need to do
192545ce70ae * lookup. If previous name was not "any", redo lookup for specific name.
193545ce70ae */
194545ce70ae#define	DYN_LOOKUP_NEEDED(p, cmd)	\
195545ce70ae    ((p)->direction == MATCH_UNKNOWN ||	\
196545ce70ae	((p)->kidx != 0 && (p)->kidx != (cmd)->arg1))
197545ce70ae#define	DYN_INFO_INIT(p)	do {	\
198545ce70ae	(p)->direction = MATCH_UNKNOWN;	\
199545ce70ae	(p)->kidx = 0;			\
200545ce70ae} while (0)
201545ce70aestruct ipfw_dyn_info {
202545ce70ae	uint16_t	direction;	/* match direction */
203545ce70ae	uint16_t	kidx;		/* state name kidx */
204545ce70ae	uint32_t	hashval;	/* hash value */
205545ce70ae	uint32_t	version;	/* bucket version */
206545ce70ae	uint32_t	f_pos;
207545ce70ae};
2087c8e435aeint ipfw_dyn_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
209545ce70ae    const ipfw_insn_limit *cmd, const struct ip_fw_args *args,
210545ce70ae    const void *ulp, int pktlen, struct ipfw_dyn_info *info,
211545ce70ae    uint32_t tablearg);
212545ce70aestruct ip_fw *ipfw_dyn_lookup_state(const struct ip_fw_args *args,
213545ce70ae    const void *ulp, int pktlen, const ipfw_insn *cmd,
214545ce70ae    struct ipfw_dyn_info *info);
215545ce70ae
216285cf94aeint ipfw_is_dyn_rule(struct ip_fw *rule);
217285cf94aevoid ipfw_expire_dyn_states(struct ip_fw_chain *, ipfw_range_tlv *);
218c07e3ecmelifarovoid ipfw_get_dynamic(struct ip_fw_chain *chain, char **bp, const char *ep);
2195d627fdmelifaroint ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd);
220c4e6c7aluigi
221c07e3ecmelifarovoid ipfw_dyn_init(struct ip_fw_chain *);	/* per-vnet initialization */
222c4e6c7aluigivoid ipfw_dyn_uninit(int);	/* per-vnet deinitialization */
223c4e6c7aluigiint ipfw_dyn_len(void);
224285cf94aeuint32_t ipfw_dyn_get_count(uint32_t *, int *);
225285cf94aevoid ipfw_dyn_reset_eaction(struct ip_fw_chain *ch, uint16_t eaction_id,
226285cf94ae    uint16_t default_id, uint16_t instance_id);
227c4e6c7aluigi
228c4e6c7aluigi/* common variables */
229c4e6c7aluigiVNET_DECLARE(int, fw_one_pass);
2303805c8fluigi#define	V_fw_one_pass		VNET(fw_one_pass)
2313805c8fluigi
232c4e6c7aluigiVNET_DECLARE(int, fw_verbose);
2333805c8fluigi#define	V_fw_verbose		VNET(fw_verbose)
234c4e6c7aluigi
2353805c8fluigiVNET_DECLARE(struct ip_fw_chain, layer3_chain);
236c4e6c7aluigi#define	V_layer3_chain		VNET(layer3_chain)
2373805c8fluigi
238a5e98abmelifaroVNET_DECLARE(int, ipfw_vnet_ready);
239a5e98abmelifaro#define	V_ipfw_vnet_ready	VNET(ipfw_vnet_ready)
240a5e98abmelifaro
2413805c8fluigiVNET_DECLARE(u_int32_t, set_disable);
2420b02c03luigi#define	V_set_disable		VNET(set_disable)
243c4e6c7aluigi
2443805c8fluigiVNET_DECLARE(int, autoinc_step);
2453805c8fluigi#define V_autoinc_step		VNET(autoinc_step)
246c4e6c7aluigi
24797c3a90melifaroVNET_DECLARE(unsigned int, fw_tables_max);
24897c3a90melifaro#define V_fw_tables_max		VNET(fw_tables_max)
249c614ff6melifaro
25001ec53emelifaroVNET_DECLARE(unsigned int, fw_tables_sets);
25101ec53emelifaro#define V_fw_tables_sets	VNET(fw_tables_sets)
25201ec53emelifaro
25301ec53emelifarostruct tables_config;
25401ec53emelifaro
2553f7d90bmelifaro#ifdef _KERNEL
2563f7d90bmelifaro/*
2573f7d90bmelifaro * Here we have the structure representing an ipfw rule.
2583f7d90bmelifaro *
2593f7d90bmelifaro * It starts with a general area
2603f7d90bmelifaro * followed by an array of one or more instructions, which the code
2613f7d90bmelifaro * accesses as an array of 32-bit values.
2623f7d90bmelifaro *
2633f7d90bmelifaro * Given a rule pointer  r:
2643f7d90bmelifaro *
2653f7d90bmelifaro *  r->cmd		is the start of the first instruction.
2663f7d90bmelifaro *  ACTION_PTR(r)	is the start of the first action (things to do
2673f7d90bmelifaro *			once a rule matched).
2683f7d90bmelifaro */
2693f7d90bmelifaro
2703f7d90bmelifarostruct ip_fw {
2713f7d90bmelifaro	uint16_t	act_ofs;	/* offset of action in 32-bit units */
2723f7d90bmelifaro	uint16_t	cmd_len;	/* # of 32-bit words in cmd	*/
2733f7d90bmelifaro	uint16_t	rulenum;	/* rule number			*/
2743f7d90bmelifaro	uint8_t		set;		/* rule set (0..31)		*/
2753f7d90bmelifaro	uint8_t		flags;		/* currently unused		*/
2763f7d90bmelifaro	counter_u64_t	cntr;		/* Pointer to rule counters	*/
2773f7d90bmelifaro	uint32_t	timestamp;	/* tv_sec of last match		*/
2783f7d90bmelifaro	uint32_t	id;		/* rule id			*/
2795b47ecemelifaro	uint32_t	cached_id;	/* used by jump_fast		*/
2805b47ecemelifaro	uint32_t	cached_pos;	/* used by jump_fast		*/
281285cf94ae	uint32_t	refcnt;		/* number of references		*/
2823f7d90bmelifaro
283285cf94ae	struct ip_fw	*next;		/* linked list of deleted rules */
2843f7d90bmelifaro	ipfw_insn	cmd[1];		/* storage for commands		*/
2853f7d90bmelifaro};
2863f7d90bmelifaro
2872750834melifaro#define	IPFW_RULE_CNTR_SIZE	(2 * sizeof(uint64_t))
288bd97071melifaro
2893f7d90bmelifaro#endif
2903f7d90bmelifaro
291c4e6c7aluigistruct ip_fw_chain {
2926758ecbluigi	struct ip_fw	**map;		/* array of rule ptrs to ease lookup */
293c32089emelifaro	uint32_t	id;		/* ruleset id */
294c32089emelifaro	int		n_rules;	/* number of static rules */
295631be4dmelifaro	void		*tablestate;	/* runtime table info */
296a1eca3cmelifaro	void		*valuestate;	/* runtime table value info */
297c7e5ac0melifaro	int		*idxmap;	/* skipto array of rules */
2989f3d7ccmelifaro	void		**srvstate;	/* runtime service mappings */
2995ceeac4luigi#if defined( __linux__ ) || defined( _WIN32 )
3005ceeac4luigi	spinlock_t rwmtx;
301003a6bcglebius#else
302003a6bcglebius	struct rmlock	rwmtx;
303c32089emelifaro#endif
3043f7d90bmelifaro	int		static_len;	/* total len of static rules (v0) */
305c32089emelifaro	uint32_t	gencnt;		/* NAT generation count */
3069f3d7ccmelifaro	LIST_HEAD(nat_list, cfg_nat) nat;       /* list of nat entries */
307c32089emelifaro	struct ip_fw	*default_rule;
30801ec53emelifaro	struct tables_config *tblcfg;	/* tables module data */
309fa3f38amelifaro	void		*ifcfg;		/* interface module data */
310c7e5ac0melifaro	int		*idxmap_back;	/* standby skipto array of rules */
3119f3d7ccmelifaro	struct namedobj_instance	*srvmap; /* cfg name->number mappings */
312c32089emelifaro#if defined( __linux__ ) || defined( _WIN32 )
313c32089emelifaro	spinlock_t uh_lock;
314c32089emelifaro#else
3152043aecluigi	struct rwlock	uh_lock;	/* lock for upper half */
3165ceeac4luigi#endif
317c4e6c7aluigi};
318c4e6c7aluigi
319a1eca3cmelifaro/* 64-byte structure representing multi-field table value */
320a1eca3cmelifarostruct table_value {
321a1eca3cmelifaro	uint32_t	tag;		/* O_TAG/O_TAGGED */
322a1eca3cmelifaro	uint32_t	pipe;		/* O_PIPE/O_QUEUE */
323a1eca3cmelifaro	uint16_t	divert;		/* O_DIVERT/O_TEE */
324a1eca3cmelifaro	uint16_t	skipto;		/* skipto, CALLRET */
325a1eca3cmelifaro	uint32_t	netgraph;	/* O_NETGRAPH/O_NGTEE */
326a1eca3cmelifaro	uint32_t	fib;		/* O_SETFIB */
327a1eca3cmelifaro	uint32_t	nat;		/* O_NAT */
328a1eca3cmelifaro	uint32_t	nh4;
329a1eca3cmelifaro	uint8_t		dscp;
3308ee4f19ae	uint8_t		spare0;
3318ee4f19ae	uint16_t	spare1;
332a1eca3cmelifaro	/* -- 32 bytes -- */
333a1eca3cmelifaro	struct in6_addr	nh6;
334a1eca3cmelifaro	uint32_t	limit;		/* O_LIMIT */
3358ee4f19ae	uint32_t	zoneid;		/* scope zone id for nh6 */
336a1eca3cmelifaro	uint64_t	refcnt;		/* Number of references */
337a1eca3cmelifaro};
338a1eca3cmelifaro
339fa3f38amelifaro
340fa3f38amelifarostruct named_object {
341fa3f38amelifaro	TAILQ_ENTRY(named_object)	nn_next;	/* namehash */
342fa3f38amelifaro	TAILQ_ENTRY(named_object)	nv_next;	/* valuehash */
343fa3f38amelifaro	char			*name;	/* object name */
344c1f7aadae	uint16_t		etlv;	/* Export TLV id */
345c1f7aadae	uint8_t			subtype;/* object subtype within class */
346f79f8e9ae	uint8_t			set;	/* set object belongs to */
347fa3f38amelifaro	uint16_t		kidx;	/* object kernel index */
348f79f8e9ae	uint16_t		spare;
349f79f8e9ae	uint32_t		ocnt;	/* object counter for internal use */
350fa3f38amelifaro	uint32_t		refcnt;	/* number of references */
351fa3f38amelifaro};
352fa3f38amelifaroTAILQ_HEAD(namedobjects_head, named_object);
353fa3f38amelifaro
354c4e6c7aluigistruct sockopt;	/* used by tcp_var.h */
3559ff102amelifarostruct sockopt_data {
3569ff102amelifaro	caddr_t		kbuf;		/* allocated buffer */
3579ff102amelifaro	size_t		ksize;		/* given buffer size */
3589ff102amelifaro	size_t		koff;		/* data already used */
3599ff102amelifaro	size_t		kavail;		/* number of bytes available */
3609ff102amelifaro	size_t		ktotal;		/* total bytes pushed */
3619ff102amelifaro	struct sockopt	*sopt;		/* socket data */
362a1876c6melifaro	caddr_t		sopt_val;	/* sopt user buffer */
3639ff102amelifaro	size_t		valsize;	/* original data size */
3649ff102amelifaro};
365c4e6c7aluigi
366fa3f38amelifarostruct ipfw_ifc;
367fa3f38amelifaro
368fa3f38amelifarotypedef void (ipfw_ifc_cb)(struct ip_fw_chain *ch, void *cbdata,
369fa3f38amelifaro    uint16_t ifindex);
370fa3f38amelifaro
371fa3f38amelifarostruct ipfw_iface {
372fa3f38amelifaro	struct named_object	no;
373fa3f38amelifaro	char ifname[64];
374fa3f38amelifaro	int resolved;
375fa3f38amelifaro	uint16_t ifindex;
376fa3f38amelifaro	uint16_t spare;
377fa3f38amelifaro	uint64_t gencnt;
378fa3f38amelifaro	TAILQ_HEAD(, ipfw_ifc)	consumers;
379fa3f38amelifaro};
380fa3f38amelifaro
381fa3f38amelifarostruct ipfw_ifc {
382fa3f38amelifaro	TAILQ_ENTRY(ipfw_ifc)	next;
383fa3f38amelifaro	struct ipfw_iface	*iface;
384fa3f38amelifaro	ipfw_ifc_cb		*cb;
385fa3f38amelifaro	void			*cbdata;
386fa3f38amelifaro};
387fa3f38amelifaro
3886a45724melifaro/* Macro for working with various counters */
3893f7d90bmelifaro#define	IPFW_INC_RULE_COUNTER(_cntr, _bytes)	do {	\
3903f7d90bmelifaro	counter_u64_add((_cntr)->cntr, 1);		\
3913f7d90bmelifaro	counter_u64_add((_cntr)->cntr + 1, _bytes);	\
3923f7d90bmelifaro	if ((_cntr)->timestamp != time_uptime)		\
3933f7d90bmelifaro		(_cntr)->timestamp = time_uptime;	\
3943f7d90bmelifaro	} while (0)
3953f7d90bmelifaro
3963f7d90bmelifaro#define	IPFW_INC_DYN_COUNTER(_cntr, _bytes)	do {		\
3973f7d90bmelifaro	(_cntr)->pcnt++;				\
3983f7d90bmelifaro	(_cntr)->bcnt += _bytes;			\
3993f7d90bmelifaro	} while (0)
4003f7d90bmelifaro
4013f7d90bmelifaro#define	IPFW_ZERO_RULE_COUNTER(_cntr) do {		\
4023f7d90bmelifaro	counter_u64_zero((_cntr)->cntr);		\
4033f7d90bmelifaro	counter_u64_zero((_cntr)->cntr + 1);		\
4043f7d90bmelifaro	(_cntr)->timestamp = 0;				\
4053f7d90bmelifaro	} while (0)
4063f7d90bmelifaro
4073f7d90bmelifaro#define	IPFW_ZERO_DYN_COUNTER(_cntr) do {		\
4083f7d90bmelifaro	(_cntr)->pcnt = 0;				\
4093f7d90bmelifaro	(_cntr)->bcnt = 0;				\
4103f7d90bmelifaro	} while (0)
4113f7d90bmelifaro
412a1eca3cmelifaro#define	TARG_VAL(ch, k, f)	((struct table_value *)((ch)->valuestate))[k].f
413a1eca3cmelifaro#define	IP_FW_ARG_TABLEARG(ch, a, f)	\
414a1eca3cmelifaro	(((a) == IP_FW_TARG) ? TARG_VAL(ch, tablearg, f) : (a))
415c4e6c7aluigi/*
416c4e6c7aluigi * The lock is heavily used by ip_fw2.c (the main file) and ip_fw_nat.c
417c4e6c7aluigi * so the variable and the macros must be here.
418c4e6c7aluigi */
419c4e6c7aluigi
420e2a6d82melifaro#if defined( __linux__ ) || defined( _WIN32 )
4212043aecluigi#define	IPFW_LOCK_INIT(_chain) do {			\
4222043aecluigi	rw_init(&(_chain)->rwmtx, "IPFW static rules");	\
4232043aecluigi	rw_init(&(_chain)->uh_lock, "IPFW UH lock");	\
4242043aecluigi	} while (0)
4252043aecluigi
4262043aecluigi#define	IPFW_LOCK_DESTROY(_chain) do {			\
4272043aecluigi	rw_destroy(&(_chain)->rwmtx);			\
4282043aecluigi	rw_destroy(&(_chain)->uh_lock);			\
4292043aecluigi	} while (0)
4302043aecluigi
431e570ee3melifaro#define	IPFW_RLOCK_ASSERT(_chain)	rw_assert(&(_chain)->rwmtx, RA_RLOCKED)
432c4e6c7aluigi#define	IPFW_WLOCK_ASSERT(_chain)	rw_assert(&(_chain)->rwmtx, RA_WLOCKED)
433c4e6c7aluigi
434e2a6d82melifaro#define	IPFW_RLOCK_TRACKER
43523037c2ae#define	IPFW_RLOCK(p)			rw_rlock(&(p)->rwmtx)
43623037c2ae#define	IPFW_RUNLOCK(p)			rw_runlock(&(p)->rwmtx)
43723037c2ae#define	IPFW_WLOCK(p)			rw_wlock(&(p)->rwmtx)
43823037c2ae#define	IPFW_WUNLOCK(p)			rw_wunlock(&(p)->rwmtx)
43923037c2ae#define	IPFW_PF_RLOCK(p)		IPFW_RLOCK(p)
44023037c2ae#define	IPFW_PF_RUNLOCK(p)		IPFW_RUNLOCK(p)
441e2a6d82melifaro#else /* FreeBSD */
442e2a6d82melifaro#define	IPFW_LOCK_INIT(_chain) do {			\
443003a6bcglebius	rm_init_flags(&(_chain)->rwmtx, "IPFW static rules", RM_RECURSE); \
444e2a6d82melifaro	rw_init(&(_chain)->uh_lock, "IPFW UH lock");	\
445e2a6d82melifaro	} while (0)
446e2a6d82melifaro
447e2a6d82melifaro#define	IPFW_LOCK_DESTROY(_chain) do {			\
448003a6bcglebius	rm_destroy(&(_chain)->rwmtx);			\
449e2a6d82melifaro	rw_destroy(&(_chain)->uh_lock);			\
450e2a6d82melifaro	} while (0)
451e2a6d82melifaro
452003a6bcglebius#define	IPFW_RLOCK_ASSERT(_chain)	rm_assert(&(_chain)->rwmtx, RA_RLOCKED)
453003a6bcglebius#define	IPFW_WLOCK_ASSERT(_chain)	rm_assert(&(_chain)->rwmtx, RA_WLOCKED)
454e2a6d82melifaro
455e2a6d82melifaro#define	IPFW_RLOCK_TRACKER		struct rm_priotracker _tracker
456003a6bcglebius#define	IPFW_RLOCK(p)			rm_rlock(&(p)->rwmtx, &_tracker)
457003a6bcglebius#define	IPFW_RUNLOCK(p)			rm_runlock(&(p)->rwmtx, &_tracker)
458003a6bcglebius#define	IPFW_WLOCK(p)			rm_wlock(&(p)->rwmtx)
459003a6bcglebius#define	IPFW_WUNLOCK(p)			rm_wunlock(&(p)->rwmtx)
460003a6bcglebius#define	IPFW_PF_RLOCK(p)		IPFW_RLOCK(p)
461003a6bcglebius#define	IPFW_PF_RUNLOCK(p)		IPFW_RUNLOCK(p)
462e2a6d82melifaro#endif
463c4e6c7aluigi
464c07e3ecmelifaro#define	IPFW_UH_RLOCK_ASSERT(_chain)	rw_assert(&(_chain)->uh_lock, RA_RLOCKED)
465c07e3ecmelifaro#define	IPFW_UH_WLOCK_ASSERT(_chain)	rw_assert(&(_chain)->uh_lock, RA_WLOCKED)
4660f5a4f0melifaro#define	IPFW_UH_UNLOCK_ASSERT(_chain)	rw_assert(&(_chain)->uh_lock, RA_UNLOCKED)
467c07e3ecmelifaro
4682043aecluigi#define IPFW_UH_RLOCK(p) rw_rlock(&(p)->uh_lock)
4692043aecluigi#define IPFW_UH_RUNLOCK(p) rw_runlock(&(p)->uh_lock)
4702043aecluigi#define IPFW_UH_WLOCK(p) rw_wlock(&(p)->uh_lock)
4712043aecluigi#define IPFW_UH_WUNLOCK(p) rw_wunlock(&(p)->uh_lock)
4722043aecluigi
47301ec53emelifarostruct obj_idx {
47401ec53emelifaro	uint16_t	uidx;	/* internal index supplied by userland */
47501ec53emelifaro	uint16_t	kidx;	/* kernel object index */
47601ec53emelifaro	uint16_t	off;	/* tlv offset from rule end in 4-byte words */
4778c5ec3amelifaro	uint8_t		spare;
47801ec53emelifaro	uint8_t		type;	/* object type within its category */
47901ec53emelifaro};
48001ec53emelifaro
48101ec53emelifarostruct rule_check_info {
482377bb9dmelifaro	uint16_t	flags;		/* rule-specific check flags */
4839f3d7ccmelifaro	uint16_t	object_opcodes;	/* num of opcodes referencing objects */
4843f7d90bmelifaro	uint16_t	urule_numoff;	/* offset of rulenum in bytes */
4853f7d90bmelifaro	uint8_t		version;	/* rule version */
486377bb9dmelifaro	uint8_t		spare;
48775913ddmelifaro	ipfw_obj_ctlv	*ctlv;		/* name TLV containter */
48801ec53emelifaro	struct ip_fw	*krule;		/* resulting rule pointer */
4893f7d90bmelifaro	caddr_t		urule;		/* original rule pointer */
49001ec53emelifaro	struct obj_idx	obuf[8];	/* table references storage */
49101ec53emelifaro};
49201ec53emelifaro
4933f7d90bmelifaro/* Legacy interface support */
4943f7d90bmelifaro/*
4953f7d90bmelifaro * FreeBSD 8 export rule format
4963f7d90bmelifaro */
4973f7d90bmelifarostruct ip_fw_rule0 {
4983f7d90bmelifaro	struct ip_fw	*x_next;	/* linked list of rules		*/
4993f7d90bmelifaro	struct ip_fw	*next_rule;	/* ptr to next [skipto] rule	*/
5003f7d90bmelifaro	/* 'next_rule' is used to pass up 'set_disable' status		*/
5013f7d90bmelifaro
5023f7d90bmelifaro	uint16_t	act_ofs;	/* offset of action in 32-bit units */
5033f7d90bmelifaro	uint16_t	cmd_len;	/* # of 32-bit words in cmd	*/
504