xref: /freebsd/sys/netpfil/ipfw/nat64/nat64lsn.h (revision a64729f5077d77e13b9497cb33ecb3c82e606ee8)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
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 
30 #ifndef	_IP_FW_NAT64LSN_H_
31 #define	_IP_FW_NAT64LSN_H_
32 
33 #include "ip_fw_nat64.h"
34 #include "nat64_translate.h"
35 
36 #define	NAT64_MIN_PORT		1024
37 struct nat64lsn_host;
38 struct nat64lsn_alias;
39 
40 struct nat64lsn_state {
41 	/* IPv6 host entry keeps hash table to speedup state lookup */
42 	CK_SLIST_ENTRY(nat64lsn_state)	entries;
43 	struct nat64lsn_host	*host;
44 
45 	struct in6_addr	ip6_dst;	/* Destination IPv6 address */
46 
47 	in_addr_t	ip_src;		/* Alias IPv4 address */
48 	in_addr_t	ip_dst;		/* Destination IPv4 address */
49 	uint16_t	dport;		/* Destination port */
50 	uint16_t	sport;		/* Source port */
51 
52 	uint32_t	hval;
53 	uint32_t	flags;		/* Internal flags */
54 	uint16_t	aport;
55 	uint16_t	timestamp;	/* last used */
56 	uint8_t		proto;
57 	uint8_t		_spare[7];
58 };
59 
60 struct nat64lsn_states_chunk {
61 	struct nat64lsn_state	state[64];
62 };
63 
64 #define	ISSET64(mask, bit)	((mask) & ((uint64_t)1 << (bit)))
65 #define	ISSET32(mask, bit)	((mask) & ((uint32_t)1 << (bit)))
66 struct nat64lsn_pg {
67 	CK_SLIST_ENTRY(nat64lsn_pg)	entries;
68 
69 	uint16_t		base_port;
70 	uint16_t		timestamp;
71 	uint8_t			proto;
72 	uint8_t			chunks_count;
73 	uint8_t			spare[2];
74 
75 	union {
76 		uint64_t	freemask64;
77 		uint32_t	freemask32[2];
78 		uint64_t	*freemask64_chunk;
79 		uint32_t	*freemask32_chunk;
80 		void		*freemask_chunk;
81 	};
82 	union {
83 		struct nat64lsn_states_chunk *states;
84 		struct nat64lsn_states_chunk **states_chunk;
85 	};
86 };
87 
88 #define	CHUNK_BY_FADDR(p, a)	((a) & ((p)->chunks_count - 1))
89 
90 #ifdef __LP64__
91 #define	FREEMASK_CHUNK(p, v)	\
92     ((p)->chunks_count == 1 ? &(p)->freemask64 : \
93 	&(p)->freemask64_chunk[CHUNK_BY_FADDR(p, v)])
94 #define	FREEMASK_BITCOUNT(pg, faddr)	\
95     bitcount64(*FREEMASK_CHUNK((pg), (faddr)))
96 #else
97 #define	FREEMASK_CHUNK(p, v)	\
98     ((p)->chunks_count == 1 ? &(p)->freemask32[0] : \
99 	&(p)->freemask32_chunk[CHUNK_BY_FADDR(p, v) * 2])
100 #define	FREEMASK_BITCOUNT(pg, faddr)	\
101     bitcount64(*(uint64_t *)FREEMASK_CHUNK((pg), (faddr)))
102 #endif /* !__LP64__ */
103 
104 struct nat64lsn_pgchunk {
105 	struct nat64lsn_pg	*pgptr[32];
106 };
107 
108 struct nat64lsn_aliaslink {
109 	CK_SLIST_ENTRY(nat64lsn_aliaslink)	alias_entries;
110 	CK_SLIST_ENTRY(nat64lsn_aliaslink)	host_entries;
111 	struct nat64lsn_alias	*alias;
112 };
113 
114 CK_SLIST_HEAD(nat64lsn_aliaslink_slist, nat64lsn_aliaslink);
115 CK_SLIST_HEAD(nat64lsn_states_slist, nat64lsn_state);
116 CK_SLIST_HEAD(nat64lsn_hosts_slist, nat64lsn_host);
117 CK_SLIST_HEAD(nat64lsn_pg_slist, nat64lsn_pg);
118 
119 struct nat64lsn_alias {
120 	struct nat64lsn_aliaslink_slist	hosts;
121 	struct nat64lsn_pg_slist	portgroups;
122 
123 	struct mtx		lock;
124 	in_addr_t		addr;	/* host byte order */
125 	uint32_t		hosts_count;
126 	uint32_t		portgroups_count;
127 	uint32_t		tcp_chunkmask;
128 	uint32_t		udp_chunkmask;
129 	uint32_t		icmp_chunkmask;
130 
131 	uint32_t		tcp_pgidx;
132 	uint32_t		udp_pgidx;
133 	uint32_t		icmp_pgidx;
134 	uint16_t		timestamp;
135 	uint16_t		spare;
136 
137 	uint32_t		tcp_pgmask[32];
138 	uint32_t		udp_pgmask[32];
139 	uint32_t		icmp_pgmask[32];
140 	struct nat64lsn_pgchunk	*tcp[32];
141 	struct nat64lsn_pgchunk	*udp[32];
142 	struct nat64lsn_pgchunk	*icmp[32];
143 
144 	/* pointer to PG that can be used for faster state allocation */
145 	struct nat64lsn_pg	*tcp_pg;
146 	struct nat64lsn_pg	*udp_pg;
147 	struct nat64lsn_pg	*icmp_pg;
148 };
149 #define	ALIAS_LOCK_INIT(p)	\
150 	mtx_init(&(p)->lock, "alias_lock", NULL, MTX_DEF)
151 #define	ALIAS_LOCK_DESTROY(p)	mtx_destroy(&(p)->lock)
152 #define	ALIAS_LOCK(p)		mtx_lock(&(p)->lock)
153 #define	ALIAS_UNLOCK(p)		mtx_unlock(&(p)->lock)
154 
155 #define	NAT64LSN_HSIZE		256
156 #define	NAT64LSN_MAX_HSIZE	4096
157 #define	NAT64LSN_HOSTS_HSIZE	1024
158 
159 struct nat64lsn_host {
160 	struct in6_addr		addr;
161 	struct nat64lsn_aliaslink_slist	aliases;
162 	struct nat64lsn_states_slist	*states_hash;
163 	CK_SLIST_ENTRY(nat64lsn_host)	entries;
164 	uint32_t		states_count;
165 	uint32_t		hval;
166 	uint32_t		flags;
167 #define	NAT64LSN_DEADHOST	1
168 #define	NAT64LSN_GROWHASH	2
169 	uint16_t		states_hashsize;
170 	uint16_t		timestamp;
171 	struct mtx		lock;
172 };
173 
174 #define	HOST_LOCK_INIT(p)	\
175 	mtx_init(&(p)->lock, "host_lock", NULL, MTX_DEF|MTX_NEW)
176 #define	HOST_LOCK_DESTROY(p)	mtx_destroy(&(p)->lock)
177 #define	HOST_LOCK(p)		mtx_lock(&(p)->lock)
178 #define	HOST_UNLOCK(p)		mtx_unlock(&(p)->lock)
179 
180 VNET_DECLARE(uint16_t, nat64lsn_eid);
181 #define	V_nat64lsn_eid		VNET(nat64lsn_eid)
182 #define	IPFW_TLV_NAT64LSN_NAME	IPFW_TLV_EACTION_NAME(V_nat64lsn_eid)
183 
184 /* Timestamp macro */
185 #define	_CT		((int)time_uptime % 65536)
186 #define	SET_AGE(x)	(x) = _CT
187 #define	GET_AGE(x)	((_CT >= (x)) ? _CT - (x): (int)65536 + _CT - (x))
188 
189 STAILQ_HEAD(nat64lsn_job_head, nat64lsn_job_item);
190 
191 struct nat64lsn_cfg {
192 	struct named_object	no;
193 
194 	struct nat64lsn_hosts_slist	*hosts_hash;
195 	struct nat64lsn_alias	*aliases;	/* array of aliases */
196 
197 	struct mtx	lock;
198 	uint32_t	hosts_hashsize;
199 	uint32_t	hash_seed;
200 
201 	uint32_t	prefix4;	/* IPv4 prefix */
202 	uint32_t	pmask4;		/* IPv4 prefix mask */
203 	uint8_t		plen4;
204 	uint8_t		nomatch_verdict;/* Return value on no-match */
205 
206 	uint32_t	hosts_count;	/* Number of items in host hash */
207 	uint32_t	states_chunks;	/* Number of states chunks per PG */
208 	uint32_t	jmaxlen;	/* Max jobqueue length */
209 	uint16_t	host_delete_delay;	/* Stale host delete delay */
210 	uint16_t	pgchunk_delete_delay;
211 	uint16_t	pg_delete_delay;	/* Stale portgroup del delay */
212 	uint16_t	st_syn_ttl;	/* TCP syn expire */
213 	uint16_t	st_close_ttl;	/* TCP fin expire */
214 	uint16_t	st_estab_ttl;	/* TCP established expire */
215 	uint16_t	st_udp_ttl;	/* UDP expire */
216 	uint16_t	st_icmp_ttl;	/* ICMP expire */
217 
218 	struct nat64_config	base;
219 #define	NAT64LSN_FLAGSMASK	(NAT64_LOG | NAT64_ALLOW_PRIVATE)
220 #define	NAT64LSN_ANYPREFIX	0x00000100
221 
222 	struct mtx		periodic_lock;
223 	struct callout		periodic;
224 	struct callout		jcallout;
225 	struct vnet		*vp;
226 	struct nat64lsn_job_head	jhead;
227 	int			jlen;
228 	char			name[64];	/* Nat instance name */
229 };
230 
231 /* CFG_LOCK protects cfg->hosts_hash from modification */
232 #define	CFG_LOCK_INIT(p)	\
233 	mtx_init(&(p)->lock, "cfg_lock", NULL, MTX_DEF)
234 #define	CFG_LOCK_DESTROY(p)	mtx_destroy(&(p)->lock)
235 #define	CFG_LOCK(p)		mtx_lock(&(p)->lock)
236 #define	CFG_UNLOCK(p)		mtx_unlock(&(p)->lock)
237 
238 #define	CALLOUT_LOCK_INIT(p)	\
239 	mtx_init(&(p)->periodic_lock, "periodic_lock", NULL, MTX_DEF)
240 #define	CALLOUT_LOCK_DESTROY(p)	mtx_destroy(&(p)->periodic_lock)
241 #define	CALLOUT_LOCK(p)		mtx_lock(&(p)->periodic_lock)
242 #define	CALLOUT_UNLOCK(p)	mtx_unlock(&(p)->periodic_lock)
243 
244 struct nat64lsn_cfg *nat64lsn_init_instance(struct ip_fw_chain *ch,
245     in_addr_t prefix, int plen);
246 void nat64lsn_destroy_instance(struct nat64lsn_cfg *cfg);
247 void nat64lsn_start_instance(struct nat64lsn_cfg *cfg);
248 void nat64lsn_init_internal(void);
249 void nat64lsn_uninit_internal(void);
250 int ipfw_nat64lsn(struct ip_fw_chain *ch, struct ip_fw_args *args,
251     ipfw_insn *cmd, int *done);
252 
253 #endif /* _IP_FW_NAT64LSN_H_ */
254