xref: /freebsd/sys/netpfil/ipfw/nat64/nat64lsn.h (revision f7c32ed617858bcd22f8d1b03199099d50125721)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2015-2019 Yandex LLC
5  * Copyright (c) 2015 Alexander V. Chernikov <melifaro@FreeBSD.org>
6  * Copyright (c) 2015-2019 Andrey V. Elsukov <ae@FreeBSD.org>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 #ifndef	_IP_FW_NAT64LSN_H_
33 #define	_IP_FW_NAT64LSN_H_
34 
35 #include "ip_fw_nat64.h"
36 #include "nat64_translate.h"
37 
38 #define	NAT64_MIN_PORT		1024
39 struct nat64lsn_host;
40 struct nat64lsn_alias;
41 
42 struct nat64lsn_state {
43 	/* IPv6 host entry keeps hash table to speedup state lookup */
44 	CK_SLIST_ENTRY(nat64lsn_state)	entries;
45 	struct nat64lsn_host	*host;
46 
47 	struct in6_addr	ip6_dst;	/* Destination IPv6 address */
48 
49 	in_addr_t	ip_src;		/* Alias IPv4 address */
50 	in_addr_t	ip_dst;		/* Destination IPv4 address */
51 	uint16_t	dport;		/* Destination port */
52 	uint16_t	sport;		/* Source port */
53 
54 	uint32_t	hval;
55 	uint32_t	flags;		/* Internal flags */
56 	uint16_t	aport;
57 	uint16_t	timestamp;	/* last used */
58 	uint8_t		proto;
59 	uint8_t		_spare[7];
60 };
61 
62 struct nat64lsn_states_chunk {
63 	struct nat64lsn_state	state[64];
64 };
65 
66 #define	ISSET64(mask, bit)	((mask) & ((uint64_t)1 << (bit)))
67 #define	ISSET32(mask, bit)	((mask) & ((uint32_t)1 << (bit)))
68 struct nat64lsn_pg {
69 	CK_SLIST_ENTRY(nat64lsn_pg)	entries;
70 
71 	uint16_t		base_port;
72 	uint16_t		timestamp;
73 	uint8_t			proto;
74 	uint8_t			chunks_count;
75 	uint8_t			spare[2];
76 
77 	union {
78 		uint64_t	freemask64;
79 		uint32_t	freemask32[2];
80 		uint64_t	*freemask64_chunk;
81 		uint32_t	*freemask32_chunk;
82 		void		*freemask_chunk;
83 	};
84 	union {
85 		struct nat64lsn_states_chunk *states;
86 		struct nat64lsn_states_chunk **states_chunk;
87 	};
88 };
89 
90 #define	CHUNK_BY_FADDR(p, a)	((a) & ((p)->chunks_count - 1))
91 
92 #ifdef __LP64__
93 #define	FREEMASK_CHUNK(p, v)	\
94     ((p)->chunks_count == 1 ? &(p)->freemask64 : \
95 	&(p)->freemask64_chunk[CHUNK_BY_FADDR(p, v)])
96 #define	FREEMASK_BITCOUNT(pg, faddr)	\
97     bitcount64(*FREEMASK_CHUNK((pg), (faddr)))
98 #else
99 #define	FREEMASK_CHUNK(p, v)	\
100     ((p)->chunks_count == 1 ? &(p)->freemask32[0] : \
101 	&(p)->freemask32_chunk[CHUNK_BY_FADDR(p, v) * 2])
102 #define	FREEMASK_BITCOUNT(pg, faddr)	\
103     bitcount64(*(uint64_t *)FREEMASK_CHUNK((pg), (faddr)))
104 #endif /* !__LP64__ */
105 
106 struct nat64lsn_pgchunk {
107 	struct nat64lsn_pg	*pgptr[32];
108 };
109 
110 struct nat64lsn_aliaslink {
111 	CK_SLIST_ENTRY(nat64lsn_aliaslink)	alias_entries;
112 	CK_SLIST_ENTRY(nat64lsn_aliaslink)	host_entries;
113 	struct nat64lsn_alias	*alias;
114 };
115 
116 CK_SLIST_HEAD(nat64lsn_aliaslink_slist, nat64lsn_aliaslink);
117 CK_SLIST_HEAD(nat64lsn_states_slist, nat64lsn_state);
118 CK_SLIST_HEAD(nat64lsn_hosts_slist, nat64lsn_host);
119 CK_SLIST_HEAD(nat64lsn_pg_slist, nat64lsn_pg);
120 
121 struct nat64lsn_alias {
122 	struct nat64lsn_aliaslink_slist	hosts;
123 	struct nat64lsn_pg_slist	portgroups;
124 
125 	struct mtx		lock;
126 	in_addr_t		addr;	/* host byte order */
127 	uint32_t		hosts_count;
128 	uint32_t		portgroups_count;
129 	uint32_t		tcp_chunkmask;
130 	uint32_t		udp_chunkmask;
131 	uint32_t		icmp_chunkmask;
132 
133 	uint32_t		tcp_pgidx;
134 	uint32_t		udp_pgidx;
135 	uint32_t		icmp_pgidx;
136 	uint16_t		timestamp;
137 	uint16_t		spare;
138 
139 	uint32_t		tcp_pgmask[32];
140 	uint32_t		udp_pgmask[32];
141 	uint32_t		icmp_pgmask[32];
142 	struct nat64lsn_pgchunk	*tcp[32];
143 	struct nat64lsn_pgchunk	*udp[32];
144 	struct nat64lsn_pgchunk	*icmp[32];
145 
146 	/* pointer to PG that can be used for faster state allocation */
147 	struct nat64lsn_pg	*tcp_pg;
148 	struct nat64lsn_pg	*udp_pg;
149 	struct nat64lsn_pg	*icmp_pg;
150 };
151 #define	ALIAS_LOCK_INIT(p)	\
152 	mtx_init(&(p)->lock, "alias_lock", NULL, MTX_DEF)
153 #define	ALIAS_LOCK_DESTROY(p)	mtx_destroy(&(p)->lock)
154 #define	ALIAS_LOCK(p)		mtx_lock(&(p)->lock)
155 #define	ALIAS_UNLOCK(p)		mtx_unlock(&(p)->lock)
156 
157 #define	NAT64LSN_HSIZE		256
158 #define	NAT64LSN_MAX_HSIZE	4096
159 #define	NAT64LSN_HOSTS_HSIZE	1024
160 
161 struct nat64lsn_host {
162 	struct in6_addr		addr;
163 	struct nat64lsn_aliaslink_slist	aliases;
164 	struct nat64lsn_states_slist	*states_hash;
165 	CK_SLIST_ENTRY(nat64lsn_host)	entries;
166 	uint32_t		states_count;
167 	uint32_t		hval;
168 	uint32_t		flags;
169 #define	NAT64LSN_DEADHOST	1
170 #define	NAT64LSN_GROWHASH	2
171 	uint16_t		states_hashsize;
172 	uint16_t		timestamp;
173 	struct mtx		lock;
174 };
175 
176 #define	HOST_LOCK_INIT(p)	\
177 	mtx_init(&(p)->lock, "host_lock", NULL, MTX_DEF|MTX_NEW)
178 #define	HOST_LOCK_DESTROY(p)	mtx_destroy(&(p)->lock)
179 #define	HOST_LOCK(p)		mtx_lock(&(p)->lock)
180 #define	HOST_UNLOCK(p)		mtx_unlock(&(p)->lock)
181 
182 VNET_DECLARE(uint16_t, nat64lsn_eid);
183 #define	V_nat64lsn_eid		VNET(nat64lsn_eid)
184 #define	IPFW_TLV_NAT64LSN_NAME	IPFW_TLV_EACTION_NAME(V_nat64lsn_eid)
185 
186 /* Timestamp macro */
187 #define	_CT		((int)time_uptime % 65536)
188 #define	SET_AGE(x)	(x) = _CT
189 #define	GET_AGE(x)	((_CT >= (x)) ? _CT - (x): (int)65536 + _CT - (x))
190 
191 STAILQ_HEAD(nat64lsn_job_head, nat64lsn_job_item);
192 
193 struct nat64lsn_cfg {
194 	struct named_object	no;
195 
196 	struct nat64lsn_hosts_slist	*hosts_hash;
197 	struct nat64lsn_alias	*aliases;	/* array of aliases */
198 
199 	struct mtx	lock;
200 	uint32_t	hosts_hashsize;
201 	uint32_t	hash_seed;
202 
203 	uint32_t	prefix4;	/* IPv4 prefix */
204 	uint32_t	pmask4;		/* IPv4 prefix mask */
205 	uint8_t		plen4;
206 	uint8_t		nomatch_verdict;/* Return value on no-match */
207 
208 	uint32_t	hosts_count;	/* Number of items in host hash */
209 	uint32_t	states_chunks;	/* Number of states chunks per PG */
210 	uint32_t	jmaxlen;	/* Max jobqueue length */
211 	uint16_t	host_delete_delay;	/* Stale host delete delay */
212 	uint16_t	pgchunk_delete_delay;
213 	uint16_t	pg_delete_delay;	/* Stale portgroup del delay */
214 	uint16_t	st_syn_ttl;	/* TCP syn expire */
215 	uint16_t	st_close_ttl;	/* TCP fin expire */
216 	uint16_t	st_estab_ttl;	/* TCP established expire */
217 	uint16_t	st_udp_ttl;	/* UDP expire */
218 	uint16_t	st_icmp_ttl;	/* ICMP expire */
219 
220 	struct nat64_config	base;
221 #define	NAT64LSN_FLAGSMASK	(NAT64_LOG | NAT64_ALLOW_PRIVATE)
222 #define	NAT64LSN_ANYPREFIX	0x00000100
223 
224 	struct mtx		periodic_lock;
225 	struct callout		periodic;
226 	struct callout		jcallout;
227 	struct vnet		*vp;
228 	struct nat64lsn_job_head	jhead;
229 	int			jlen;
230 	char			name[64];	/* Nat instance name */
231 };
232 
233 /* CFG_LOCK protects cfg->hosts_hash from modification */
234 #define	CFG_LOCK_INIT(p)	\
235 	mtx_init(&(p)->lock, "cfg_lock", NULL, MTX_DEF)
236 #define	CFG_LOCK_DESTROY(p)	mtx_destroy(&(p)->lock)
237 #define	CFG_LOCK(p)		mtx_lock(&(p)->lock)
238 #define	CFG_UNLOCK(p)		mtx_unlock(&(p)->lock)
239 
240 #define	CALLOUT_LOCK_INIT(p)	\
241 	mtx_init(&(p)->periodic_lock, "periodic_lock", NULL, MTX_DEF)
242 #define	CALLOUT_LOCK_DESTROY(p)	mtx_destroy(&(p)->periodic_lock)
243 #define	CALLOUT_LOCK(p)		mtx_lock(&(p)->periodic_lock)
244 #define	CALLOUT_UNLOCK(p)	mtx_unlock(&(p)->periodic_lock)
245 
246 struct nat64lsn_cfg *nat64lsn_init_instance(struct ip_fw_chain *ch,
247     in_addr_t prefix, int plen);
248 void nat64lsn_destroy_instance(struct nat64lsn_cfg *cfg);
249 void nat64lsn_start_instance(struct nat64lsn_cfg *cfg);
250 void nat64lsn_init_internal(void);
251 void nat64lsn_uninit_internal(void);
252 int ipfw_nat64lsn(struct ip_fw_chain *ch, struct ip_fw_args *args,
253     ipfw_insn *cmd, int *done);
254 
255 #endif /* _IP_FW_NAT64LSN_H_ */
256