1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2020 Yandex LLC
5 * Copyright (c) 2020 Andrey V. Elsukov <ae@FreeBSD.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#pragma D depends_on provider ipfw
30
31/* ipfw_chk() return values */
32#pragma D binding "1.0" IP_FW_PASS
33inline int IP_FW_PASS = 	0;
34#pragma D binding "1.0" IP_FW_DENY
35inline int IP_FW_DENY = 	1;
36#pragma D binding "1.0" IP_FW_DIVERT
37inline int IP_FW_DIVERT =	2;
38#pragma D binding "1.0" IP_FW_TEE
39inline int IP_FW_TEE =		3;
40#pragma D binding "1.0" IP_FW_DUMMYNET
41inline int IP_FW_DUMMYNET =	4;
42#pragma D binding "1.0" IP_FW_NETGRAPH
43inline int IP_FW_NETGRAPH =	5;
44#pragma D binding "1.0" IP_FW_NGTEE
45inline int IP_FW_NGTEE =	6;
46#pragma D binding "1.0" IP_FW_NAT
47inline int IP_FW_NAT =		7;
48#pragma D binding "1.0" IP_FW_REASS
49inline int IP_FW_REASS =	8;
50#pragma D binding "1.0" IP_FW_NAT64
51inline int IP_FW_NAT64 =	9;
52
53#pragma D binding "1.0" ipfw_retcodes
54inline string ipfw_retcodes[int ret] =
55	ret == IP_FW_PASS ? "PASS" :
56	ret == IP_FW_DENY ? "DENY" :
57	ret == IP_FW_DIVERT ? "DIVERT" :
58	ret == IP_FW_TEE ? "TEE" :
59	ret == IP_FW_DUMMYNET ? "DUMMYNET" :
60	ret == IP_FW_NETGRAPH ? "NETGRAPH" :
61	ret == IP_FW_NGTEE ? "NGTEE" :
62	ret == IP_FW_NAT ? "NAT" :
63	ret == IP_FW_REASS ? "REASS" :
64	ret == IP_FW_NAT64 ? "NAT64" :
65	"<unknown>";
66
67/* ip_fw_args flags */
68#pragma D binding "1.0" IPFW_ARGS_ETHER
69inline int IPFW_ARGS_ETHER =	0x00010000; /* valid ethernet header */
70#pragma D binding "1.0" IPFW_ARGS_NH4
71inline int IPFW_ARGS_NH4 =	0x00020000; /* IPv4 next hop in hopstore */
72#pragma D binding "1.0" IPFW_ARGS_NH6
73inline int IPFW_ARGS_NH6 =	0x00040000; /* IPv6 next hop in hopstore */
74#pragma D binding "1.0" IPFW_ARGS_NH4PTR
75inline int IPFW_ARGS_NH4PTR =	0x00080000; /* IPv4 next hop in next_hop */
76#pragma D binding "1.0" IPFW_ARGS_NH6PTR
77inline int IPFW_ARGS_NH6PTR =	0x00100000; /* IPv6 next hop in next_hop6 */
78#pragma D binding "1.0" IPFW_ARGS_REF
79inline int IPFW_ARGS_REF =	0x00200000; /* valid ipfw_rule_ref	*/
80#pragma D binding "1.0" IPFW_ARGS_IN
81inline int IPFW_ARGS_IN =	0x00400000; /* called on input */
82#pragma D binding "1.0" IPFW_ARGS_OUT
83inline int IPFW_ARGS_OUT =	0x00800000; /* called on output */
84#pragma D binding "1.0" IPFW_ARGS_IP4
85inline int IPFW_ARGS_IP4 =	0x01000000; /* belongs to v4 ISR */
86#pragma D binding "1.0" IPFW_ARGS_IP6
87inline int IPFW_ARGS_IP6 =	0x02000000; /* belongs to v6 ISR */
88#pragma D binding "1.0" IPFW_ARGS_DROP
89inline int IPFW_ARGS_DROP =	0x04000000; /* drop it (dummynet) */
90#pragma D binding "1.0" IPFW_ARGS_LENMASK
91inline int IPFW_ARGS_LENMASK =	0x0000ffff; /* length of data in *mem */
92
93/* ipfw_rule_ref.info */
94#pragma D binding "1.0" IPFW_INFO_MASK
95inline int IPFW_INFO_MASK =	0x0000ffff;
96#pragma D binding "1.0" IPFW_INFO_OUT
97inline int IPFW_INFO_OUT =	0x00000000;
98#pragma D binding "1.0" IPFW_INFO_IN
99inline int IPFW_INFO_IN =	0x80000000;
100#pragma D binding "1.0" IPFW_ONEPASS
101inline int IPFW_ONEPASS =	0x40000000;
102#pragma D binding "1.0" IPFW_IS_MASK
103inline int IPFW_IS_MASK =	0x30000000;
104#pragma D binding "1.0" IPFW_IS_DIVERT
105inline int IPFW_IS_DIVERT =	0x20000000;
106#pragma D binding "1.0" IPFW_IS_DUMMYNET
107inline int IPFW_IS_DUMMYNET =	0x10000000;
108#pragma D binding "1.0" IPFW_IS_PIPE
109inline int IPFW_IS_PIPE =	0x08000000;
110
111typedef struct ipfw_match_info {
112	uint32_t	flags;
113
114	struct mbuf	*m;
115	void		*mem;
116	struct inpcb	*inp;
117	struct ifnet	*ifp;
118	struct ip	*ipp;
119	struct ip6_hdr	*ip6p;
120
121	/* flow id */
122	uint8_t		addr_type;
123	uint8_t		proto;
124	uint8_t		proto_flags;
125	uint16_t	fib;	/* XXX */
126	in_addr_t	dst_ip;	/* in network byte order */
127	in_addr_t	src_ip;	/* in network byte order */
128	struct in6_addr	dst_ip6;
129	struct in6_addr	src_ip6;
130
131	uint16_t	dst_port; /* in host byte order */
132	uint16_t	src_port; /* in host byte order */
133
134	uint32_t	flowid;	/* IPv6 flowid */
135	uint32_t	extra;
136
137	/* ipfw_rule_ref */
138	uint32_t	slot;
139	uint32_t	rulenum;
140	uint32_t	rule_id;
141	uint32_t	chain_id;
142	uint32_t	match_info;
143} ipfw_match_info_t;
144
145#pragma D binding "1.0" translator
146translator ipfw_match_info_t < struct ip_fw_args *p > {
147	flags =		p->flags;
148	m =		(p->flags & IPFW_ARGS_LENMASK) ? NULL : p->m;
149	mem =		(p->flags & IPFW_ARGS_LENMASK) ? p->mem : NULL;
150	inp =		p->inp;
151	ifp =		p->ifp;
152	/* Initialize IP pointer corresponding to addr_type */
153	ipp =		(p->flags & IPFW_ARGS_IP4) ?
154	    (p->flags & IPFW_ARGS_LENMASK) ? (struct ip *)p->mem :
155	    (p->m != NULL) ? (struct ip *)p->m->m_data : NULL : NULL;
156	ip6p =		(p->flags & IPFW_ARGS_IP6) ?
157	    (p->flags & IPFW_ARGS_LENMASK) ? (struct ip6_hdr *)p->mem :
158	    (p->m != NULL) ? (struct ip6_hdr *)p->m->m_data : NULL : NULL;
159
160	/* fill f_id fields */
161	addr_type =	p->f_id.addr_type;
162	proto =		p->f_id.proto;
163	proto_flags =	p->f_id._flags;
164
165	/* f_id.fib keeps truncated fibnum, use mbuf's fibnum if possible */
166	fib =		p->m != NULL ? p->m->m_pkthdr.fibnum : p->f_id.fib;
167
168	/*
169	 * ipfw_chk() keeps IPv4 addresses in host byte order. But for
170	 * dtrace script it is useful to have them in network byte order,
171	 * because inet_ntoa() uses address in network byte order.
172	 */
173	dst_ip =	htonl(p->f_id.dst_ip);
174	src_ip =	htonl(p->f_id.src_ip);
175
176	dst_ip6 =	p->f_id.dst_ip6;
177	src_ip6 =	p->f_id.src_ip6;
178
179	dst_port =	p->f_id.dst_port;
180	src_port =	p->f_id.src_port;
181
182	flowid =	p->f_id.flow_id6;
183	extra = 	p->f_id.extra;
184
185	/* ipfw_rule_ref */
186	slot =		(p->flags & IPFW_ARGS_REF) ? p->rule.slot : 0;
187	rulenum =	(p->flags & IPFW_ARGS_REF) ? p->rule.rulenum : 0;
188	rule_id =	(p->flags & IPFW_ARGS_REF) ? p->rule.rule_id : 0;
189	chain_id =	(p->flags & IPFW_ARGS_REF) ? p->rule.chain_id : 0;
190	match_info =	(p->flags & IPFW_ARGS_REF) ? p->rule.info : 0;
191};
192
193typedef struct ipfw_rule_info {
194	uint16_t	act_ofs;
195	uint16_t	cmd_len;
196	uint32_t	rulenum;
197	uint8_t		flags;
198	uint8_t		set;
199	uint32_t	rule_id;
200	uint32_t	cached_id;
201	uint32_t	cached_pos;
202	uint32_t	refcnt;
203} ipfw_rule_info_t;
204
205#pragma D binding "1.0" translator
206translator ipfw_rule_info_t < struct ip_fw *r > {
207	act_ofs =	r->act_ofs;
208	cmd_len =	r->cmd_len;
209	rulenum =	r->rulenum;
210	flags =		r->flags;
211	set =		r->set;
212	rule_id =	r->id;
213	cached_id =	r->cache.id;
214	cached_pos =	r->cache.pos;
215	refcnt =	r->refcnt;
216};
217
218