xref: /freebsd/sys/netpfil/ipfw/nat64/nat64lsn.c (revision 62cfcf62f627e5093fb37026a6d8c98e4d2ef04c)
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) 2016-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 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/counter.h>
36 #include <sys/ck.h>
37 #include <sys/epoch.h>
38 #include <sys/errno.h>
39 #include <sys/hash.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/module.h>
45 #include <sys/rmlock.h>
46 #include <sys/socket.h>
47 #include <sys/syslog.h>
48 #include <sys/sysctl.h>
49 
50 #include <net/if.h>
51 #include <net/if_var.h>
52 #include <net/if_pflog.h>
53 #include <net/pfil.h>
54 
55 #include <netinet/in.h>
56 #include <netinet/ip.h>
57 #include <netinet/ip_var.h>
58 #include <netinet/ip_fw.h>
59 #include <netinet/ip6.h>
60 #include <netinet/icmp6.h>
61 #include <netinet/ip_icmp.h>
62 #include <netinet/tcp.h>
63 #include <netinet/udp.h>
64 #include <netinet6/in6_var.h>
65 #include <netinet6/ip6_var.h>
66 #include <netinet6/ip_fw_nat64.h>
67 
68 #include <netpfil/ipfw/ip_fw_private.h>
69 #include <netpfil/pf/pf.h>
70 
71 #include "nat64lsn.h"
72 
73 MALLOC_DEFINE(M_NAT64LSN, "NAT64LSN", "NAT64LSN");
74 
75 #define	NAT64LSN_EPOCH_ENTER(et)  NET_EPOCH_ENTER(et)
76 #define	NAT64LSN_EPOCH_EXIT(et)   NET_EPOCH_EXIT(et)
77 #define	NAT64LSN_EPOCH_ASSERT()   NET_EPOCH_ASSERT()
78 #define	NAT64LSN_EPOCH_CALL(c, f) NET_EPOCH_CALL((f), (c))
79 
80 static uma_zone_t nat64lsn_host_zone;
81 static uma_zone_t nat64lsn_pgchunk_zone;
82 static uma_zone_t nat64lsn_pg_zone;
83 static uma_zone_t nat64lsn_aliaslink_zone;
84 static uma_zone_t nat64lsn_state_zone;
85 static uma_zone_t nat64lsn_job_zone;
86 
87 static void nat64lsn_periodic(void *data);
88 #define	PERIODIC_DELAY		4
89 #define	NAT64_LOOKUP(chain, cmd)	\
90 	(struct nat64lsn_cfg *)SRV_OBJECT((chain), (cmd)->arg1)
91 /*
92  * Delayed job queue, used to create new hosts
93  * and new portgroups
94  */
95 enum nat64lsn_jtype {
96 	JTYPE_NEWHOST = 1,
97 	JTYPE_NEWPORTGROUP,
98 	JTYPE_DESTROY,
99 };
100 
101 struct nat64lsn_job_item {
102 	STAILQ_ENTRY(nat64lsn_job_item)	entries;
103 	enum nat64lsn_jtype	jtype;
104 
105 	union {
106 		struct { /* used by JTYPE_NEWHOST, JTYPE_NEWPORTGROUP */
107 			struct mbuf		*m;
108 			struct nat64lsn_host	*host;
109 			struct nat64lsn_state	*state;
110 			uint32_t		src6_hval;
111 			uint32_t		state_hval;
112 			struct ipfw_flow_id	f_id;
113 			in_addr_t		faddr;
114 			uint16_t		port;
115 			uint8_t			proto;
116 			uint8_t			done;
117 		};
118 		struct { /* used by JTYPE_DESTROY */
119 			struct nat64lsn_hosts_slist	hosts;
120 			struct nat64lsn_pg_slist	portgroups;
121 			struct nat64lsn_pgchunk		*pgchunk;
122 			struct epoch_context		epoch_ctx;
123 		};
124 	};
125 };
126 
127 static struct mtx jmtx;
128 #define	JQUEUE_LOCK_INIT()	mtx_init(&jmtx, "qlock", NULL, MTX_DEF)
129 #define	JQUEUE_LOCK_DESTROY()	mtx_destroy(&jmtx)
130 #define	JQUEUE_LOCK()		mtx_lock(&jmtx)
131 #define	JQUEUE_UNLOCK()		mtx_unlock(&jmtx)
132 
133 static int nat64lsn_alloc_host(struct nat64lsn_cfg *cfg,
134     struct nat64lsn_job_item *ji);
135 static int nat64lsn_alloc_pg(struct nat64lsn_cfg *cfg,
136     struct nat64lsn_job_item *ji);
137 static struct nat64lsn_job_item *nat64lsn_create_job(
138     struct nat64lsn_cfg *cfg, int jtype);
139 static void nat64lsn_enqueue_job(struct nat64lsn_cfg *cfg,
140     struct nat64lsn_job_item *ji);
141 static void nat64lsn_job_destroy(epoch_context_t ctx);
142 static void nat64lsn_destroy_host(struct nat64lsn_host *host);
143 static void nat64lsn_destroy_pg(struct nat64lsn_pg *pg);
144 
145 static int nat64lsn_translate4(struct nat64lsn_cfg *cfg,
146     const struct ipfw_flow_id *f_id, struct mbuf **mp);
147 static int nat64lsn_translate6(struct nat64lsn_cfg *cfg,
148     struct ipfw_flow_id *f_id, struct mbuf **mp);
149 static int nat64lsn_translate6_internal(struct nat64lsn_cfg *cfg,
150     struct mbuf **mp, struct nat64lsn_state *state, uint8_t flags);
151 
152 #define	NAT64_BIT_TCP_FIN	0	/* FIN was seen */
153 #define	NAT64_BIT_TCP_SYN	1	/* First syn in->out */
154 #define	NAT64_BIT_TCP_ESTAB	2	/* Packet with Ack */
155 #define	NAT64_BIT_READY_IPV4	6	/* state is ready for translate4 */
156 #define	NAT64_BIT_STALE		7	/* state is going to be expired */
157 
158 #define	NAT64_FLAG_FIN		(1 << NAT64_BIT_TCP_FIN)
159 #define	NAT64_FLAG_SYN		(1 << NAT64_BIT_TCP_SYN)
160 #define	NAT64_FLAG_ESTAB	(1 << NAT64_BIT_TCP_ESTAB)
161 #define	NAT64_FLAGS_TCP	(NAT64_FLAG_SYN|NAT64_FLAG_ESTAB|NAT64_FLAG_FIN)
162 
163 #define	NAT64_FLAG_READY	(1 << NAT64_BIT_READY_IPV4)
164 #define	NAT64_FLAG_STALE	(1 << NAT64_BIT_STALE)
165 
166 static inline uint8_t
167 convert_tcp_flags(uint8_t flags)
168 {
169 	uint8_t result;
170 
171 	result = flags & (TH_FIN|TH_SYN);
172 	result |= (flags & TH_RST) >> 2; /* Treat RST as FIN */
173 	result |= (flags & TH_ACK) >> 2; /* Treat ACK as estab */
174 
175 	return (result);
176 }
177 
178 static void
179 nat64lsn_log(struct pfloghdr *plog, struct mbuf *m, sa_family_t family,
180     struct nat64lsn_state *state)
181 {
182 
183 	memset(plog, 0, sizeof(*plog));
184 	plog->length = PFLOG_REAL_HDRLEN;
185 	plog->af = family;
186 	plog->action = PF_NAT;
187 	plog->dir = PF_IN;
188 	plog->rulenr = htonl(state->ip_src);
189 	plog->subrulenr = htonl((uint32_t)(state->aport << 16) |
190 	    (state->proto << 8) | (state->ip_dst & 0xff));
191 	plog->ruleset[0] = '\0';
192 	strlcpy(plog->ifname, "NAT64LSN", sizeof(plog->ifname));
193 	ipfw_bpf_mtap2(plog, PFLOG_HDRLEN, m);
194 }
195 
196 #define	HVAL(p, n, s)	jenkins_hash32((const uint32_t *)(p), (n), (s))
197 #define	HOST_HVAL(c, a)	HVAL((a),\
198     sizeof(struct in6_addr) / sizeof(uint32_t), (c)->hash_seed)
199 #define	HOSTS(c, v)	((c)->hosts_hash[(v) & ((c)->hosts_hashsize - 1)])
200 
201 #define	ALIASLINK_HVAL(c, f)	HVAL(&(f)->dst_ip6,\
202     sizeof(struct in6_addr) * 2 / sizeof(uint32_t), (c)->hash_seed)
203 #define	ALIAS_BYHASH(c, v)	\
204     ((c)->aliases[(v) & ((1 << (32 - (c)->plen4)) - 1)])
205 static struct nat64lsn_aliaslink*
206 nat64lsn_get_aliaslink(struct nat64lsn_cfg *cfg __unused,
207     struct nat64lsn_host *host, const struct ipfw_flow_id *f_id __unused)
208 {
209 
210 	/*
211 	 * We can implement some different algorithms how
212 	 * select an alias address.
213 	 * XXX: for now we use first available.
214 	 */
215 	return (CK_SLIST_FIRST(&host->aliases));
216 }
217 
218 #define	STATE_HVAL(c, d)	HVAL((d), 2, (c)->hash_seed)
219 #define	STATE_HASH(h, v)	\
220     ((h)->states_hash[(v) & ((h)->states_hashsize - 1)])
221 #define	STATES_CHUNK(p, v)	\
222     ((p)->chunks_count == 1 ? (p)->states : \
223 	((p)->states_chunk[CHUNK_BY_FADDR(p, v)]))
224 
225 #ifdef __LP64__
226 #define	FREEMASK_FFSLL(pg, faddr)		\
227     ffsll(*FREEMASK_CHUNK((pg), (faddr)))
228 #define	FREEMASK_BTR(pg, faddr, bit)	\
229     ck_pr_btr_64(FREEMASK_CHUNK((pg), (faddr)), (bit))
230 #define	FREEMASK_BTS(pg, faddr, bit)	\
231     ck_pr_bts_64(FREEMASK_CHUNK((pg), (faddr)), (bit))
232 #define	FREEMASK_ISSET(pg, faddr, bit)	\
233     ISSET64(*FREEMASK_CHUNK((pg), (faddr)), (bit))
234 #define	FREEMASK_COPY(pg, n, out)	\
235     (out) = ck_pr_load_64(FREEMASK_CHUNK((pg), (n)))
236 #else
237 static inline int
238 freemask_ffsll(uint32_t *freemask)
239 {
240 	int i;
241 
242 	if ((i = ffsl(freemask[0])) != 0)
243 		return (i);
244 	if ((i = ffsl(freemask[1])) != 0)
245 		return (i + 32);
246 	return (0);
247 }
248 #define	FREEMASK_FFSLL(pg, faddr)		\
249     freemask_ffsll(FREEMASK_CHUNK((pg), (faddr)))
250 #define	FREEMASK_BTR(pg, faddr, bit)	\
251     ck_pr_btr_32(FREEMASK_CHUNK((pg), (faddr)) + (bit) / 32, (bit) % 32)
252 #define	FREEMASK_BTS(pg, faddr, bit)	\
253     ck_pr_bts_32(FREEMASK_CHUNK((pg), (faddr)) + (bit) / 32, (bit) % 32)
254 #define	FREEMASK_ISSET(pg, faddr, bit)	\
255     ISSET32(*(FREEMASK_CHUNK((pg), (faddr)) + (bit) / 32), (bit) % 32)
256 #define	FREEMASK_COPY(pg, n, out)	\
257     (out) = ck_pr_load_32(FREEMASK_CHUNK((pg), (n))) | \
258 	((uint64_t)ck_pr_load_32(FREEMASK_CHUNK((pg), (n)) + 1) << 32)
259 #endif /* !__LP64__ */
260 
261 
262 #define	NAT64LSN_TRY_PGCNT	32
263 static struct nat64lsn_pg*
264 nat64lsn_get_pg(uint32_t *chunkmask, uint32_t *pgmask,
265     struct nat64lsn_pgchunk **chunks, struct nat64lsn_pg **pgptr,
266     uint32_t *pgidx, in_addr_t faddr)
267 {
268 	struct nat64lsn_pg *pg, *oldpg;
269 	uint32_t idx, oldidx;
270 	int cnt;
271 
272 	cnt = 0;
273 	/* First try last used PG */
274 	oldpg = pg = ck_pr_load_ptr(pgptr);
275 	idx = oldidx = ck_pr_load_32(pgidx);
276 	/* If pgidx is out of range, reset it to the first pgchunk */
277 	if (!ISSET32(*chunkmask, idx / 32))
278 		idx = 0;
279 	do {
280 		ck_pr_fence_load();
281 		if (pg != NULL && FREEMASK_BITCOUNT(pg, faddr) > 0) {
282 			/*
283 			 * If last used PG has not free states,
284 			 * try to update pointer.
285 			 * NOTE: it can be already updated by jobs handler,
286 			 *	 thus we use CAS operation.
287 			 */
288 			if (cnt > 0)
289 				ck_pr_cas_ptr(pgptr, oldpg, pg);
290 			return (pg);
291 		}
292 		/* Stop if idx is out of range */
293 		if (!ISSET32(*chunkmask, idx / 32))
294 			break;
295 
296 		if (ISSET32(pgmask[idx / 32], idx % 32))
297 			pg = ck_pr_load_ptr(
298 			    &chunks[idx / 32]->pgptr[idx % 32]);
299 		else
300 			pg = NULL;
301 
302 		idx++;
303 	} while (++cnt < NAT64LSN_TRY_PGCNT);
304 
305 	/* If pgidx is out of range, reset it to the first pgchunk */
306 	if (!ISSET32(*chunkmask, idx / 32))
307 		idx = 0;
308 	ck_pr_cas_32(pgidx, oldidx, idx);
309 	return (NULL);
310 }
311 
312 static struct nat64lsn_state*
313 nat64lsn_get_state6to4(struct nat64lsn_cfg *cfg, struct nat64lsn_host *host,
314     const struct ipfw_flow_id *f_id, uint32_t hval, in_addr_t faddr,
315     uint16_t port, uint8_t proto)
316 {
317 	struct nat64lsn_aliaslink *link;
318 	struct nat64lsn_state *state;
319 	struct nat64lsn_pg *pg;
320 	int i, offset;
321 
322 	NAT64LSN_EPOCH_ASSERT();
323 
324 	/* Check that we already have state for given arguments */
325 	CK_SLIST_FOREACH(state, &STATE_HASH(host, hval), entries) {
326 		if (state->proto == proto && state->ip_dst == faddr &&
327 		    state->sport == port && state->dport == f_id->dst_port)
328 			return (state);
329 	}
330 
331 	link = nat64lsn_get_aliaslink(cfg, host, f_id);
332 	if (link == NULL)
333 		return (NULL);
334 
335 	switch (proto) {
336 	case IPPROTO_TCP:
337 		pg = nat64lsn_get_pg(
338 		    &link->alias->tcp_chunkmask, link->alias->tcp_pgmask,
339 		    link->alias->tcp, &link->alias->tcp_pg,
340 		    &link->alias->tcp_pgidx, faddr);
341 		break;
342 	case IPPROTO_UDP:
343 		pg = nat64lsn_get_pg(
344 		    &link->alias->udp_chunkmask, link->alias->udp_pgmask,
345 		    link->alias->udp, &link->alias->udp_pg,
346 		    &link->alias->udp_pgidx, faddr);
347 		break;
348 	case IPPROTO_ICMP:
349 		pg = nat64lsn_get_pg(
350 		    &link->alias->icmp_chunkmask, link->alias->icmp_pgmask,
351 		    link->alias->icmp, &link->alias->icmp_pg,
352 		    &link->alias->icmp_pgidx, faddr);
353 		break;
354 	default:
355 		panic("%s: wrong proto %d", __func__, proto);
356 	}
357 	if (pg == NULL)
358 		return (NULL);
359 
360 	/* Check that PG has some free states */
361 	state = NULL;
362 	i = FREEMASK_BITCOUNT(pg, faddr);
363 	while (i-- > 0) {
364 		offset = FREEMASK_FFSLL(pg, faddr);
365 		if (offset == 0) {
366 			/*
367 			 * We lost the race.
368 			 * No more free states in this PG.
369 			 */
370 			break;
371 		}
372 
373 		/* Lets try to atomically grab the state */
374 		if (FREEMASK_BTR(pg, faddr, offset - 1)) {
375 			state = &STATES_CHUNK(pg, faddr)->state[offset - 1];
376 			/* Initialize */
377 			state->flags = proto != IPPROTO_TCP ? 0 :
378 			    convert_tcp_flags(f_id->_flags);
379 			state->proto = proto;
380 			state->aport = pg->base_port + offset - 1;
381 			state->dport = f_id->dst_port;
382 			state->sport = port;
383 			state->ip6_dst = f_id->dst_ip6;
384 			state->ip_dst = faddr;
385 			state->ip_src = link->alias->addr;
386 			state->hval = hval;
387 			state->host = host;
388 			SET_AGE(state->timestamp);
389 
390 			/* Insert new state into host's hash table */
391 			HOST_LOCK(host);
392 			CK_SLIST_INSERT_HEAD(&STATE_HASH(host, hval),
393 			    state, entries);
394 			host->states_count++;
395 			/*
396 			 * XXX: In case if host is going to be expired,
397 			 * reset NAT64LSN_DEADHOST flag.
398 			 */
399 			host->flags &= ~NAT64LSN_DEADHOST;
400 			HOST_UNLOCK(host);
401 			NAT64STAT_INC(&cfg->base.stats, screated);
402 			/* Mark the state as ready for translate4 */
403 			ck_pr_fence_store();
404 			ck_pr_bts_32(&state->flags, NAT64_BIT_READY_IPV4);
405 			break;
406 		}
407 	}
408 	return (state);
409 }
410 
411 /*
412  * Inspects icmp packets to see if the message contains different
413  * packet header so we need to alter @addr and @port.
414  */
415 static int
416 inspect_icmp_mbuf(struct mbuf **mp, uint8_t *proto, uint32_t *addr,
417     uint16_t *port)
418 {
419 	struct icmp *icmp;
420 	struct ip *ip;
421 	int off;
422 	uint8_t inner_proto;
423 
424 	ip = mtod(*mp, struct ip *); /* Outer IP header */
425 	off = (ip->ip_hl << 2) + ICMP_MINLEN;
426 	if ((*mp)->m_len < off)
427 		*mp = m_pullup(*mp, off);
428 	if (*mp == NULL)
429 		return (ENOMEM);
430 
431 	ip = mtod(*mp, struct ip *); /* Outer IP header */
432 	icmp = L3HDR(ip, struct icmp *);
433 	switch (icmp->icmp_type) {
434 	case ICMP_ECHO:
435 	case ICMP_ECHOREPLY:
436 		/* Use icmp ID as distinguisher */
437 		*port = ntohs(icmp->icmp_id);
438 		return (0);
439 	case ICMP_UNREACH:
440 	case ICMP_TIMXCEED:
441 		break;
442 	default:
443 		return (EOPNOTSUPP);
444 	}
445 	/*
446 	 * ICMP_UNREACH and ICMP_TIMXCEED contains IP header + 64 bits
447 	 * of ULP header.
448 	 */
449 	if ((*mp)->m_pkthdr.len < off + sizeof(struct ip) + ICMP_MINLEN)
450 		return (EINVAL);
451 	if ((*mp)->m_len < off + sizeof(struct ip) + ICMP_MINLEN)
452 		*mp = m_pullup(*mp, off + sizeof(struct ip) + ICMP_MINLEN);
453 	if (*mp == NULL)
454 		return (ENOMEM);
455 	ip = mtodo(*mp, off); /* Inner IP header */
456 	inner_proto = ip->ip_p;
457 	off += ip->ip_hl << 2; /* Skip inner IP header */
458 	*addr = ntohl(ip->ip_src.s_addr);
459 	if ((*mp)->m_len < off + ICMP_MINLEN)
460 		*mp = m_pullup(*mp, off + ICMP_MINLEN);
461 	if (*mp == NULL)
462 		return (ENOMEM);
463 	switch (inner_proto) {
464 	case IPPROTO_TCP:
465 	case IPPROTO_UDP:
466 		/* Copy source port from the header */
467 		*port = ntohs(*((uint16_t *)mtodo(*mp, off)));
468 		*proto = inner_proto;
469 		return (0);
470 	case IPPROTO_ICMP:
471 		/*
472 		 * We will translate only ICMP errors for our ICMP
473 		 * echo requests.
474 		 */
475 		icmp = mtodo(*mp, off);
476 		if (icmp->icmp_type != ICMP_ECHO)
477 			return (EOPNOTSUPP);
478 		*port = ntohs(icmp->icmp_id);
479 		return (0);
480 	};
481 	return (EOPNOTSUPP);
482 }
483 
484 static struct nat64lsn_state*
485 nat64lsn_get_state4to6(struct nat64lsn_cfg *cfg, struct nat64lsn_alias *alias,
486     in_addr_t faddr, uint16_t port, uint8_t proto)
487 {
488 	struct nat64lsn_state *state;
489 	struct nat64lsn_pg *pg;
490 	int chunk_idx, pg_idx, state_idx;
491 
492 	NAT64LSN_EPOCH_ASSERT();
493 
494 	if (port < NAT64_MIN_PORT)
495 		return (NULL);
496 	/*
497 	 * Alias keeps 32 pgchunks for each protocol.
498 	 * Each pgchunk has 32 pointers to portgroup.
499 	 * Each portgroup has 64 states for ports.
500 	 */
501 	port -= NAT64_MIN_PORT;
502 	chunk_idx = port / 2048;
503 
504 	port -= chunk_idx * 2048;
505 	pg_idx = port / 64;
506 	state_idx = port % 64;
507 
508 	/*
509 	 * First check in proto_chunkmask that we have allocated PG chunk.
510 	 * Then check in proto_pgmask that we have valid PG pointer.
511 	 */
512 	pg = NULL;
513 	switch (proto) {
514 	case IPPROTO_TCP:
515 		if (ISSET32(alias->tcp_chunkmask, chunk_idx) &&
516 		    ISSET32(alias->tcp_pgmask[chunk_idx], pg_idx)) {
517 			pg = alias->tcp[chunk_idx]->pgptr[pg_idx];
518 			break;
519 		}
520 		return (NULL);
521 	case IPPROTO_UDP:
522 		if (ISSET32(alias->udp_chunkmask, chunk_idx) &&
523 		    ISSET32(alias->udp_pgmask[chunk_idx], pg_idx)) {
524 			pg = alias->udp[chunk_idx]->pgptr[pg_idx];
525 			break;
526 		}
527 		return (NULL);
528 	case IPPROTO_ICMP:
529 		if (ISSET32(alias->icmp_chunkmask, chunk_idx) &&
530 		    ISSET32(alias->icmp_pgmask[chunk_idx], pg_idx)) {
531 			pg = alias->icmp[chunk_idx]->pgptr[pg_idx];
532 			break;
533 		}
534 		return (NULL);
535 	default:
536 		panic("%s: wrong proto %d", __func__, proto);
537 	}
538 	if (pg == NULL)
539 		return (NULL);
540 
541 	if (FREEMASK_ISSET(pg, faddr, state_idx))
542 		return (NULL);
543 
544 	state = &STATES_CHUNK(pg, faddr)->state[state_idx];
545 	ck_pr_fence_load();
546 	if (ck_pr_load_32(&state->flags) & NAT64_FLAG_READY)
547 		return (state);
548 	return (NULL);
549 }
550 
551 static int
552 nat64lsn_translate4(struct nat64lsn_cfg *cfg,
553     const struct ipfw_flow_id *f_id, struct mbuf **mp)
554 {
555 	struct pfloghdr loghdr, *logdata;
556 	struct in6_addr src6;
557 	struct nat64lsn_state *state;
558 	struct nat64lsn_alias *alias;
559 	uint32_t addr, flags;
560 	uint16_t port, ts;
561 	int ret;
562 	uint8_t proto;
563 
564 	addr = f_id->dst_ip;
565 	port = f_id->dst_port;
566 	proto = f_id->proto;
567 	if (addr < cfg->prefix4 || addr > cfg->pmask4) {
568 		NAT64STAT_INC(&cfg->base.stats, nomatch4);
569 		return (cfg->nomatch_verdict);
570 	}
571 
572 	/* Check if protocol is supported */
573 	switch (proto) {
574 	case IPPROTO_ICMP:
575 		ret = inspect_icmp_mbuf(mp, &proto, &addr, &port);
576 		if (ret != 0) {
577 			if (ret == ENOMEM) {
578 				NAT64STAT_INC(&cfg->base.stats, nomem);
579 				return (IP_FW_DENY);
580 			}
581 			NAT64STAT_INC(&cfg->base.stats, noproto);
582 			return (cfg->nomatch_verdict);
583 		}
584 		if (addr < cfg->prefix4 || addr > cfg->pmask4) {
585 			NAT64STAT_INC(&cfg->base.stats, nomatch4);
586 			return (cfg->nomatch_verdict);
587 		}
588 		/* FALLTHROUGH */
589 	case IPPROTO_TCP:
590 	case IPPROTO_UDP:
591 		break;
592 	default:
593 		NAT64STAT_INC(&cfg->base.stats, noproto);
594 		return (cfg->nomatch_verdict);
595 	}
596 
597 	alias = &ALIAS_BYHASH(cfg, addr);
598 	MPASS(addr == alias->addr);
599 
600 	/* Check that we have state for this port */
601 	state = nat64lsn_get_state4to6(cfg, alias, f_id->src_ip,
602 	    port, proto);
603 	if (state == NULL) {
604 		NAT64STAT_INC(&cfg->base.stats, nomatch4);
605 		return (cfg->nomatch_verdict);
606 	}
607 
608 	/* TODO: Check flags to see if we need to do some static mapping */
609 
610 	/* Update some state fields if need */
611 	SET_AGE(ts);
612 	if (f_id->proto == IPPROTO_TCP)
613 		flags = convert_tcp_flags(f_id->_flags);
614 	else
615 		flags = 0;
616 	if (state->timestamp != ts)
617 		state->timestamp = ts;
618 	if ((state->flags & flags) != flags)
619 		state->flags |= flags;
620 
621 	port = htons(state->sport);
622 	src6 = state->ip6_dst;
623 
624 	if (cfg->base.flags & NAT64_LOG) {
625 		logdata = &loghdr;
626 		nat64lsn_log(logdata, *mp, AF_INET, state);
627 	} else
628 		logdata = NULL;
629 
630 	/*
631 	 * We already have src6 with embedded address, but it is possible,
632 	 * that src_ip is different than state->ip_dst, this is why we
633 	 * do embedding again.
634 	 */
635 	nat64_embed_ip4(&src6, cfg->base.plat_plen, htonl(f_id->src_ip));
636 	ret = nat64_do_handle_ip4(*mp, &src6, &state->host->addr, port,
637 	    &cfg->base, logdata);
638 	if (ret == NAT64SKIP)
639 		return (cfg->nomatch_verdict);
640 	if (ret == NAT64RETURN)
641 		*mp = NULL;
642 	return (IP_FW_DENY);
643 }
644 
645 /*
646  * Check if particular state is stale and should be deleted.
647  * Return 1 if true, 0 otherwise.
648  */
649 static int
650 nat64lsn_check_state(struct nat64lsn_cfg *cfg, struct nat64lsn_state *state)
651 {
652 	int age, ttl;
653 
654 	/* State was marked as stale in previous pass. */
655 	if (ISSET32(state->flags, NAT64_BIT_STALE))
656 		return (1);
657 
658 	/* State is not yet initialized, it is going to be READY */
659 	if (!ISSET32(state->flags, NAT64_BIT_READY_IPV4))
660 		return (0);
661 
662 	age = GET_AGE(state->timestamp);
663 	switch (state->proto) {
664 	case IPPROTO_TCP:
665 		if (ISSET32(state->flags, NAT64_BIT_TCP_FIN))
666 			ttl = cfg->st_close_ttl;
667 		else if (ISSET32(state->flags, NAT64_BIT_TCP_ESTAB))
668 			ttl = cfg->st_estab_ttl;
669 		else if (ISSET32(state->flags, NAT64_BIT_TCP_SYN))
670 			ttl = cfg->st_syn_ttl;
671 		else
672 			ttl = cfg->st_syn_ttl;
673 		if (age > ttl)
674 			return (1);
675 		break;
676 	case IPPROTO_UDP:
677 		if (age > cfg->st_udp_ttl)
678 			return (1);
679 		break;
680 	case IPPROTO_ICMP:
681 		if (age > cfg->st_icmp_ttl)
682 			return (1);
683 		break;
684 	}
685 	return (0);
686 }
687 
688 static int
689 nat64lsn_maintain_pg(struct nat64lsn_cfg *cfg, struct nat64lsn_pg *pg)
690 {
691 	struct nat64lsn_state *state;
692 	struct nat64lsn_host *host;
693 	uint64_t freemask;
694 	int c, i, update_age;
695 
696 	update_age = 0;
697 	for (c = 0; c < pg->chunks_count; c++) {
698 		FREEMASK_COPY(pg, c, freemask);
699 		for (i = 0; i < 64; i++) {
700 			if (ISSET64(freemask, i))
701 				continue;
702 			state = &STATES_CHUNK(pg, c)->state[i];
703 			if (nat64lsn_check_state(cfg, state) == 0) {
704 				update_age = 1;
705 				continue;
706 			}
707 			/*
708 			 * Expire state:
709 			 * 1. Mark as STALE and unlink from host's hash.
710 			 * 2. Set bit in freemask.
711 			 */
712 			if (ISSET32(state->flags, NAT64_BIT_STALE)) {
713 				/*
714 				 * State was marked as STALE in previous
715 				 * pass. Now it is safe to release it.
716 				 */
717 				state->flags = 0;
718 				ck_pr_fence_store();
719 				FREEMASK_BTS(pg, c, i);
720 				NAT64STAT_INC(&cfg->base.stats, sdeleted);
721 				continue;
722 			}
723 			MPASS(state->flags & NAT64_FLAG_READY);
724 
725 			host = state->host;
726 			HOST_LOCK(host);
727 			CK_SLIST_REMOVE(&STATE_HASH(host, state->hval),
728 			    state, nat64lsn_state, entries);
729 			host->states_count--;
730 			HOST_UNLOCK(host);
731 
732 			/* Reset READY flag */
733 			ck_pr_btr_32(&state->flags, NAT64_BIT_READY_IPV4);
734 			/* And set STALE flag */
735 			ck_pr_bts_32(&state->flags, NAT64_BIT_STALE);
736 			ck_pr_fence_store();
737 			/*
738 			 * Now translate6 will not use this state, wait
739 			 * until it become safe for translate4, then mark
740 			 * state as free.
741 			 */
742 		}
743 	}
744 
745 	/*
746 	 * We have some alive states, update timestamp.
747 	 */
748 	if (update_age)
749 		SET_AGE(pg->timestamp);
750 
751 	if (GET_AGE(pg->timestamp) < cfg->pg_delete_delay)
752 		return (0);
753 
754 	return (1);
755 }
756 
757 static void
758 nat64lsn_expire_portgroups(struct nat64lsn_cfg *cfg,
759     struct nat64lsn_pg_slist *portgroups)
760 {
761 	struct nat64lsn_alias *alias;
762 	struct nat64lsn_pg *pg, *tpg, *firstpg, **pgptr;
763 	uint32_t *pgmask, *pgidx;
764 	int i, idx;
765 
766 	for (i = 0; i < 1 << (32 - cfg->plen4); i++) {
767 		alias = &cfg->aliases[i];
768 		CK_SLIST_FOREACH_SAFE(pg, &alias->portgroups, entries, tpg) {
769 			if (nat64lsn_maintain_pg(cfg, pg) == 0)
770 				continue;
771 			/* Always keep first PG */
772 			if (pg->base_port == NAT64_MIN_PORT)
773 				continue;
774 			/*
775 			 * PG is expired, unlink it and schedule for
776 			 * deferred destroying.
777 			 */
778 			idx = (pg->base_port - NAT64_MIN_PORT) / 64;
779 			switch (pg->proto) {
780 			case IPPROTO_TCP:
781 				pgmask = alias->tcp_pgmask;
782 				pgptr = &alias->tcp_pg;
783 				pgidx = &alias->tcp_pgidx;
784 				firstpg = alias->tcp[0]->pgptr[0];
785 				break;
786 			case IPPROTO_UDP:
787 				pgmask = alias->udp_pgmask;
788 				pgptr = &alias->udp_pg;
789 				pgidx = &alias->udp_pgidx;
790 				firstpg = alias->udp[0]->pgptr[0];
791 				break;
792 			case IPPROTO_ICMP:
793 				pgmask = alias->icmp_pgmask;
794 				pgptr = &alias->icmp_pg;
795 				pgidx = &alias->icmp_pgidx;
796 				firstpg = alias->icmp[0]->pgptr[0];
797 				break;
798 			}
799 			/* Reset the corresponding bit in pgmask array. */
800 			ck_pr_btr_32(&pgmask[idx / 32], idx % 32);
801 			ck_pr_fence_store();
802 			/* If last used PG points to this PG, reset it. */
803 			ck_pr_cas_ptr(pgptr, pg, firstpg);
804 			ck_pr_cas_32(pgidx, idx, 0);
805 			/* Unlink PG from alias's chain */
806 			ALIAS_LOCK(alias);
807 			CK_SLIST_REMOVE(&alias->portgroups, pg,
808 			    nat64lsn_pg, entries);
809 			alias->portgroups_count--;
810 			ALIAS_UNLOCK(alias);
811 			/* And link to job's chain for deferred destroying */
812 			NAT64STAT_INC(&cfg->base.stats, spgdeleted);
813 			CK_SLIST_INSERT_HEAD(portgroups, pg, entries);
814 		}
815 	}
816 }
817 
818 static void
819 nat64lsn_expire_hosts(struct nat64lsn_cfg *cfg,
820     struct nat64lsn_hosts_slist *hosts)
821 {
822 	struct nat64lsn_host *host, *tmp;
823 	int i;
824 
825 	for (i = 0; i < cfg->hosts_hashsize; i++) {
826 		CK_SLIST_FOREACH_SAFE(host, &cfg->hosts_hash[i],
827 		    entries, tmp) {
828 			/* Is host was marked in previous call? */
829 			if (host->flags & NAT64LSN_DEADHOST) {
830 				if (host->states_count > 0) {
831 					host->flags &= ~NAT64LSN_DEADHOST;
832 					continue;
833 				}
834 				/*
835 				 * Unlink host from hash table and schedule
836 				 * it for deferred destroying.
837 				 */
838 				CFG_LOCK(cfg);
839 				CK_SLIST_REMOVE(&cfg->hosts_hash[i], host,
840 				    nat64lsn_host, entries);
841 				cfg->hosts_count--;
842 				CFG_UNLOCK(cfg);
843 				CK_SLIST_INSERT_HEAD(hosts, host, entries);
844 				continue;
845 			}
846 			if (GET_AGE(host->timestamp) < cfg->host_delete_delay)
847 				continue;
848 			if (host->states_count > 0)
849 				continue;
850 			/* Mark host as going to be expired in next pass */
851 			host->flags |= NAT64LSN_DEADHOST;
852 			ck_pr_fence_store();
853 		}
854 	}
855 }
856 
857 static struct nat64lsn_pgchunk*
858 nat64lsn_expire_pgchunk(struct nat64lsn_cfg *cfg)
859 {
860 #if 0
861 	struct nat64lsn_alias *alias;
862 	struct nat64lsn_pgchunk *chunk;
863 	uint32_t pgmask;
864 	int i, c;
865 
866 	for (i = 0; i < 1 << (32 - cfg->plen4); i++) {
867 		alias = &cfg->aliases[i];
868 		if (GET_AGE(alias->timestamp) < cfg->pgchunk_delete_delay)
869 			continue;
870 		/* Always keep single chunk allocated */
871 		for (c = 1; c < 32; c++) {
872 			if ((alias->tcp_chunkmask & (1 << c)) == 0)
873 				break;
874 			chunk = ck_pr_load_ptr(&alias->tcp[c]);
875 			if (ck_pr_load_32(&alias->tcp_pgmask[c]) != 0)
876 				continue;
877 			ck_pr_btr_32(&alias->tcp_chunkmask, c);
878 			ck_pr_fence_load();
879 			if (ck_pr_load_32(&alias->tcp_pgmask[c]) != 0)
880 				continue;
881 		}
882 	}
883 #endif
884 	return (NULL);
885 }
886 
887 #if 0
888 static void
889 nat64lsn_maintain_hosts(struct nat64lsn_cfg *cfg)
890 {
891 	struct nat64lsn_host *h;
892 	struct nat64lsn_states_slist *hash;
893 	int i, j, hsize;
894 
895 	for (i = 0; i < cfg->hosts_hashsize; i++) {
896 		CK_SLIST_FOREACH(h, &cfg->hosts_hash[i], entries) {
897 			 if (h->states_count / 2 < h->states_hashsize ||
898 			     h->states_hashsize >= NAT64LSN_MAX_HSIZE)
899 				 continue;
900 			 hsize = h->states_hashsize * 2;
901 			 hash = malloc(sizeof(*hash)* hsize, M_NOWAIT);
902 			 if (hash == NULL)
903 				 continue;
904 			 for (j = 0; j < hsize; j++)
905 				CK_SLIST_INIT(&hash[i]);
906 
907 			 ck_pr_bts_32(&h->flags, NAT64LSN_GROWHASH);
908 		}
909 	}
910 }
911 #endif
912 
913 /*
914  * This procedure is used to perform various maintance
915  * on dynamic hash list. Currently it is called every 4 seconds.
916  */
917 static void
918 nat64lsn_periodic(void *data)
919 {
920 	struct nat64lsn_job_item *ji;
921 	struct nat64lsn_cfg *cfg;
922 
923 	cfg = (struct nat64lsn_cfg *) data;
924 	CURVNET_SET(cfg->vp);
925 	if (cfg->hosts_count > 0) {
926 		ji = uma_zalloc(nat64lsn_job_zone, M_NOWAIT);
927 		if (ji != NULL) {
928 			ji->jtype = JTYPE_DESTROY;
929 			CK_SLIST_INIT(&ji->hosts);
930 			CK_SLIST_INIT(&ji->portgroups);
931 			nat64lsn_expire_hosts(cfg, &ji->hosts);
932 			nat64lsn_expire_portgroups(cfg, &ji->portgroups);
933 			ji->pgchunk = nat64lsn_expire_pgchunk(cfg);
934 			NAT64LSN_EPOCH_CALL(&ji->epoch_ctx,
935 			    nat64lsn_job_destroy);
936 		} else
937 			NAT64STAT_INC(&cfg->base.stats, jnomem);
938 	}
939 	callout_schedule(&cfg->periodic, hz * PERIODIC_DELAY);
940 	CURVNET_RESTORE();
941 }
942 
943 #define	ALLOC_ERROR(stage, type)	((stage) ? 10 * (type) + (stage): 0)
944 #define	HOST_ERROR(stage)		ALLOC_ERROR(stage, 1)
945 #define	PG_ERROR(stage)			ALLOC_ERROR(stage, 2)
946 static int
947 nat64lsn_alloc_host(struct nat64lsn_cfg *cfg, struct nat64lsn_job_item *ji)
948 {
949 	char a[INET6_ADDRSTRLEN];
950 	struct nat64lsn_aliaslink *link;
951 	struct nat64lsn_host *host;
952 	struct nat64lsn_state *state;
953 	uint32_t hval, data[2];
954 	int i;
955 
956 	/* Check that host was not yet added. */
957 	NAT64LSN_EPOCH_ASSERT();
958 	CK_SLIST_FOREACH(host, &HOSTS(cfg, ji->src6_hval), entries) {
959 		if (IN6_ARE_ADDR_EQUAL(&ji->f_id.src_ip6, &host->addr)) {
960 			/* The host was allocated in previous call. */
961 			ji->host = host;
962 			goto get_state;
963 		}
964 	}
965 
966 	host = ji->host = uma_zalloc(nat64lsn_host_zone, M_NOWAIT);
967 	if (ji->host == NULL)
968 		return (HOST_ERROR(1));
969 
970 	host->states_hashsize = NAT64LSN_HSIZE;
971 	host->states_hash = malloc(sizeof(struct nat64lsn_states_slist) *
972 	    host->states_hashsize, M_NAT64LSN, M_NOWAIT);
973 	if (host->states_hash == NULL) {
974 		uma_zfree(nat64lsn_host_zone, host);
975 		return (HOST_ERROR(2));
976 	}
977 
978 	link = uma_zalloc(nat64lsn_aliaslink_zone, M_NOWAIT);
979 	if (link == NULL) {
980 		free(host->states_hash, M_NAT64LSN);
981 		uma_zfree(nat64lsn_host_zone, host);
982 		return (HOST_ERROR(3));
983 	}
984 
985 	/* Initialize */
986 	HOST_LOCK_INIT(host);
987 	SET_AGE(host->timestamp);
988 	host->addr = ji->f_id.src_ip6;
989 	host->hval = ji->src6_hval;
990 	host->flags = 0;
991 	host->states_count = 0;
992 	host->states_hashsize = NAT64LSN_HSIZE;
993 	CK_SLIST_INIT(&host->aliases);
994 	for (i = 0; i < host->states_hashsize; i++)
995 		CK_SLIST_INIT(&host->states_hash[i]);
996 
997 	/* Determine alias from flow hash. */
998 	hval = ALIASLINK_HVAL(cfg, &ji->f_id);
999 	link->alias = &ALIAS_BYHASH(cfg, hval);
1000 	CK_SLIST_INSERT_HEAD(&host->aliases, link, host_entries);
1001 
1002 	ALIAS_LOCK(link->alias);
1003 	CK_SLIST_INSERT_HEAD(&link->alias->hosts, link, alias_entries);
1004 	link->alias->hosts_count++;
1005 	ALIAS_UNLOCK(link->alias);
1006 
1007 	CFG_LOCK(cfg);
1008 	CK_SLIST_INSERT_HEAD(&HOSTS(cfg, ji->src6_hval), host, entries);
1009 	cfg->hosts_count++;
1010 	CFG_UNLOCK(cfg);
1011 
1012 get_state:
1013 	data[0] = ji->faddr;
1014 	data[1] = (ji->f_id.dst_port << 16) | ji->port;
1015 	ji->state_hval = hval = STATE_HVAL(cfg, data);
1016 	state = nat64lsn_get_state6to4(cfg, host, &ji->f_id, hval,
1017 	    ji->faddr, ji->port, ji->proto);
1018 	/*
1019 	 * We failed to obtain new state, used alias needs new PG.
1020 	 * XXX: or another alias should be used.
1021 	 */
1022 	if (state == NULL) {
1023 		/* Try to allocate new PG */
1024 		if (nat64lsn_alloc_pg(cfg, ji) != PG_ERROR(0))
1025 			return (HOST_ERROR(4));
1026 		/* We assume that nat64lsn_alloc_pg() got state */
1027 	} else
1028 		ji->state = state;
1029 
1030 	ji->done = 1;
1031 	DPRINTF(DP_OBJ, "ALLOC HOST %s %p",
1032 	    inet_ntop(AF_INET6, &host->addr, a, sizeof(a)), host);
1033 	return (HOST_ERROR(0));
1034 }
1035 
1036 static int
1037 nat64lsn_find_pg_place(uint32_t *data)
1038 {
1039 	int i;
1040 
1041 	for (i = 0; i < 32; i++) {
1042 		if (~data[i] == 0)
1043 			continue;
1044 		return (i * 32 + ffs(~data[i]) - 1);
1045 	}
1046 	return (-1);
1047 }
1048 
1049 static int
1050 nat64lsn_alloc_proto_pg(struct nat64lsn_cfg *cfg,
1051     struct nat64lsn_alias *alias, uint32_t *chunkmask,
1052     uint32_t *pgmask, struct nat64lsn_pgchunk **chunks,
1053     struct nat64lsn_pg **pgptr, uint8_t proto)
1054 {
1055 	struct nat64lsn_pg *pg;
1056 	int i, pg_idx, chunk_idx;
1057 
1058 	/* Find place in pgchunk where PG can be added */
1059 	pg_idx = nat64lsn_find_pg_place(pgmask);
1060 	if (pg_idx < 0)	/* no more PGs */
1061 		return (PG_ERROR(1));
1062 	/* Check that we have allocated pgchunk for given PG index */
1063 	chunk_idx = pg_idx / 32;
1064 	if (!ISSET32(*chunkmask, chunk_idx)) {
1065 		chunks[chunk_idx] = uma_zalloc(nat64lsn_pgchunk_zone,
1066 		    M_NOWAIT);
1067 		if (chunks[chunk_idx] == NULL)
1068 			return (PG_ERROR(2));
1069 		ck_pr_bts_32(chunkmask, chunk_idx);
1070 		ck_pr_fence_store();
1071 	}
1072 	/* Allocate PG and states chunks */
1073 	pg = uma_zalloc(nat64lsn_pg_zone, M_NOWAIT);
1074 	if (pg == NULL)
1075 		return (PG_ERROR(3));
1076 	pg->chunks_count = cfg->states_chunks;
1077 	if (pg->chunks_count > 1) {
1078 		pg->freemask_chunk = malloc(pg->chunks_count *
1079 		    sizeof(uint64_t), M_NAT64LSN, M_NOWAIT);
1080 		if (pg->freemask_chunk == NULL) {
1081 			uma_zfree(nat64lsn_pg_zone, pg);
1082 			return (PG_ERROR(4));
1083 		}
1084 		pg->states_chunk = malloc(pg->chunks_count *
1085 		    sizeof(struct nat64lsn_states_chunk *), M_NAT64LSN,
1086 		    M_NOWAIT | M_ZERO);
1087 		if (pg->states_chunk == NULL) {
1088 			free(pg->freemask_chunk, M_NAT64LSN);
1089 			uma_zfree(nat64lsn_pg_zone, pg);
1090 			return (PG_ERROR(5));
1091 		}
1092 		for (i = 0; i < pg->chunks_count; i++) {
1093 			pg->states_chunk[i] = uma_zalloc(
1094 			    nat64lsn_state_zone, M_NOWAIT);
1095 			if (pg->states_chunk[i] == NULL)
1096 				goto states_failed;
1097 		}
1098 		memset(pg->freemask_chunk, 0xff,
1099 		    sizeof(uint64_t) * pg->chunks_count);
1100 	} else {
1101 		pg->states = uma_zalloc(nat64lsn_state_zone, M_NOWAIT);
1102 		if (pg->states == NULL) {
1103 			uma_zfree(nat64lsn_pg_zone, pg);
1104 			return (PG_ERROR(6));
1105 		}
1106 		memset(&pg->freemask64, 0xff, sizeof(uint64_t));
1107 	}
1108 
1109 	/* Initialize PG and hook it to pgchunk */
1110 	SET_AGE(pg->timestamp);
1111 	pg->proto = proto;
1112 	pg->base_port = NAT64_MIN_PORT + 64 * pg_idx;
1113 	ck_pr_store_ptr(&chunks[chunk_idx]->pgptr[pg_idx % 32], pg);
1114 	ck_pr_fence_store();
1115 	ck_pr_bts_32(&pgmask[pg_idx / 32], pg_idx % 32);
1116 	ck_pr_store_ptr(pgptr, pg);
1117 
1118 	ALIAS_LOCK(alias);
1119 	CK_SLIST_INSERT_HEAD(&alias->portgroups, pg, entries);
1120 	SET_AGE(alias->timestamp);
1121 	alias->portgroups_count++;
1122 	ALIAS_UNLOCK(alias);
1123 	NAT64STAT_INC(&cfg->base.stats, spgcreated);
1124 	return (PG_ERROR(0));
1125 
1126 states_failed:
1127 	for (i = 0; i < pg->chunks_count; i++)
1128 		uma_zfree(nat64lsn_state_zone, pg->states_chunk[i]);
1129 	free(pg->freemask_chunk, M_NAT64LSN);
1130 	free(pg->states_chunk, M_NAT64LSN);
1131 	uma_zfree(nat64lsn_pg_zone, pg);
1132 	return (PG_ERROR(7));
1133 }
1134 
1135 static int
1136 nat64lsn_alloc_pg(struct nat64lsn_cfg *cfg, struct nat64lsn_job_item *ji)
1137 {
1138 	struct nat64lsn_aliaslink *link;
1139 	struct nat64lsn_alias *alias;
1140 	int ret;
1141 
1142 	link = nat64lsn_get_aliaslink(cfg, ji->host, &ji->f_id);
1143 	if (link == NULL)
1144 		return (PG_ERROR(1));
1145 
1146 	/*
1147 	 * TODO: check that we did not already allocated PG in
1148 	 *	 previous call.
1149 	 */
1150 
1151 	ret = 0;
1152 	alias = link->alias;
1153 	/* Find place in pgchunk where PG can be added */
1154 	switch (ji->proto) {
1155 	case IPPROTO_TCP:
1156 		ret = nat64lsn_alloc_proto_pg(cfg, alias,
1157 		    &alias->tcp_chunkmask, alias->tcp_pgmask,
1158 		    alias->tcp, &alias->tcp_pg, ji->proto);
1159 		break;
1160 	case IPPROTO_UDP:
1161 		ret = nat64lsn_alloc_proto_pg(cfg, alias,
1162 		    &alias->udp_chunkmask, alias->udp_pgmask,
1163 		    alias->udp, &alias->udp_pg, ji->proto);
1164 		break;
1165 	case IPPROTO_ICMP:
1166 		ret = nat64lsn_alloc_proto_pg(cfg, alias,
1167 		    &alias->icmp_chunkmask, alias->icmp_pgmask,
1168 		    alias->icmp, &alias->icmp_pg, ji->proto);
1169 		break;
1170 	default:
1171 		panic("%s: wrong proto %d", __func__, ji->proto);
1172 	}
1173 	if (ret == PG_ERROR(1)) {
1174 		/*
1175 		 * PG_ERROR(1) means that alias lacks free PGs
1176 		 * XXX: try next alias.
1177 		 */
1178 		printf("NAT64LSN: %s: failed to obtain PG\n",
1179 		    __func__);
1180 		return (ret);
1181 	}
1182 	if (ret == PG_ERROR(0)) {
1183 		ji->state = nat64lsn_get_state6to4(cfg, ji->host, &ji->f_id,
1184 		    ji->state_hval, ji->faddr, ji->port, ji->proto);
1185 		if (ji->state == NULL)
1186 			ret = PG_ERROR(8);
1187 		else
1188 			ji->done = 1;
1189 	}
1190 	return (ret);
1191 }
1192 
1193 static void
1194 nat64lsn_do_request(void *data)
1195 {
1196 	struct epoch_tracker et;
1197 	struct nat64lsn_job_head jhead;
1198 	struct nat64lsn_job_item *ji, *ji2;
1199 	struct nat64lsn_cfg *cfg;
1200 	int jcount;
1201 	uint8_t flags;
1202 
1203 	cfg = (struct nat64lsn_cfg *)data;
1204 	if (cfg->jlen == 0)
1205 		return;
1206 
1207 	CURVNET_SET(cfg->vp);
1208 	STAILQ_INIT(&jhead);
1209 
1210 	/* Grab queue */
1211 	JQUEUE_LOCK();
1212 	STAILQ_SWAP(&jhead, &cfg->jhead, nat64lsn_job_item);
1213 	jcount = cfg->jlen;
1214 	cfg->jlen = 0;
1215 	JQUEUE_UNLOCK();
1216 
1217 	/* TODO: check if we need to resize hash */
1218 
1219 	NAT64STAT_INC(&cfg->base.stats, jcalls);
1220 	DPRINTF(DP_JQUEUE, "count=%d", jcount);
1221 
1222 	/*
1223 	 * TODO:
1224 	 * What we should do here is to build a hash
1225 	 * to ensure we don't have lots of duplicate requests.
1226 	 * Skip this for now.
1227 	 *
1228 	 * TODO: Limit per-call number of items
1229 	 */
1230 
1231 	NAT64LSN_EPOCH_ENTER(et);
1232 	STAILQ_FOREACH(ji, &jhead, entries) {
1233 		switch (ji->jtype) {
1234 		case JTYPE_NEWHOST:
1235 			if (nat64lsn_alloc_host(cfg, ji) != HOST_ERROR(0))
1236 				NAT64STAT_INC(&cfg->base.stats, jhostfails);
1237 			break;
1238 		case JTYPE_NEWPORTGROUP:
1239 			if (nat64lsn_alloc_pg(cfg, ji) != PG_ERROR(0))
1240 				NAT64STAT_INC(&cfg->base.stats, jportfails);
1241 			break;
1242 		default:
1243 			continue;
1244 		}
1245 		if (ji->done != 0) {
1246 			flags = ji->proto != IPPROTO_TCP ? 0 :
1247 			    convert_tcp_flags(ji->f_id._flags);
1248 			nat64lsn_translate6_internal(cfg, &ji->m,
1249 			    ji->state, flags);
1250 			NAT64STAT_INC(&cfg->base.stats, jreinjected);
1251 		}
1252 	}
1253 	NAT64LSN_EPOCH_EXIT(et);
1254 
1255 	ji = STAILQ_FIRST(&jhead);
1256 	while (ji != NULL) {
1257 		ji2 = STAILQ_NEXT(ji, entries);
1258 		/*
1259 		 * In any case we must free mbuf if
1260 		 * translator did not consumed it.
1261 		 */
1262 		m_freem(ji->m);
1263 		uma_zfree(nat64lsn_job_zone, ji);
1264 		ji = ji2;
1265 	}
1266 	CURVNET_RESTORE();
1267 }
1268 
1269 static struct nat64lsn_job_item *
1270 nat64lsn_create_job(struct nat64lsn_cfg *cfg, int jtype)
1271 {
1272 	struct nat64lsn_job_item *ji;
1273 
1274 	/*
1275 	 * Do not try to lock possibly contested mutex if we're near the
1276 	 * limit. Drop packet instead.
1277 	 */
1278 	ji = NULL;
1279 	if (cfg->jlen >= cfg->jmaxlen)
1280 		NAT64STAT_INC(&cfg->base.stats, jmaxlen);
1281 	else {
1282 		ji = uma_zalloc(nat64lsn_job_zone, M_NOWAIT);
1283 		if (ji == NULL)
1284 			NAT64STAT_INC(&cfg->base.stats, jnomem);
1285 	}
1286 	if (ji == NULL) {
1287 		NAT64STAT_INC(&cfg->base.stats, dropped);
1288 		DPRINTF(DP_DROPS, "failed to create job");
1289 	} else {
1290 		ji->jtype = jtype;
1291 		ji->done = 0;
1292 	}
1293 	return (ji);
1294 }
1295 
1296 static void
1297 nat64lsn_enqueue_job(struct nat64lsn_cfg *cfg, struct nat64lsn_job_item *ji)
1298 {
1299 
1300 	JQUEUE_LOCK();
1301 	STAILQ_INSERT_TAIL(&cfg->jhead, ji, entries);
1302 	NAT64STAT_INC(&cfg->base.stats, jrequests);
1303 	cfg->jlen++;
1304 
1305 	if (callout_pending(&cfg->jcallout) == 0)
1306 		callout_reset(&cfg->jcallout, 1, nat64lsn_do_request, cfg);
1307 	JQUEUE_UNLOCK();
1308 }
1309 
1310 static void
1311 nat64lsn_job_destroy(epoch_context_t ctx)
1312 {
1313 	struct nat64lsn_job_item *ji;
1314 	struct nat64lsn_host *host;
1315 	struct nat64lsn_pg *pg;
1316 	int i;
1317 
1318 	ji = __containerof(ctx, struct nat64lsn_job_item, epoch_ctx);
1319 	MPASS(ji->jtype == JTYPE_DESTROY);
1320 	while (!CK_SLIST_EMPTY(&ji->hosts)) {
1321 		host = CK_SLIST_FIRST(&ji->hosts);
1322 		CK_SLIST_REMOVE_HEAD(&ji->hosts, entries);
1323 		if (host->states_count > 0) {
1324 			/*
1325 			 * XXX: The state has been created
1326 			 * during host deletion.
1327 			 */
1328 			printf("NAT64LSN: %s: destroying host with %d "
1329 			    "states\n", __func__, host->states_count);
1330 		}
1331 		nat64lsn_destroy_host(host);
1332 	}
1333 	while (!CK_SLIST_EMPTY(&ji->portgroups)) {
1334 		pg = CK_SLIST_FIRST(&ji->portgroups);
1335 		CK_SLIST_REMOVE_HEAD(&ji->portgroups, entries);
1336 		for (i = 0; i < pg->chunks_count; i++) {
1337 			if (FREEMASK_BITCOUNT(pg, i) != 64) {
1338 				/*
1339 				 * XXX: The state has been created during
1340 				 * PG deletion.
1341 				 */
1342 				printf("NAT64LSN: %s: destroying PG %p "
1343 				    "with non-empty chunk %d\n", __func__,
1344 				    pg, i);
1345 			}
1346 		}
1347 		nat64lsn_destroy_pg(pg);
1348 	}
1349 	uma_zfree(nat64lsn_pgchunk_zone, ji->pgchunk);
1350 	uma_zfree(nat64lsn_job_zone, ji);
1351 }
1352 
1353 static int
1354 nat64lsn_request_host(struct nat64lsn_cfg *cfg,
1355     const struct ipfw_flow_id *f_id, struct mbuf **mp, uint32_t hval,
1356     in_addr_t faddr, uint16_t port, uint8_t proto)
1357 {
1358 	struct nat64lsn_job_item *ji;
1359 
1360 	ji = nat64lsn_create_job(cfg, JTYPE_NEWHOST);
1361 	if (ji != NULL) {
1362 		ji->m = *mp;
1363 		ji->f_id = *f_id;
1364 		ji->faddr = faddr;
1365 		ji->port = port;
1366 		ji->proto = proto;
1367 		ji->src6_hval = hval;
1368 
1369 		nat64lsn_enqueue_job(cfg, ji);
1370 		NAT64STAT_INC(&cfg->base.stats, jhostsreq);
1371 		*mp = NULL;
1372 	}
1373 	return (IP_FW_DENY);
1374 }
1375 
1376 static int
1377 nat64lsn_request_pg(struct nat64lsn_cfg *cfg, struct nat64lsn_host *host,
1378     const struct ipfw_flow_id *f_id, struct mbuf **mp, uint32_t hval,
1379     in_addr_t faddr, uint16_t port, uint8_t proto)
1380 {
1381 	struct nat64lsn_job_item *ji;
1382 
1383 	ji = nat64lsn_create_job(cfg, JTYPE_NEWPORTGROUP);
1384 	if (ji != NULL) {
1385 		ji->m = *mp;
1386 		ji->f_id = *f_id;
1387 		ji->faddr = faddr;
1388 		ji->port = port;
1389 		ji->proto = proto;
1390 		ji->state_hval = hval;
1391 		ji->host = host;
1392 
1393 		nat64lsn_enqueue_job(cfg, ji);
1394 		NAT64STAT_INC(&cfg->base.stats, jportreq);
1395 		*mp = NULL;
1396 	}
1397 	return (IP_FW_DENY);
1398 }
1399 
1400 static int
1401 nat64lsn_translate6_internal(struct nat64lsn_cfg *cfg, struct mbuf **mp,
1402     struct nat64lsn_state *state, uint8_t flags)
1403 {
1404 	struct pfloghdr loghdr, *logdata;
1405 	int ret;
1406 	uint16_t ts;
1407 
1408 	/* Update timestamp and flags if needed */
1409 	SET_AGE(ts);
1410 	if (state->timestamp != ts)
1411 		state->timestamp = ts;
1412 	if ((state->flags & flags) != 0)
1413 		state->flags |= flags;
1414 
1415 	if (cfg->base.flags & NAT64_LOG) {
1416 		logdata = &loghdr;
1417 		nat64lsn_log(logdata, *mp, AF_INET6, state);
1418 	} else
1419 		logdata = NULL;
1420 
1421 	ret = nat64_do_handle_ip6(*mp, htonl(state->ip_src),
1422 	    htons(state->aport), &cfg->base, logdata);
1423 	if (ret == NAT64SKIP)
1424 		return (cfg->nomatch_verdict);
1425 	if (ret == NAT64RETURN)
1426 		*mp = NULL;
1427 	return (IP_FW_DENY);
1428 }
1429 
1430 static int
1431 nat64lsn_translate6(struct nat64lsn_cfg *cfg, struct ipfw_flow_id *f_id,
1432     struct mbuf **mp)
1433 {
1434 	struct nat64lsn_state *state;
1435 	struct nat64lsn_host *host;
1436 	struct icmp6_hdr *icmp6;
1437 	uint32_t addr, hval, data[2];
1438 	int offset, proto;
1439 	uint16_t port;
1440 	uint8_t flags;
1441 
1442 	/* Check if protocol is supported */
1443 	port = f_id->src_port;
1444 	proto = f_id->proto;
1445 	switch (f_id->proto) {
1446 	case IPPROTO_ICMPV6:
1447 		/*
1448 		 * For ICMPv6 echo reply/request we use icmp6_id as
1449 		 * local port.
1450 		 */
1451 		offset = 0;
1452 		proto = nat64_getlasthdr(*mp, &offset);
1453 		if (proto < 0) {
1454 			NAT64STAT_INC(&cfg->base.stats, dropped);
1455 			DPRINTF(DP_DROPS, "mbuf isn't contigious");
1456 			return (IP_FW_DENY);
1457 		}
1458 		if (proto == IPPROTO_ICMPV6) {
1459 			icmp6 = mtodo(*mp, offset);
1460 			if (icmp6->icmp6_type == ICMP6_ECHO_REQUEST ||
1461 			    icmp6->icmp6_type == ICMP6_ECHO_REPLY)
1462 				port = ntohs(icmp6->icmp6_id);
1463 		}
1464 		proto = IPPROTO_ICMP;
1465 		/* FALLTHROUGH */
1466 	case IPPROTO_TCP:
1467 	case IPPROTO_UDP:
1468 		break;
1469 	default:
1470 		NAT64STAT_INC(&cfg->base.stats, noproto);
1471 		return (cfg->nomatch_verdict);
1472 	}
1473 
1474 	/* Extract IPv4 from destination IPv6 address */
1475 	addr = nat64_extract_ip4(&f_id->dst_ip6, cfg->base.plat_plen);
1476 	if (addr == 0 || nat64_check_private_ip4(&cfg->base, addr) != 0) {
1477 		char a[INET_ADDRSTRLEN];
1478 
1479 		NAT64STAT_INC(&cfg->base.stats, dropped);
1480 		DPRINTF(DP_DROPS, "dropped due to embedded IPv4 address %s",
1481 		    inet_ntop(AF_INET, &addr, a, sizeof(a)));
1482 		return (IP_FW_DENY); /* XXX: add extra stats? */
1483 	}
1484 
1485 	/* Try to find host */
1486 	hval = HOST_HVAL(cfg, &f_id->src_ip6);
1487 	CK_SLIST_FOREACH(host, &HOSTS(cfg, hval), entries) {
1488 		if (IN6_ARE_ADDR_EQUAL(&f_id->src_ip6, &host->addr))
1489 			break;
1490 	}
1491 	/* We use IPv4 address in host byte order */
1492 	addr = ntohl(addr);
1493 	if (host == NULL)
1494 		return (nat64lsn_request_host(cfg, f_id, mp,
1495 		    hval, addr, port, proto));
1496 
1497 	flags = proto != IPPROTO_TCP ? 0 : convert_tcp_flags(f_id->_flags);
1498 
1499 	data[0] = addr;
1500 	data[1] = (f_id->dst_port << 16) | port;
1501 	hval = STATE_HVAL(cfg, data);
1502 	state = nat64lsn_get_state6to4(cfg, host, f_id, hval, addr,
1503 	    port, proto);
1504 	if (state == NULL)
1505 		return (nat64lsn_request_pg(cfg, host, f_id, mp, hval, addr,
1506 		    port, proto));
1507 	return (nat64lsn_translate6_internal(cfg, mp, state, flags));
1508 }
1509 
1510 /*
1511  * Main dataplane entry point.
1512  */
1513 int
1514 ipfw_nat64lsn(struct ip_fw_chain *ch, struct ip_fw_args *args,
1515     ipfw_insn *cmd, int *done)
1516 {
1517 	struct nat64lsn_cfg *cfg;
1518 	ipfw_insn *icmd;
1519 	int ret;
1520 
1521 	IPFW_RLOCK_ASSERT(ch);
1522 
1523 	*done = 0;	/* continue the search in case of failure */
1524 	icmd = cmd + 1;
1525 	if (cmd->opcode != O_EXTERNAL_ACTION ||
1526 	    cmd->arg1 != V_nat64lsn_eid ||
1527 	    icmd->opcode != O_EXTERNAL_INSTANCE ||
1528 	    (cfg = NAT64_LOOKUP(ch, icmd)) == NULL)
1529 		return (IP_FW_DENY);
1530 
1531 	*done = 1;	/* terminate the search */
1532 
1533 	switch (args->f_id.addr_type) {
1534 	case 4:
1535 		ret = nat64lsn_translate4(cfg, &args->f_id, &args->m);
1536 		break;
1537 	case 6:
1538 		/*
1539 		 * Check that destination IPv6 address matches our prefix6.
1540 		 */
1541 		if ((cfg->base.flags & NAT64LSN_ANYPREFIX) == 0 &&
1542 		    memcmp(&args->f_id.dst_ip6, &cfg->base.plat_prefix,
1543 		    cfg->base.plat_plen / 8) != 0) {
1544 			ret = cfg->nomatch_verdict;
1545 			break;
1546 		}
1547 		ret = nat64lsn_translate6(cfg, &args->f_id, &args->m);
1548 		break;
1549 	default:
1550 		ret = cfg->nomatch_verdict;
1551 	}
1552 
1553 	if (ret != IP_FW_PASS && args->m != NULL) {
1554 		m_freem(args->m);
1555 		args->m = NULL;
1556 	}
1557 	return (ret);
1558 }
1559 
1560 static int
1561 nat64lsn_state_ctor(void *mem, int size, void *arg, int flags)
1562 {
1563 	struct nat64lsn_states_chunk *chunk;
1564 	int i;
1565 
1566 	chunk = (struct nat64lsn_states_chunk *)mem;
1567 	for (i = 0; i < 64; i++)
1568 		chunk->state[i].flags = 0;
1569 	return (0);
1570 }
1571 
1572 void
1573 nat64lsn_init_internal(void)
1574 {
1575 
1576 	nat64lsn_host_zone = uma_zcreate("NAT64LSN hosts",
1577 	    sizeof(struct nat64lsn_host), NULL, NULL, NULL, NULL,
1578 	    UMA_ALIGN_PTR, 0);
1579 	nat64lsn_pgchunk_zone = uma_zcreate("NAT64LSN portgroup chunks",
1580 	    sizeof(struct nat64lsn_pgchunk), NULL, NULL, NULL, NULL,
1581 	    UMA_ALIGN_PTR, 0);
1582 	nat64lsn_pg_zone = uma_zcreate("NAT64LSN portgroups",
1583 	    sizeof(struct nat64lsn_pg), NULL, NULL, NULL, NULL,
1584 	    UMA_ALIGN_PTR, 0);
1585 	nat64lsn_aliaslink_zone = uma_zcreate("NAT64LSN links",
1586 	    sizeof(struct nat64lsn_aliaslink), NULL, NULL, NULL, NULL,
1587 	    UMA_ALIGN_PTR, 0);
1588 	nat64lsn_state_zone = uma_zcreate("NAT64LSN states",
1589 	    sizeof(struct nat64lsn_states_chunk), nat64lsn_state_ctor,
1590 	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
1591 	nat64lsn_job_zone = uma_zcreate("NAT64LSN jobs",
1592 	    sizeof(struct nat64lsn_job_item), NULL, NULL, NULL, NULL,
1593 	    UMA_ALIGN_PTR, 0);
1594 	JQUEUE_LOCK_INIT();
1595 }
1596 
1597 void
1598 nat64lsn_uninit_internal(void)
1599 {
1600 
1601 	/* XXX: epoch_task drain */
1602 	JQUEUE_LOCK_DESTROY();
1603 	uma_zdestroy(nat64lsn_host_zone);
1604 	uma_zdestroy(nat64lsn_pgchunk_zone);
1605 	uma_zdestroy(nat64lsn_pg_zone);
1606 	uma_zdestroy(nat64lsn_aliaslink_zone);
1607 	uma_zdestroy(nat64lsn_state_zone);
1608 	uma_zdestroy(nat64lsn_job_zone);
1609 }
1610 
1611 void
1612 nat64lsn_start_instance(struct nat64lsn_cfg *cfg)
1613 {
1614 
1615 	CALLOUT_LOCK(cfg);
1616 	callout_reset(&cfg->periodic, hz * PERIODIC_DELAY,
1617 	    nat64lsn_periodic, cfg);
1618 	CALLOUT_UNLOCK(cfg);
1619 }
1620 
1621 struct nat64lsn_cfg *
1622 nat64lsn_init_instance(struct ip_fw_chain *ch, in_addr_t prefix, int plen)
1623 {
1624 	struct nat64lsn_cfg *cfg;
1625 	struct nat64lsn_alias *alias;
1626 	int i, naddr;
1627 
1628 	cfg = malloc(sizeof(struct nat64lsn_cfg), M_NAT64LSN,
1629 	    M_WAITOK | M_ZERO);
1630 
1631 	CFG_LOCK_INIT(cfg);
1632 	CALLOUT_LOCK_INIT(cfg);
1633 	STAILQ_INIT(&cfg->jhead);
1634 	cfg->vp = curvnet;
1635 	COUNTER_ARRAY_ALLOC(cfg->base.stats.cnt, NAT64STATS, M_WAITOK);
1636 
1637 	cfg->hash_seed = arc4random();
1638 	cfg->hosts_hashsize = NAT64LSN_HOSTS_HSIZE;
1639 	cfg->hosts_hash = malloc(sizeof(struct nat64lsn_hosts_slist) *
1640 	    cfg->hosts_hashsize, M_NAT64LSN, M_WAITOK | M_ZERO);
1641 	for (i = 0; i < cfg->hosts_hashsize; i++)
1642 		CK_SLIST_INIT(&cfg->hosts_hash[i]);
1643 
1644 	naddr = 1 << (32 - plen);
1645 	cfg->prefix4 = prefix;
1646 	cfg->pmask4 = prefix | (naddr - 1);
1647 	cfg->plen4 = plen;
1648 	cfg->aliases = malloc(sizeof(struct nat64lsn_alias) * naddr,
1649 	    M_NAT64LSN, M_WAITOK | M_ZERO);
1650 	for (i = 0; i < naddr; i++) {
1651 		alias = &cfg->aliases[i];
1652 		alias->addr = prefix + i; /* host byte order */
1653 		CK_SLIST_INIT(&alias->hosts);
1654 		ALIAS_LOCK_INIT(alias);
1655 	}
1656 
1657         callout_init_mtx(&cfg->periodic, &cfg->periodic_lock, 0);
1658         callout_init(&cfg->jcallout, CALLOUT_MPSAFE);
1659 
1660 	return (cfg);
1661 }
1662 
1663 static void
1664 nat64lsn_destroy_pg(struct nat64lsn_pg *pg)
1665 {
1666 	int i;
1667 
1668 	if (pg->chunks_count == 1) {
1669 		uma_zfree(nat64lsn_state_zone, pg->states);
1670 	} else {
1671 		for (i = 0; i < pg->chunks_count; i++)
1672 			uma_zfree(nat64lsn_state_zone, pg->states_chunk[i]);
1673 		free(pg->states_chunk, M_NAT64LSN);
1674 		free(pg->freemask_chunk, M_NAT64LSN);
1675 	}
1676 	uma_zfree(nat64lsn_pg_zone, pg);
1677 }
1678 
1679 static void
1680 nat64lsn_destroy_alias(struct nat64lsn_cfg *cfg,
1681     struct nat64lsn_alias *alias)
1682 {
1683 	struct nat64lsn_pg *pg;
1684 	int i;
1685 
1686 	while (!CK_SLIST_EMPTY(&alias->portgroups)) {
1687 		pg = CK_SLIST_FIRST(&alias->portgroups);
1688 		CK_SLIST_REMOVE_HEAD(&alias->portgroups, entries);
1689 		nat64lsn_destroy_pg(pg);
1690 	}
1691 	for (i = 0; i < 32; i++) {
1692 		if (ISSET32(alias->tcp_chunkmask, i))
1693 			uma_zfree(nat64lsn_pgchunk_zone, alias->tcp[i]);
1694 		if (ISSET32(alias->udp_chunkmask, i))
1695 			uma_zfree(nat64lsn_pgchunk_zone, alias->udp[i]);
1696 		if (ISSET32(alias->icmp_chunkmask, i))
1697 			uma_zfree(nat64lsn_pgchunk_zone, alias->icmp[i]);
1698 	}
1699 	ALIAS_LOCK_DESTROY(alias);
1700 }
1701 
1702 static void
1703 nat64lsn_destroy_host(struct nat64lsn_host *host)
1704 {
1705 	struct nat64lsn_aliaslink *link;
1706 
1707 	while (!CK_SLIST_EMPTY(&host->aliases)) {
1708 		link = CK_SLIST_FIRST(&host->aliases);
1709 		CK_SLIST_REMOVE_HEAD(&host->aliases, host_entries);
1710 
1711 		ALIAS_LOCK(link->alias);
1712 		CK_SLIST_REMOVE(&link->alias->hosts, link,
1713 		    nat64lsn_aliaslink, alias_entries);
1714 		link->alias->hosts_count--;
1715 		ALIAS_UNLOCK(link->alias);
1716 
1717 		uma_zfree(nat64lsn_aliaslink_zone, link);
1718 	}
1719 	HOST_LOCK_DESTROY(host);
1720 	free(host->states_hash, M_NAT64LSN);
1721 	uma_zfree(nat64lsn_host_zone, host);
1722 }
1723 
1724 void
1725 nat64lsn_destroy_instance(struct nat64lsn_cfg *cfg)
1726 {
1727 	struct nat64lsn_host *host;
1728 	int i;
1729 
1730 	CALLOUT_LOCK(cfg);
1731 	callout_drain(&cfg->periodic);
1732 	CALLOUT_UNLOCK(cfg);
1733 	callout_drain(&cfg->jcallout);
1734 
1735 	for (i = 0; i < cfg->hosts_hashsize; i++) {
1736 		while (!CK_SLIST_EMPTY(&cfg->hosts_hash[i])) {
1737 			host = CK_SLIST_FIRST(&cfg->hosts_hash[i]);
1738 			CK_SLIST_REMOVE_HEAD(&cfg->hosts_hash[i], entries);
1739 			nat64lsn_destroy_host(host);
1740 		}
1741 	}
1742 
1743 	for (i = 0; i < (1 << (32 - cfg->plen4)); i++)
1744 		nat64lsn_destroy_alias(cfg, &cfg->aliases[i]);
1745 
1746 	CALLOUT_LOCK_DESTROY(cfg);
1747 	CFG_LOCK_DESTROY(cfg);
1748 	COUNTER_ARRAY_FREE(cfg->base.stats.cnt, NAT64STATS);
1749 	free(cfg->hosts_hash, M_NAT64LSN);
1750 	free(cfg->aliases, M_NAT64LSN);
1751 	free(cfg, M_NAT64LSN);
1752 }
1753 
1754