xref: /illumos-gate/usr/src/uts/common/inet/ipf/ip_nat.c (revision 5338faaa)
17c478bd9Sstevel@tonic-gate /*
227dbc409San  * Copyright (C) 1995-2004 by Darren Reed.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate  *
633f2fefdSDarren Reed  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
77c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
87c478bd9Sstevel@tonic-gate  */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
117c478bd9Sstevel@tonic-gate # undef KERNEL
127c478bd9Sstevel@tonic-gate # undef _KERNEL
137c478bd9Sstevel@tonic-gate # define        KERNEL	1
147c478bd9Sstevel@tonic-gate # define        _KERNEL	1
157c478bd9Sstevel@tonic-gate #endif
167c478bd9Sstevel@tonic-gate #include <sys/errno.h>
177c478bd9Sstevel@tonic-gate #include <sys/types.h>
187c478bd9Sstevel@tonic-gate #include <sys/param.h>
197c478bd9Sstevel@tonic-gate #include <sys/time.h>
207c478bd9Sstevel@tonic-gate #include <sys/file.h>
217c478bd9Sstevel@tonic-gate #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
227c478bd9Sstevel@tonic-gate     defined(_KERNEL)
237c478bd9Sstevel@tonic-gate # include "opt_ipfilter_log.h"
247c478bd9Sstevel@tonic-gate #endif
257c478bd9Sstevel@tonic-gate #if !defined(_KERNEL)
267c478bd9Sstevel@tonic-gate # include <stdio.h>
277c478bd9Sstevel@tonic-gate # include <string.h>
287c478bd9Sstevel@tonic-gate # include <stdlib.h>
297c478bd9Sstevel@tonic-gate # define _KERNEL
307c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
317c478bd9Sstevel@tonic-gate struct file;
327c478bd9Sstevel@tonic-gate # endif
337c478bd9Sstevel@tonic-gate # include <sys/uio.h>
347c478bd9Sstevel@tonic-gate # undef _KERNEL
357c478bd9Sstevel@tonic-gate #endif
367c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
377c478bd9Sstevel@tonic-gate # include <sys/filio.h>
387c478bd9Sstevel@tonic-gate # include <sys/fcntl.h>
397c478bd9Sstevel@tonic-gate #else
407c478bd9Sstevel@tonic-gate # include <sys/ioctl.h>
417c478bd9Sstevel@tonic-gate #endif
42ab25eeb5Syz #if !defined(AIX)
43ab25eeb5Syz # include <sys/fcntl.h>
44ab25eeb5Syz #endif
45ab25eeb5Syz #if !defined(linux)
46ab25eeb5Syz # include <sys/protosw.h>
47ab25eeb5Syz #endif
487c478bd9Sstevel@tonic-gate #include <sys/socket.h>
497c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
507c478bd9Sstevel@tonic-gate # include <sys/systm.h>
517c478bd9Sstevel@tonic-gate # if !defined(__SVR4) && !defined(__svr4__)
527c478bd9Sstevel@tonic-gate #  include <sys/mbuf.h>
537c478bd9Sstevel@tonic-gate # endif
547c478bd9Sstevel@tonic-gate #endif
557c478bd9Sstevel@tonic-gate #if defined(__SVR4) || defined(__svr4__)
567c478bd9Sstevel@tonic-gate # include <sys/filio.h>
577c478bd9Sstevel@tonic-gate # include <sys/byteorder.h>
587c478bd9Sstevel@tonic-gate # ifdef _KERNEL
597c478bd9Sstevel@tonic-gate #  include <sys/dditypes.h>
607c478bd9Sstevel@tonic-gate # endif
617c478bd9Sstevel@tonic-gate # include <sys/stream.h>
627c478bd9Sstevel@tonic-gate # include <sys/kmem.h>
637c478bd9Sstevel@tonic-gate #endif
647c478bd9Sstevel@tonic-gate #if __FreeBSD_version >= 300000
657c478bd9Sstevel@tonic-gate # include <sys/queue.h>
667c478bd9Sstevel@tonic-gate #endif
677c478bd9Sstevel@tonic-gate #include <net/if.h>
687c478bd9Sstevel@tonic-gate #if __FreeBSD_version >= 300000
697c478bd9Sstevel@tonic-gate # include <net/if_var.h>
707c478bd9Sstevel@tonic-gate # if defined(_KERNEL) && !defined(IPFILTER_LKM)
717c478bd9Sstevel@tonic-gate #  include "opt_ipfilter.h"
727c478bd9Sstevel@tonic-gate # endif
737c478bd9Sstevel@tonic-gate #endif
747c478bd9Sstevel@tonic-gate #ifdef sun
757c478bd9Sstevel@tonic-gate # include <net/af.h>
767c478bd9Sstevel@tonic-gate #endif
777c478bd9Sstevel@tonic-gate #include <net/route.h>
787c478bd9Sstevel@tonic-gate #include <netinet/in.h>
797c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h>
807c478bd9Sstevel@tonic-gate #include <netinet/ip.h>
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate #ifdef RFC1825
837c478bd9Sstevel@tonic-gate # include <vpn/md5.h>
847c478bd9Sstevel@tonic-gate # include <vpn/ipsec.h>
857c478bd9Sstevel@tonic-gate extern struct ifnet vpnif;
867c478bd9Sstevel@tonic-gate #endif
877c478bd9Sstevel@tonic-gate 
88ab25eeb5Syz #if !defined(linux)
89ab25eeb5Syz # include <netinet/ip_var.h>
90ab25eeb5Syz #endif
917c478bd9Sstevel@tonic-gate #include <netinet/tcp.h>
927c478bd9Sstevel@tonic-gate #include <netinet/udp.h>
937c478bd9Sstevel@tonic-gate #include <netinet/ip_icmp.h>
947c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
95ab25eeb5Syz #include <netinet/tcpip.h>
967c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
977c478bd9Sstevel@tonic-gate #include "netinet/ip_nat.h"
987c478bd9Sstevel@tonic-gate #include "netinet/ip_frag.h"
997c478bd9Sstevel@tonic-gate #include "netinet/ip_state.h"
1007c478bd9Sstevel@tonic-gate #include "netinet/ip_proxy.h"
101f4b3ec61Sdh #include "netinet/ipf_stack.h"
1027c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_SYNC
1037c478bd9Sstevel@tonic-gate #include "netinet/ip_sync.h"
1047c478bd9Sstevel@tonic-gate #endif
1057c478bd9Sstevel@tonic-gate #if (__FreeBSD_version >= 300000)
1067c478bd9Sstevel@tonic-gate # include <sys/malloc.h>
1077c478bd9Sstevel@tonic-gate #endif
108ab25eeb5Syz /* END OF INCLUDES */
109ab25eeb5Syz 
1107c478bd9Sstevel@tonic-gate #undef	SOCKADDR_IN
1117c478bd9Sstevel@tonic-gate #define	SOCKADDR_IN	struct sockaddr_in
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate #if !defined(lint)
1147c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)ip_nat.c	1.11 6/5/96 (C) 1995 Darren Reed";
115ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_nat.c,v 2.195.2.42 2005/08/11 19:51:36 darrenr Exp $";
1167c478bd9Sstevel@tonic-gate #endif
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /* ======================================================================== */
1207c478bd9Sstevel@tonic-gate /* How the NAT is organised and works.                                      */
1217c478bd9Sstevel@tonic-gate /*                                                                          */
1227c478bd9Sstevel@tonic-gate /* Inside (interface y) NAT       Outside (interface x)                     */
1237c478bd9Sstevel@tonic-gate /* -------------------- -+- -------------------------------------           */
1247c478bd9Sstevel@tonic-gate /* Packet going          |   out, processsed by fr_checknatout() for x      */
1257c478bd9Sstevel@tonic-gate /* ------------>         |   ------------>                                  */
1267c478bd9Sstevel@tonic-gate /* src=10.1.1.1          |   src=192.1.1.1                                  */
1277c478bd9Sstevel@tonic-gate /*                       |                                                  */
1287c478bd9Sstevel@tonic-gate /*                       |   in, processed by fr_checknatin() for x         */
1297c478bd9Sstevel@tonic-gate /* <------------         |   <------------                                  */
1307c478bd9Sstevel@tonic-gate /* dst=10.1.1.1          |   dst=192.1.1.1                                  */
1317c478bd9Sstevel@tonic-gate /* -------------------- -+- -------------------------------------           */
1327c478bd9Sstevel@tonic-gate /* fr_checknatout() - changes ip_src and if required, sport                 */
1337c478bd9Sstevel@tonic-gate /*             - creates a new mapping, if required.                        */
1347c478bd9Sstevel@tonic-gate /* fr_checknatin()  - changes ip_dst and if required, dport                 */
1357c478bd9Sstevel@tonic-gate /*                                                                          */
1367c478bd9Sstevel@tonic-gate /* In the NAT table, internal source is recorded as "in" and externally     */
1377c478bd9Sstevel@tonic-gate /* seen as "out".                                                           */
1387c478bd9Sstevel@tonic-gate /* ======================================================================== */
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 
141f4b3ec61Sdh static	int	nat_clearlist __P((ipf_stack_t *));
142f4b3ec61Sdh static	void	nat_addnat __P((struct ipnat *, ipf_stack_t *));
143f4b3ec61Sdh static	void	nat_addrdr __P((struct ipnat *, ipf_stack_t *));
144f4b3ec61Sdh static	int	fr_natgetent __P((caddr_t, ipf_stack_t *));
145f4b3ec61Sdh static	int	fr_natgetsz __P((caddr_t, ipf_stack_t *));
146f4b3ec61Sdh static	int	fr_natputent __P((caddr_t, int, ipf_stack_t *));
147f4b3ec61Sdh static	void	nat_tabmove __P((nat_t *, ipf_stack_t *));
1487c478bd9Sstevel@tonic-gate static	int	nat_match __P((fr_info_t *, ipnat_t *));
1497c478bd9Sstevel@tonic-gate static	INLINE	int nat_newmap __P((fr_info_t *, nat_t *, natinfo_t *));
1507c478bd9Sstevel@tonic-gate static	INLINE	int nat_newrdr __P((fr_info_t *, nat_t *, natinfo_t *));
1517c478bd9Sstevel@tonic-gate static	hostmap_t *nat_hostmap __P((ipnat_t *, struct in_addr,
152f4b3ec61Sdh 				    struct in_addr, struct in_addr, u_32_t,
153f4b3ec61Sdh 				    ipf_stack_t *));
1547c478bd9Sstevel@tonic-gate static	INLINE	int nat_icmpquerytype4 __P((int));
155d6c23f6fSyx static	int	nat_ruleaddrinit __P((ipnat_t *));
156d6c23f6fSyx static	int	nat_siocaddnat __P((ipnat_t *, ipnat_t **, int, ipf_stack_t *));
157d6c23f6fSyx static	void	nat_siocdelnat __P((ipnat_t *, ipnat_t **, int, ipf_stack_t *));
158f4b3ec61Sdh static	INLINE	int nat_icmperrortype4 __P((int));
1597c478bd9Sstevel@tonic-gate static	INLINE	int nat_finalise __P((fr_info_t *, nat_t *, natinfo_t *,
1607c478bd9Sstevel@tonic-gate 				      tcphdr_t *, nat_t **, int));
161dcf3e898Sjojemann static	INLINE	int nat_resolverule __P((ipnat_t *, ipf_stack_t *));
162381a2a9aSdr static	void	nat_mssclamp __P((tcphdr_t *, u_32_t, u_short *));
163f4b3ec61Sdh static	int	nat_getnext __P((ipftoken_t *, ipfgeniter_t *, ipf_stack_t *));
164f4b3ec61Sdh static	int	nat_iterator __P((ipftoken_t *, ipfgeniter_t *, ipf_stack_t *));
165ea8244dcSJohn Ojemann static	int	nat_flushtable __P((int, ipf_stack_t *));
1667c478bd9Sstevel@tonic-gate 
1673c50f6d6San #define NAT_HAS_L4_CHANGED(n)	\
16827dbc409San  	(((n)->nat_flags & (IPN_TCPUDPICMP)) && \
16927dbc409San  	(n)->nat_inport != (n)->nat_outport)
1707c478bd9Sstevel@tonic-gate 
171ea8244dcSJohn Ojemann 
1727c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
1737c478bd9Sstevel@tonic-gate /* Function:    fr_natinit                                                  */
1747c478bd9Sstevel@tonic-gate /* Returns:     int - 0 == success, -1 == failure                           */
1757c478bd9Sstevel@tonic-gate /* Parameters:  Nil                                                         */
1767c478bd9Sstevel@tonic-gate /*                                                                          */
1777c478bd9Sstevel@tonic-gate /* Initialise all of the NAT locks, tables and other structures.            */
1787c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_natinit(ifs)179f4b3ec61Sdh int fr_natinit(ifs)
180f4b3ec61Sdh ipf_stack_t *ifs;
1817c478bd9Sstevel@tonic-gate {
1827c478bd9Sstevel@tonic-gate 	int i;
1837c478bd9Sstevel@tonic-gate 
184f4b3ec61Sdh 	KMALLOCS(ifs->ifs_nat_table[0], nat_t **,
185f4b3ec61Sdh 		 sizeof(nat_t *) * ifs->ifs_ipf_nattable_sz);
186f4b3ec61Sdh 	if (ifs->ifs_nat_table[0] != NULL)
187f4b3ec61Sdh 		bzero((char *)ifs->ifs_nat_table[0],
188f4b3ec61Sdh 		      ifs->ifs_ipf_nattable_sz * sizeof(nat_t *));
1897c478bd9Sstevel@tonic-gate 	else
1907c478bd9Sstevel@tonic-gate 		return -1;
1917c478bd9Sstevel@tonic-gate 
192f4b3ec61Sdh 	KMALLOCS(ifs->ifs_nat_table[1], nat_t **,
193f4b3ec61Sdh 		 sizeof(nat_t *) * ifs->ifs_ipf_nattable_sz);
194f4b3ec61Sdh 	if (ifs->ifs_nat_table[1] != NULL)
195f4b3ec61Sdh 		bzero((char *)ifs->ifs_nat_table[1],
196f4b3ec61Sdh 		      ifs->ifs_ipf_nattable_sz * sizeof(nat_t *));
1977c478bd9Sstevel@tonic-gate 	else
198ab25eeb5Syz 		return -2;
1997c478bd9Sstevel@tonic-gate 
200f4b3ec61Sdh 	KMALLOCS(ifs->ifs_nat_rules, ipnat_t **,
201f4b3ec61Sdh 		 sizeof(ipnat_t *) * ifs->ifs_ipf_natrules_sz);
202f4b3ec61Sdh 	if (ifs->ifs_nat_rules != NULL)
203f4b3ec61Sdh 		bzero((char *)ifs->ifs_nat_rules,
204f4b3ec61Sdh 		      ifs->ifs_ipf_natrules_sz * sizeof(ipnat_t *));
2057c478bd9Sstevel@tonic-gate 	else
206ab25eeb5Syz 		return -3;
2077c478bd9Sstevel@tonic-gate 
208f4b3ec61Sdh 	KMALLOCS(ifs->ifs_rdr_rules, ipnat_t **,
209f4b3ec61Sdh 		 sizeof(ipnat_t *) * ifs->ifs_ipf_rdrrules_sz);
210f4b3ec61Sdh 	if (ifs->ifs_rdr_rules != NULL)
211f4b3ec61Sdh 		bzero((char *)ifs->ifs_rdr_rules,
212f4b3ec61Sdh 		      ifs->ifs_ipf_rdrrules_sz * sizeof(ipnat_t *));
2137c478bd9Sstevel@tonic-gate 	else
214ab25eeb5Syz 		return -4;
2157c478bd9Sstevel@tonic-gate 
216f4b3ec61Sdh 	KMALLOCS(ifs->ifs_maptable, hostmap_t **,
217f4b3ec61Sdh 		 sizeof(hostmap_t *) * ifs->ifs_ipf_hostmap_sz);
218f4b3ec61Sdh 	if (ifs->ifs_maptable != NULL)
219f4b3ec61Sdh 		bzero((char *)ifs->ifs_maptable,
220f4b3ec61Sdh 		      sizeof(hostmap_t *) * ifs->ifs_ipf_hostmap_sz);
2217c478bd9Sstevel@tonic-gate 	else
222ab25eeb5Syz 		return -5;
2237c478bd9Sstevel@tonic-gate 
224f4b3ec61Sdh 	ifs->ifs_ipf_hm_maplist = NULL;
225f4b3ec61Sdh 
226f4b3ec61Sdh 	KMALLOCS(ifs->ifs_nat_stats.ns_bucketlen[0], u_long *,
227f4b3ec61Sdh 		 ifs->ifs_ipf_nattable_sz * sizeof(u_long));
228f4b3ec61Sdh 	if (ifs->ifs_nat_stats.ns_bucketlen[0] == NULL)
229f4b3ec61Sdh 		return -1;
230f4b3ec61Sdh 	bzero((char *)ifs->ifs_nat_stats.ns_bucketlen[0],
231f4b3ec61Sdh 	      ifs->ifs_ipf_nattable_sz * sizeof(u_long));
232f4b3ec61Sdh 
233f4b3ec61Sdh 	KMALLOCS(ifs->ifs_nat_stats.ns_bucketlen[1], u_long *,
234f4b3ec61Sdh 		 ifs->ifs_ipf_nattable_sz * sizeof(u_long));
235f4b3ec61Sdh 	if (ifs->ifs_nat_stats.ns_bucketlen[1] == NULL)
236f4b3ec61Sdh 		return -1;
237f4b3ec61Sdh 	bzero((char *)ifs->ifs_nat_stats.ns_bucketlen[1],
238f4b3ec61Sdh 	      ifs->ifs_ipf_nattable_sz * sizeof(u_long));
239f4b3ec61Sdh 
240f4b3ec61Sdh 	if (ifs->ifs_fr_nat_maxbucket == 0) {
241f4b3ec61Sdh 		for (i = ifs->ifs_ipf_nattable_sz; i > 0; i >>= 1)
242f4b3ec61Sdh 			ifs->ifs_fr_nat_maxbucket++;
243f4b3ec61Sdh 		ifs->ifs_fr_nat_maxbucket *= 2;
2447c478bd9Sstevel@tonic-gate 	}
2457c478bd9Sstevel@tonic-gate 
246f4b3ec61Sdh 	fr_sttab_init(ifs->ifs_nat_tqb, ifs);
2477c478bd9Sstevel@tonic-gate 	/*
2487c478bd9Sstevel@tonic-gate 	 * Increase this because we may have "keep state" following this too
2497c478bd9Sstevel@tonic-gate 	 * and packet storms can occur if this is removed too quickly.
2507c478bd9Sstevel@tonic-gate 	 */
251f4b3ec61Sdh 	ifs->ifs_nat_tqb[IPF_TCPS_CLOSED].ifq_ttl = ifs->ifs_fr_tcplastack;
252f4b3ec61Sdh 	ifs->ifs_nat_tqb[IPF_TCP_NSTATES - 1].ifq_next = &ifs->ifs_nat_udptq;
253f4b3ec61Sdh 	ifs->ifs_nat_udptq.ifq_ttl = ifs->ifs_fr_defnatage;
254f4b3ec61Sdh 	ifs->ifs_nat_udptq.ifq_ref = 1;
255f4b3ec61Sdh 	ifs->ifs_nat_udptq.ifq_head = NULL;
256f4b3ec61Sdh 	ifs->ifs_nat_udptq.ifq_tail = &ifs->ifs_nat_udptq.ifq_head;
257f4b3ec61Sdh 	MUTEX_INIT(&ifs->ifs_nat_udptq.ifq_lock, "nat ipftq udp tab");
258f4b3ec61Sdh 	ifs->ifs_nat_udptq.ifq_next = &ifs->ifs_nat_icmptq;
259f4b3ec61Sdh 	ifs->ifs_nat_icmptq.ifq_ttl = ifs->ifs_fr_defnaticmpage;
260f4b3ec61Sdh 	ifs->ifs_nat_icmptq.ifq_ref = 1;
261f4b3ec61Sdh 	ifs->ifs_nat_icmptq.ifq_head = NULL;
262f4b3ec61Sdh 	ifs->ifs_nat_icmptq.ifq_tail = &ifs->ifs_nat_icmptq.ifq_head;
263f4b3ec61Sdh 	MUTEX_INIT(&ifs->ifs_nat_icmptq.ifq_lock, "nat icmp ipftq tab");
264f4b3ec61Sdh 	ifs->ifs_nat_icmptq.ifq_next = &ifs->ifs_nat_iptq;
265f4b3ec61Sdh 	ifs->ifs_nat_iptq.ifq_ttl = ifs->ifs_fr_defnatipage;
266f4b3ec61Sdh 	ifs->ifs_nat_iptq.ifq_ref = 1;
267f4b3ec61Sdh 	ifs->ifs_nat_iptq.ifq_head = NULL;
268f4b3ec61Sdh 	ifs->ifs_nat_iptq.ifq_tail = &ifs->ifs_nat_iptq.ifq_head;
269f4b3ec61Sdh 	MUTEX_INIT(&ifs->ifs_nat_iptq.ifq_lock, "nat ip ipftq tab");
270f4b3ec61Sdh 	ifs->ifs_nat_iptq.ifq_next = NULL;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	for (i = 0; i < IPF_TCP_NSTATES; i++) {
273f4b3ec61Sdh 		if (ifs->ifs_nat_tqb[i].ifq_ttl < ifs->ifs_fr_defnaticmpage)
274f4b3ec61Sdh 			ifs->ifs_nat_tqb[i].ifq_ttl = ifs->ifs_fr_defnaticmpage;
2757c478bd9Sstevel@tonic-gate #ifdef LARGE_NAT
276f4b3ec61Sdh 		else if (ifs->ifs_nat_tqb[i].ifq_ttl > ifs->ifs_fr_defnatage)
277f4b3ec61Sdh 			ifs->ifs_nat_tqb[i].ifq_ttl = ifs->ifs_fr_defnatage;
2787c478bd9Sstevel@tonic-gate #endif
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	/*
2827c478bd9Sstevel@tonic-gate 	 * Increase this because we may have "keep state" following
2837c478bd9Sstevel@tonic-gate 	 * this too and packet storms can occur if this is removed
2847c478bd9Sstevel@tonic-gate 	 * too quickly.
2857c478bd9Sstevel@tonic-gate 	 */
286f4b3ec61Sdh 	ifs->ifs_nat_tqb[IPF_TCPS_CLOSED].ifq_ttl =
287f4b3ec61Sdh 	    ifs->ifs_nat_tqb[IPF_TCPS_LAST_ACK].ifq_ttl;
2887c478bd9Sstevel@tonic-gate 
289f4b3ec61Sdh 	RWLOCK_INIT(&ifs->ifs_ipf_nat, "ipf IP NAT rwlock");
290f4b3ec61Sdh 	RWLOCK_INIT(&ifs->ifs_ipf_natfrag, "ipf IP NAT-Frag rwlock");
291f4b3ec61Sdh 	MUTEX_INIT(&ifs->ifs_ipf_nat_new, "ipf nat new mutex");
292f4b3ec61Sdh 	MUTEX_INIT(&ifs->ifs_ipf_natio, "ipf nat io mutex");
2937c478bd9Sstevel@tonic-gate 
294f4b3ec61Sdh 	ifs->ifs_fr_nat_init = 1;
295ea8244dcSJohn Ojemann 	ifs->ifs_nat_last_force_flush = ifs->ifs_fr_ticks;
2967c478bd9Sstevel@tonic-gate 	return 0;
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3017c478bd9Sstevel@tonic-gate /* Function:    nat_addrdr                                                  */
3027c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
3037c478bd9Sstevel@tonic-gate /* Parameters:  n(I) - pointer to NAT rule to add                           */
3047c478bd9Sstevel@tonic-gate /*                                                                          */
3057c478bd9Sstevel@tonic-gate /* Adds a redirect rule to the hash table of redirect rules and the list of */
3067c478bd9Sstevel@tonic-gate /* loaded NAT rules.  Updates the bitmask indicating which netmasks are in  */
3077c478bd9Sstevel@tonic-gate /* use by redirect rules.                                                   */
3087c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
nat_addrdr(n,ifs)309f4b3ec61Sdh static void nat_addrdr(n, ifs)
3107c478bd9Sstevel@tonic-gate ipnat_t *n;
311f4b3ec61Sdh ipf_stack_t *ifs;
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 	ipnat_t **np;
3147c478bd9Sstevel@tonic-gate 	u_32_t j;
3157c478bd9Sstevel@tonic-gate 	u_int hv;
3167c478bd9Sstevel@tonic-gate 	int k;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	k = count4bits(n->in_outmsk);
3197c478bd9Sstevel@tonic-gate 	if ((k >= 0) && (k != 32))
320f4b3ec61Sdh 		ifs->ifs_rdr_masks |= 1 << k;
3217c478bd9Sstevel@tonic-gate 	j = (n->in_outip & n->in_outmsk);
322f4b3ec61Sdh 	hv = NAT_HASH_FN(j, 0, ifs->ifs_ipf_rdrrules_sz);
323f4b3ec61Sdh 	np = ifs->ifs_rdr_rules + hv;
3247c478bd9Sstevel@tonic-gate 	while (*np != NULL)
3257c478bd9Sstevel@tonic-gate 		np = &(*np)->in_rnext;
3267c478bd9Sstevel@tonic-gate 	n->in_rnext = NULL;
3277c478bd9Sstevel@tonic-gate 	n->in_prnext = np;
328ab25eeb5Syz 	n->in_hv = hv;
3297c478bd9Sstevel@tonic-gate 	*np = n;
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3347c478bd9Sstevel@tonic-gate /* Function:    nat_addnat                                                  */
3357c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
3367c478bd9Sstevel@tonic-gate /* Parameters:  n(I) - pointer to NAT rule to add                           */
3377c478bd9Sstevel@tonic-gate /*                                                                          */
3387c478bd9Sstevel@tonic-gate /* Adds a NAT map rule to the hash table of rules and the list of  loaded   */
3397c478bd9Sstevel@tonic-gate /* NAT rules.  Updates the bitmask indicating which netmasks are in use by  */
3407c478bd9Sstevel@tonic-gate /* redirect rules.                                                          */
3417c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
nat_addnat(n,ifs)342f4b3ec61Sdh static void nat_addnat(n, ifs)
3437c478bd9Sstevel@tonic-gate ipnat_t *n;
344f4b3ec61Sdh ipf_stack_t *ifs;
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 	ipnat_t **np;
3477c478bd9Sstevel@tonic-gate 	u_32_t j;
3487c478bd9Sstevel@tonic-gate 	u_int hv;
3497c478bd9Sstevel@tonic-gate 	int k;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	k = count4bits(n->in_inmsk);
3527c478bd9Sstevel@tonic-gate 	if ((k >= 0) && (k != 32))
353f4b3ec61Sdh 		ifs->ifs_nat_masks |= 1 << k;
3547c478bd9Sstevel@tonic-gate 	j = (n->in_inip & n->in_inmsk);
355f4b3ec61Sdh 	hv = NAT_HASH_FN(j, 0, ifs->ifs_ipf_natrules_sz);
356f4b3ec61Sdh 	np = ifs->ifs_nat_rules + hv;
3577c478bd9Sstevel@tonic-gate 	while (*np != NULL)
3587c478bd9Sstevel@tonic-gate 		np = &(*np)->in_mnext;
3597c478bd9Sstevel@tonic-gate 	n->in_mnext = NULL;
3607c478bd9Sstevel@tonic-gate 	n->in_pmnext = np;
361ab25eeb5Syz 	n->in_hv = hv;
3627c478bd9Sstevel@tonic-gate 	*np = n;
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3677c478bd9Sstevel@tonic-gate /* Function:    nat_delrdr                                                  */
3687c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
3697c478bd9Sstevel@tonic-gate /* Parameters:  n(I) - pointer to NAT rule to delete                        */
3707c478bd9Sstevel@tonic-gate /*                                                                          */
3717c478bd9Sstevel@tonic-gate /* Removes a redirect rule from the hash table of redirect rules.           */
3727c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
nat_delrdr(n)373d6c23f6fSyx void nat_delrdr(n)
3747c478bd9Sstevel@tonic-gate ipnat_t *n;
3757c478bd9Sstevel@tonic-gate {
3767c478bd9Sstevel@tonic-gate 	if (n->in_rnext)
3777c478bd9Sstevel@tonic-gate 		n->in_rnext->in_prnext = n->in_prnext;
3787c478bd9Sstevel@tonic-gate 	*n->in_prnext = n->in_rnext;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3837c478bd9Sstevel@tonic-gate /* Function:    nat_delnat                                                  */
3847c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
3857c478bd9Sstevel@tonic-gate /* Parameters:  n(I) - pointer to NAT rule to delete                        */
3867c478bd9Sstevel@tonic-gate /*                                                                          */
3877c478bd9Sstevel@tonic-gate /* Removes a NAT map rule from the hash table of NAT map rules.             */
3887c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
nat_delnat(n)389d6c23f6fSyx void nat_delnat(n)
3907c478bd9Sstevel@tonic-gate ipnat_t *n;
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate 	if (n->in_mnext != NULL)
3937c478bd9Sstevel@tonic-gate 		n->in_mnext->in_pmnext = n->in_pmnext;
3947c478bd9Sstevel@tonic-gate 	*n->in_pmnext = n->in_mnext;
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3997c478bd9Sstevel@tonic-gate /* Function:    nat_hostmap                                                 */
4007c478bd9Sstevel@tonic-gate /* Returns:     struct hostmap* - NULL if no hostmap could be created,      */
4017c478bd9Sstevel@tonic-gate /*                                else a pointer to the hostmapping to use  */
4027c478bd9Sstevel@tonic-gate /* Parameters:  np(I)   - pointer to NAT rule                               */
4037c478bd9Sstevel@tonic-gate /*              real(I) - real IP address                                   */
4047c478bd9Sstevel@tonic-gate /*              map(I)  - mapped IP address                                 */
4057c478bd9Sstevel@tonic-gate /*              port(I) - destination port number                           */
4067c478bd9Sstevel@tonic-gate /* Write Locks: ipf_nat                                                     */
4077c478bd9Sstevel@tonic-gate /*                                                                          */
4087c478bd9Sstevel@tonic-gate /* Check if an ip address has already been allocated for a given mapping    */
4097c478bd9Sstevel@tonic-gate /* that is not doing port based translation.  If is not yet allocated, then */
410ab25eeb5Syz /* create a new entry if a non-NULL NAT rule pointer has been supplied.     */
4117c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
nat_hostmap(np,src,dst,map,port,ifs)412f4b3ec61Sdh static struct hostmap *nat_hostmap(np, src, dst, map, port, ifs)
4137c478bd9Sstevel@tonic-gate ipnat_t *np;
4147c478bd9Sstevel@tonic-gate struct in_addr src;
4157c478bd9Sstevel@tonic-gate struct in_addr dst;
4167c478bd9Sstevel@tonic-gate struct in_addr map;
4177c478bd9Sstevel@tonic-gate u_32_t port;
418f4b3ec61Sdh ipf_stack_t *ifs;
4197c478bd9Sstevel@tonic-gate {
4207c478bd9Sstevel@tonic-gate 	hostmap_t *hm;
4217c478bd9Sstevel@tonic-gate 	u_int hv;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	hv = (src.s_addr ^ dst.s_addr);
4247c478bd9Sstevel@tonic-gate 	hv += src.s_addr;
4257c478bd9Sstevel@tonic-gate 	hv += dst.s_addr;
4267c478bd9Sstevel@tonic-gate 	hv %= HOSTMAP_SIZE;
427f4b3ec61Sdh 	for (hm = ifs->ifs_maptable[hv]; hm; hm = hm->hm_next)
4287c478bd9Sstevel@tonic-gate 		if ((hm->hm_srcip.s_addr == src.s_addr) &&
4297c478bd9Sstevel@tonic-gate 		    (hm->hm_dstip.s_addr == dst.s_addr) &&
4307c478bd9Sstevel@tonic-gate 		    ((np == NULL) || (np == hm->hm_ipnat)) &&
4317c478bd9Sstevel@tonic-gate 		    ((port == 0) || (port == hm->hm_port))) {
4327c478bd9Sstevel@tonic-gate 			hm->hm_ref++;
4337c478bd9Sstevel@tonic-gate 			return hm;
4347c478bd9Sstevel@tonic-gate 		}
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	if (np == NULL)
4377c478bd9Sstevel@tonic-gate 		return NULL;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	KMALLOC(hm, hostmap_t *);
4407c478bd9Sstevel@tonic-gate 	if (hm) {
441f4b3ec61Sdh 		hm->hm_hnext = ifs->ifs_ipf_hm_maplist;
442f4b3ec61Sdh 		hm->hm_phnext = &ifs->ifs_ipf_hm_maplist;
443f4b3ec61Sdh 		if (ifs->ifs_ipf_hm_maplist != NULL)
444f4b3ec61Sdh 			ifs->ifs_ipf_hm_maplist->hm_phnext = &hm->hm_hnext;
445f4b3ec61Sdh 		ifs->ifs_ipf_hm_maplist = hm;
446f4b3ec61Sdh 
447f4b3ec61Sdh 		hm->hm_next = ifs->ifs_maptable[hv];
448f4b3ec61Sdh 		hm->hm_pnext = ifs->ifs_maptable + hv;
449f4b3ec61Sdh 		if (ifs->ifs_maptable[hv] != NULL)
450f4b3ec61Sdh 			ifs->ifs_maptable[hv]->hm_pnext = &hm->hm_next;
451f4b3ec61Sdh 		ifs->ifs_maptable[hv] = hm;
4527c478bd9Sstevel@tonic-gate 		hm->hm_ipnat = np;
4537c478bd9Sstevel@tonic-gate 		hm->hm_srcip = src;
4547c478bd9Sstevel@tonic-gate 		hm->hm_dstip = dst;
4557c478bd9Sstevel@tonic-gate 		hm->hm_mapip = map;
4567c478bd9Sstevel@tonic-gate 		hm->hm_ref = 1;
4577c478bd9Sstevel@tonic-gate 		hm->hm_port = port;
458d6c23f6fSyx 		hm->hm_v = 4;
4597c478bd9Sstevel@tonic-gate 	}
4607c478bd9Sstevel@tonic-gate 	return hm;
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
46590b0a856Sjojemann /* Function:    fr_hostmapdel                                              */
4667c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
46790b0a856Sjojemann /* Parameters:  hmp(I) - pointer to pointer to hostmap structure            */
4687c478bd9Sstevel@tonic-gate /* Write Locks: ipf_nat                                                     */
4697c478bd9Sstevel@tonic-gate /*                                                                          */
4707c478bd9Sstevel@tonic-gate /* Decrement the references to this hostmap structure by one.  If this      */
4717c478bd9Sstevel@tonic-gate /* reaches zero then remove it and free it.                                 */
4727c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_hostmapdel(hmp)47390b0a856Sjojemann void fr_hostmapdel(hmp)
47490b0a856Sjojemann struct hostmap **hmp;
4757c478bd9Sstevel@tonic-gate {
47690b0a856Sjojemann 	struct hostmap *hm;
47790b0a856Sjojemann 
47890b0a856Sjojemann 	hm = *hmp;
47990b0a856Sjojemann 	*hmp = NULL;
48090b0a856Sjojemann 
4817c478bd9Sstevel@tonic-gate 	hm->hm_ref--;
4827c478bd9Sstevel@tonic-gate 	if (hm->hm_ref == 0) {
4837c478bd9Sstevel@tonic-gate 		if (hm->hm_next)
4847c478bd9Sstevel@tonic-gate 			hm->hm_next->hm_pnext = hm->hm_pnext;
4857c478bd9Sstevel@tonic-gate 		*hm->hm_pnext = hm->hm_next;
486f4b3ec61Sdh 		if (hm->hm_hnext)
487f4b3ec61Sdh 			hm->hm_hnext->hm_phnext = hm->hm_phnext;
488f4b3ec61Sdh 		*hm->hm_phnext = hm->hm_hnext;
4897c478bd9Sstevel@tonic-gate 		KFREE(hm);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4957c478bd9Sstevel@tonic-gate /* Function:    fix_outcksum                                                */
4967c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
497381a2a9aSdr /* Parameters:  sp(I)  - location of 16bit checksum to update               */
4987c478bd9Sstevel@tonic-gate /*              n((I)  - amount to adjust checksum by                       */
4997c478bd9Sstevel@tonic-gate /*                                                                          */
5007c478bd9Sstevel@tonic-gate /* Adjusts the 16bit checksum by "n" for packets going out.                 */
5017c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fix_outcksum(sp,n)502381a2a9aSdr void fix_outcksum(sp, n)
5037c478bd9Sstevel@tonic-gate u_short *sp;
5047c478bd9Sstevel@tonic-gate u_32_t n;
5057c478bd9Sstevel@tonic-gate {
5067c478bd9Sstevel@tonic-gate 	u_short sumshort;
5077c478bd9Sstevel@tonic-gate 	u_32_t sum1;
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	if (n == 0)
5107c478bd9Sstevel@tonic-gate 		return;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	sum1 = (~ntohs(*sp)) & 0xffff;
5137c478bd9Sstevel@tonic-gate 	sum1 += (n);
5147c478bd9Sstevel@tonic-gate 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
5157c478bd9Sstevel@tonic-gate 	/* Again */
5167c478bd9Sstevel@tonic-gate 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
5177c478bd9Sstevel@tonic-gate 	sumshort = ~(u_short)sum1;
5187c478bd9Sstevel@tonic-gate 	*(sp) = htons(sumshort);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5237c478bd9Sstevel@tonic-gate /* Function:    fix_incksum                                                 */
5247c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
525381a2a9aSdr /* Parameters:  sp(I)  - location of 16bit checksum to update               */
5267c478bd9Sstevel@tonic-gate /*              n((I)  - amount to adjust checksum by                       */
5277c478bd9Sstevel@tonic-gate /*                                                                          */
5287c478bd9Sstevel@tonic-gate /* Adjusts the 16bit checksum by "n" for packets going in.                  */
5297c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fix_incksum(sp,n)530381a2a9aSdr void fix_incksum(sp, n)
5317c478bd9Sstevel@tonic-gate u_short *sp;
5327c478bd9Sstevel@tonic-gate u_32_t n;
5337c478bd9Sstevel@tonic-gate {
5347c478bd9Sstevel@tonic-gate 	u_short sumshort;
5357c478bd9Sstevel@tonic-gate 	u_32_t sum1;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (n == 0)
5387c478bd9Sstevel@tonic-gate 		return;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	sum1 = (~ntohs(*sp)) & 0xffff;
5417c478bd9Sstevel@tonic-gate 	sum1 += ~(n) & 0xffff;
5427c478bd9Sstevel@tonic-gate 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
5437c478bd9Sstevel@tonic-gate 	/* Again */
5447c478bd9Sstevel@tonic-gate 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
5457c478bd9Sstevel@tonic-gate 	sumshort = ~(u_short)sum1;
5467c478bd9Sstevel@tonic-gate 	*(sp) = htons(sumshort);
5477c478bd9Sstevel@tonic-gate }
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5517c478bd9Sstevel@tonic-gate /* Function:    fix_datacksum                                               */
5527c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
5537c478bd9Sstevel@tonic-gate /* Parameters:  sp(I)  - location of 16bit checksum to update               */
5547c478bd9Sstevel@tonic-gate /*              n((I)  - amount to adjust checksum by                       */
5557c478bd9Sstevel@tonic-gate /*                                                                          */
5567c478bd9Sstevel@tonic-gate /* Fix_datacksum is used *only* for the adjustments of checksums in the     */
5577c478bd9Sstevel@tonic-gate /* data section of an IP packet.                                            */
5587c478bd9Sstevel@tonic-gate /*                                                                          */
5597c478bd9Sstevel@tonic-gate /* The only situation in which you need to do this is when NAT'ing an       */
5607c478bd9Sstevel@tonic-gate /* ICMP error message. Such a message, contains in its body the IP header   */
5617c478bd9Sstevel@tonic-gate /* of the original IP packet, that causes the error.                        */
5627c478bd9Sstevel@tonic-gate /*                                                                          */
5637c478bd9Sstevel@tonic-gate /* You can't use fix_incksum or fix_outcksum in that case, because for the  */
5647c478bd9Sstevel@tonic-gate /* kernel the data section of the ICMP error is just data, and no special   */
5657c478bd9Sstevel@tonic-gate /* processing like hardware cksum or ntohs processing have been done by the */
5667c478bd9Sstevel@tonic-gate /* kernel on the data section.                                              */
5677c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fix_datacksum(sp,n)5687c478bd9Sstevel@tonic-gate void fix_datacksum(sp, n)
5697c478bd9Sstevel@tonic-gate u_short *sp;
5707c478bd9Sstevel@tonic-gate u_32_t n;
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 	u_short sumshort;
5737c478bd9Sstevel@tonic-gate 	u_32_t sum1;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	if (n == 0)
5767c478bd9Sstevel@tonic-gate 		return;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	sum1 = (~ntohs(*sp)) & 0xffff;
5797c478bd9Sstevel@tonic-gate 	sum1 += (n);
5807c478bd9Sstevel@tonic-gate 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
5817c478bd9Sstevel@tonic-gate 	/* Again */
5827c478bd9Sstevel@tonic-gate 	sum1 = (sum1 >> 16) + (sum1 & 0xffff);
5837c478bd9Sstevel@tonic-gate 	sumshort = ~(u_short)sum1;
5847c478bd9Sstevel@tonic-gate 	*(sp) = htons(sumshort);
5857c478bd9Sstevel@tonic-gate }
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5897c478bd9Sstevel@tonic-gate /* Function:    fr_nat_ioctl                                                */
5907c478bd9Sstevel@tonic-gate /* Returns:     int - 0 == success, != 0 == failure                         */
5917c478bd9Sstevel@tonic-gate /* Parameters:  data(I) - pointer to ioctl data                             */
5927c478bd9Sstevel@tonic-gate /*              cmd(I)  - ioctl command integer                             */
5937c478bd9Sstevel@tonic-gate /*              mode(I) - file mode bits used with open                     */
594ea8244dcSJohn Ojemann /*              uid(I)  - uid of caller                                     */
595ea8244dcSJohn Ojemann /*              ctx(I)  - pointer to give the uid context                   */
596ea8244dcSJohn Ojemann /*              ifs     - ipf stack instance                                */
5977c478bd9Sstevel@tonic-gate /*                                                                          */
5987c478bd9Sstevel@tonic-gate /* Processes an ioctl call made to operate on the IP Filter NAT device.     */
5997c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_nat_ioctl(data,cmd,mode,uid,ctx,ifs)600f4b3ec61Sdh int fr_nat_ioctl(data, cmd, mode, uid, ctx, ifs)
601ab25eeb5Syz ioctlcmd_t cmd;
6027c478bd9Sstevel@tonic-gate caddr_t data;
603f4b3ec61Sdh int mode, uid;
604f4b3ec61Sdh void *ctx;
605f4b3ec61Sdh ipf_stack_t *ifs;
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate 	ipnat_t *nat, *nt, *n = NULL, **np = NULL;
6087c478bd9Sstevel@tonic-gate 	int error = 0, ret, arg, getlock;
6097c478bd9Sstevel@tonic-gate 	ipnat_t natd;
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate #if (BSD >= 199306) && defined(_KERNEL)
6127c478bd9Sstevel@tonic-gate 	if ((securelevel >= 2) && (mode & FWRITE))
6137c478bd9Sstevel@tonic-gate 		return EPERM;
6147c478bd9Sstevel@tonic-gate #endif
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate #if defined(__osf__) && defined(_KERNEL)
6177c478bd9Sstevel@tonic-gate 	getlock = 0;
6187c478bd9Sstevel@tonic-gate #else
6197c478bd9Sstevel@tonic-gate 	getlock = (mode & NAT_LOCKHELD) ? 0 : 1;
6207c478bd9Sstevel@tonic-gate #endif
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	nat = NULL;     /* XXX gcc -Wuninitialized */
623ab25eeb5Syz 	if (cmd == (ioctlcmd_t)SIOCADNAT) {
6247c478bd9Sstevel@tonic-gate 		KMALLOC(nt, ipnat_t *);
6257c478bd9Sstevel@tonic-gate 	} else {
6267c478bd9Sstevel@tonic-gate 		nt = NULL;
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate 
629