diff -druN src/ip_stack.h src/ip_stack.h
--- src/ip_stack.h	1970-01-01 01:00:00.000000000 +0100
+++ src/ip_stack.h	2007-11-21 10:37:32.054244000 +0100
@@ -0,0 +1,441 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_INET_IP_STACK_H
+#define	_INET_IP_STACK_H
+
+#pragma ident	"@(#)ip_stack.h	1.7	07/09/25 SMI"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#include <sys/isa_defs.h>
+#include <sys/md5.h>
+#include <sys/types.h>
+#include <inet/nd.h>
+#include <sys/atomic.h>
+#include <sys/socket.h>
+#include "netstack.h"
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <netinet/ip.h>
+#include <netinet/igmp_var.h>
+#include <inet/ip.h>
+#include <sys/taskq.h>
+
+#ifdef _KERNEL
+#include <netinet/ip6.h>
+#include <sys/avl.h>
+#include <sys/vmem.h>
+#include <sys/squeue.h>
+#endif	/* _KERNEL */
+
+#ifdef _KERNEL
+
+
+/*
+ * IP statistics.
+ */
+#define	IP_STAT(ipst, x)	((ipst)->ips_ip_statistics.x.value.ui64++)
+#define	IP_STAT_UPDATE(ipst, x, n) \
+		((ipst)->ips_ip_statistics.x.value.ui64 += (n))
+
+/*
+ * Named statistics.
+ *
+ * List of arbitrary name=value statistics.
+ */
+
+#if 0
+typedef struct kstat_named {
+	char	name[KSTAT_STRLEN];	/* name of counter */
+	uchar_t	data_type;		/* data type */
+	union {
+		char		c[16];	/* enough for 128-bit ints */
+		int32_t		i32;
+		uint32_t	ui32;
+		struct {
+			union {
+				char 		*ptr;	/* NULL-term string */
+#if defined(_KERNEL) && defined(_MULTI_DATAMODEL)
+				caddr32_t	ptr32;
+#endif
+				char 		__pad[8]; /* 64-bit padding */
+			} addr;
+			uint32_t	len;	/* # bytes for strlen + '\0' */
+		} str;
+/*
+ * The int64_t and uint64_t types are not valid for a maximally conformant
+ * 32-bit compilation environment (cc -Xc) using compilers prior to the
+ * introduction of C99 conforming compiler (reference ISO/IEC 9899:1990).
+ * In these cases, the visibility of i64 and ui64 is only permitted for
+ * 64-bit compilation environments or 32-bit non-maximally conformant
+ * C89 or C90 ANSI C compilation environments (cc -Xt and cc -Xa). In the
+ * C99 ANSI C compilation environment, the long long type is supported.
+ * The _INT64_TYPE is defined by the implementation (see sys/int_types.h).
+ */
+#if defined(_INT64_TYPE)
+		int64_t		i64;
+		uint64_t	ui64;
+#endif
+		long		l;
+		ulong_t		ul;
+
+		/* These structure members are obsolete */
+
+		longlong_t	ll;
+		u_longlong_t	ull;
+		float		f;
+		double		d;
+	} value;			/* value of counter */
+} kstat_named_t;
+#endif
+
+   
+typedef struct ip_stat {
+	kstat_named_t	ipsec_fanout_proto;
+	kstat_named_t	ip_udp_fannorm;
+	kstat_named_t	ip_udp_fanmb;
+	kstat_named_t	ip_udp_fanothers;
+	kstat_named_t	ip_udp_fast_path;
+	kstat_named_t	ip_udp_slow_path;
+	kstat_named_t	ip_udp_input_err;
+	kstat_named_t	ip_tcppullup;
+	kstat_named_t	ip_tcpoptions;
+	kstat_named_t	ip_multipkttcp;
+	kstat_named_t	ip_tcp_fast_path;
+	kstat_named_t	ip_tcp_slow_path;
+	kstat_named_t	ip_tcp_input_error;
+	kstat_named_t	ip_db_ref;
+	kstat_named_t	ip_notaligned1;
+	kstat_named_t	ip_notaligned2;
+	kstat_named_t	ip_multimblk3;
+	kstat_named_t	ip_multimblk4;
+	kstat_named_t	ip_ipoptions;
+	kstat_named_t	ip_classify_fail;
+	kstat_named_t	ip_opt;
+	kstat_named_t	ip_udp_rput_local;
+	kstat_named_t	ipsec_proto_ahesp;
+	kstat_named_t	ip_conn_flputbq;
+	kstat_named_t	ip_conn_walk_drain;
+	kstat_named_t   ip_out_sw_cksum;
+	kstat_named_t   ip_in_sw_cksum;
+	kstat_named_t   ip_trash_ire_reclaim_calls;
+	kstat_named_t   ip_trash_ire_reclaim_success;
+	kstat_named_t   ip_ire_arp_timer_expired;
+	kstat_named_t   ip_ire_redirect_timer_expired;
+	kstat_named_t	ip_ire_pmtu_timer_expired;
+	kstat_named_t	ip_input_multi_squeue;
+	kstat_named_t	ip_tcp_in_full_hw_cksum_err;
+	kstat_named_t	ip_tcp_in_part_hw_cksum_err;
+	kstat_named_t	ip_tcp_in_sw_cksum_err;
+	kstat_named_t	ip_tcp_out_sw_cksum_bytes;
+	kstat_named_t	ip_udp_in_full_hw_cksum_err;
+	kstat_named_t	ip_udp_in_part_hw_cksum_err;
+	kstat_named_t	ip_udp_in_sw_cksum_err;
+	kstat_named_t	ip_udp_out_sw_cksum_bytes;
+	kstat_named_t	ip_frag_mdt_pkt_out;
+	kstat_named_t	ip_frag_mdt_discarded;
+	kstat_named_t	ip_frag_mdt_allocfail;
+	kstat_named_t	ip_frag_mdt_addpdescfail;
+	kstat_named_t	ip_frag_mdt_allocd;
+} ip_stat_t;
+
+
+/*
+ * IP6 statistics.
+ */
+#define	IP6_STAT(ipst, x)	((ipst)->ips_ip6_statistics.x.value.ui64++)
+#define	IP6_STAT_UPDATE(ipst, x, n)	\
+	((ipst)->ips_ip6_statistics.x.value.ui64 += (n))
+
+typedef struct ip6_stat {
+	kstat_named_t	ip6_udp_fast_path;
+	kstat_named_t	ip6_udp_slow_path;
+	kstat_named_t	ip6_udp_fannorm;
+	kstat_named_t	ip6_udp_fanmb;
+	kstat_named_t   ip6_out_sw_cksum;
+	kstat_named_t   ip6_in_sw_cksum;
+	kstat_named_t	ip6_tcp_in_full_hw_cksum_err;
+	kstat_named_t	ip6_tcp_in_part_hw_cksum_err;
+	kstat_named_t	ip6_tcp_in_sw_cksum_err;
+	kstat_named_t	ip6_tcp_out_sw_cksum_bytes;
+	kstat_named_t	ip6_udp_in_full_hw_cksum_err;
+	kstat_named_t	ip6_udp_in_part_hw_cksum_err;
+	kstat_named_t	ip6_udp_in_sw_cksum_err;
+	kstat_named_t	ip6_udp_out_sw_cksum_bytes;
+	kstat_named_t	ip6_frag_mdt_pkt_out;
+	kstat_named_t	ip6_frag_mdt_discarded;
+	kstat_named_t	ip6_frag_mdt_allocfail;
+	kstat_named_t	ip6_frag_mdt_addpdescfail;
+	kstat_named_t	ip6_frag_mdt_allocd;
+} ip6_stat_t;
+
+typedef struct ire_stats {
+	uint64_t ire_stats_alloced;	/* # of ires alloced */
+	uint64_t ire_stats_freed;	/* # of ires freed */
+	uint64_t ire_stats_inserted;	/* # of ires inserted in the bucket */
+	uint64_t ire_stats_deleted;	/* # of ires deleted from the bucket */
+} ire_stats_t;
+
+typedef struct mib2_ipIfStatsEntry {
+
+	/* Local ifindex to identify the interface */
+	DeviceIndex	ipIfStatsIfIndex;
+
+	/* forwarder?  1 gateway, 2 NOT gateway	{ ipv6MIBObjects 1} RW */
+	int	ipIfStatsForwarding;
+	/* default Hoplimit for IPv6		{ ipv6MIBObjects 2} RW */
+	int	ipIfStatsDefaultHopLimit;
+#define	ipIfStatsDefaultTTL	ipIfStatsDefaultHopLimit
+
+	int	ipIfStatsEntrySize;
+	int	ipIfStatsAddrEntrySize;
+	int	ipIfStatsRouteEntrySize;
+	int	ipIfStatsNetToMediaEntrySize;
+	int	ipIfStatsMemberEntrySize;
+	int	ipIfStatsGroupSourceEntrySize;
+
+	/* # input datagrams (incl errors)	{ ipIfStatsEntry 3 } */
+	Counter	ipIfStatsInReceives;
+	/* # errors in IP headers and options	{ ipIfStatsEntry 7 } */
+	Counter	ipIfStatsInHdrErrors;
+	/* # exceeds outgoing link MTU(v6 only)	{ ipv6IfStatsEntry 3 } */
+	Counter	ipIfStatsInTooBigErrors;
+	/* # discarded due to no route to dest 	{ ipIfStatsEntry 8 } */
+	Counter	ipIfStatsInNoRoutes;
+	/* # invalid or unsupported addresses	{ ipIfStatsEntry 9 } */
+	Counter	ipIfStatsInAddrErrors;
+	/* # unknown next header 		{ ipIfStatsEntry 10 } */
+	Counter	ipIfStatsInUnknownProtos;
+	/* # too short packets			{ ipIfStatsEntry 11 } */
+	Counter	ipIfStatsInTruncatedPkts;
+	/* # discarded e.g. due to no buffers	{ ipIfStatsEntry 17 } */
+	Counter	ipIfStatsInDiscards;
+	/* # delivered to upper layer protocols	{ ipIfStatsEntry 18 } */
+	Counter	ipIfStatsInDelivers;
+	/* # forwarded out interface		{ ipIfStatsEntry 23 } */
+	Counter	ipIfStatsOutForwDatagrams;
+	/* # originated out interface		{ ipIfStatsEntry 20 } */
+	Counter	ipIfStatsOutRequests;
+	/* # discarded e.g. due to no buffers	{ ipIfStatsEntry 25 } */
+	Counter	ipIfStatsOutDiscards;
+	/* # sucessfully fragmented packets	{ ipIfStatsEntry 27 } */
+	Counter	ipIfStatsOutFragOKs;
+	/* # fragmentation failed		{ ipIfStatsEntry 28 } */
+	Counter	ipIfStatsOutFragFails;
+	/* # fragments created			{ ipIfStatsEntry 29 } */
+	Counter	ipIfStatsOutFragCreates;
+	/* # fragments to reassemble		{ ipIfStatsEntry 14 } */
+	Counter	ipIfStatsReasmReqds;
+	/* # packets after reassembly		{ ipIfStatsEntry 15 } */
+	Counter	ipIfStatsReasmOKs;
+	/* # reassembly failed			{ ipIfStatsEntry 16 } */
+	Counter	ipIfStatsReasmFails;
+	/* # received multicast packets		{ ipIfStatsEntry 34 } */
+	Counter	ipIfStatsInMcastPkts;
+	/* # transmitted multicast packets	{ ipIfStatsEntry 38 } */
+	Counter	ipIfStatsOutMcastPkts;
+
+	/*
+	 * In addition to defined MIBs
+	 */
+
+	/* # discarded due to no route to dest 	{ ipSystemStatsEntry 22 } */
+	Counter	ipIfStatsOutNoRoutes;
+	/* # of complete duplicates in reassembly */
+	Counter	ipIfStatsReasmDuplicates;
+	/* # of partial duplicates in reassembly */
+	Counter	ipIfStatsReasmPartDups;
+	/* # of packets not forwarded due to adminstrative reasons */
+	Counter	ipIfStatsForwProhibits;
+	/* # of UDP packets with bad UDP checksums */
+	Counter udpInCksumErrs;
+#define	udpIfStatsInCksumErrs	udpInCksumErrs
+	/* # of UDP packets droped due to queue overflow */
+	Counter udpInOverflows;
+#define	udpIfStatsInOverflows	udpInOverflows
+	/*
+	 * # of RAW IP packets (all IP protocols except UDP, TCP
+	 * and ICMP) droped due to queue overflow
+	 */
+	Counter rawipInOverflows;
+#define	rawipIfStatsInOverflows	rawipInOverflows
+
+	/*
+	 * # of IP packets received with the wrong version (i.e., not equal
+	 * to ipIfStatsIPVersion) and that were dropped.
+	 */
+	Counter ipIfStatsInWrongIPVersion;
+	/*
+	 * Depending on the value of ipIfStatsIPVersion, this counter tracks
+	 * v4: # of IPv6 packets transmitted by ip_wput or,
+	 * v6: # of IPv4 packets transmitted by ip_wput_v6.
+	 */
+	Counter ipIfStatsOutWrongIPVersion;
+	/*
+	 * Depending on the value of ipIfStatsIPVersion, this counter tracks
+	 * # of times ip_wput has switched to become ip_wput_v6, or vice versa.
+	 */
+	Counter ipIfStatsOutSwitchIPVersion;
+
+	/*
+	 * Fields defined in RFC 4293
+	 */
+
+	/* ip version				{ ipIfStatsEntry 1 } */
+	int		ipIfStatsIPVersion;
+	/* # input datagrams (incl errors)	{ ipIfStatsEntry 4 } */
+	Counter64	ipIfStatsHCInReceives;
+	/* # input octets (incl errors)		{ ipIfStatsEntry 6 } */
+	Counter64	ipIfStatsHCInOctets;
+	/*
+	 *					{ ipIfStatsEntry 13 }
+	 * # input datagrams for which a forwarding attempt was made
+	 */
+	Counter64	ipIfStatsHCInForwDatagrams;
+	/* # delivered to upper layer protocols	{ ipIfStatsEntry 19 } */
+	Counter64	ipIfStatsHCInDelivers;
+	/* # originated out interface		{ ipIfStatsEntry 21 } */
+	Counter64	ipIfStatsHCOutRequests;
+	/* # forwarded out interface		{ ipIfStatsEntry 23 } */
+	Counter64	ipIfStatsHCOutForwDatagrams;
+	/* # dg's requiring fragmentation 	{ ipIfStatsEntry 26 } */
+	Counter		ipIfStatsOutFragReqds;
+	/* # output datagrams			{ ipIfStatsEntry 31 } */
+	Counter64	ipIfStatsHCOutTransmits;
+	/* # output octets			{ ipIfStatsEntry 33 } */
+	Counter64	ipIfStatsHCOutOctets;
+	/* # received multicast datagrams	{ ipIfStatsEntry 35 } */
+	Counter64	ipIfStatsHCInMcastPkts;
+	/* # received multicast octets		{ ipIfStatsEntry 37 } */
+	Counter64	ipIfStatsHCInMcastOctets;
+	/* # transmitted multicast datagrams	{ ipIfStatsEntry 39 } */
+	Counter64	ipIfStatsHCOutMcastPkts;
+	/* # transmitted multicast octets	{ ipIfStatsEntry 41 } */
+	Counter64	ipIfStatsHCOutMcastOctets;
+	/* # received broadcast datagrams	{ ipIfStatsEntry 43 } */
+	Counter64	ipIfStatsHCInBcastPkts;
+	/* # transmitted broadcast datagrams	{ ipIfStatsEntry 45 } */
+	Counter64	ipIfStatsHCOutBcastPkts;
+
+	/*
+	 * Fields defined in mib2_ip_t
+	 */
+
+	/* # of incoming packets that succeeded policy checks */
+	Counter		ipsecInSucceeded;
+#define	ipsecIfStatsInSucceeded	ipsecInSucceeded
+	/* # of incoming packets that failed policy checks */
+	Counter		ipsecInFailed;
+#define	ipsecIfStatsInFailed	ipsecInFailed
+	/* # of bad IP header checksums */
+	Counter		ipInCksumErrs;
+#define	ipIfStatsInCksumErrs	ipInCksumErrs
+	/* total # of segments recv'd with error	{ tcp 14 } */
+	Counter		tcpInErrs;
+#define	tcpIfStatsInErrs	tcpInErrs
+	/* # of recv'd dg's not deliverable (no appl.)	{ udp 2 } */
+	Counter		udpNoPorts;
+#define	udpIfStatsNoPorts	udpNoPorts
+} mib2_ipIfStatsEntry_t;
+
+/*
+ * IP stack instances
+ */
+struct ip_stack {
+	netstack_t	*ips_netstack;	/* Common netstack */
+
+	struct ipparam_s	*ips_param_arr; 	/* ndd variable table */
+	void			*ips_ndp_arr;
+
+	mib2_ipIfStatsEntry_t	ips_ip_mib;	/* SNMP fixed size info */
+	mib2_icmp_t	ips_icmp_mib;
+	/*
+	 * IPv6 mibs when the interface (ill) is not known.
+	 * When the ill is known the per-interface mib in the ill is used.
+	 */
+	mib2_ipIfStatsEntry_t	ips_ip6_mib;
+	mib2_ipv6IfIcmpEntry_t	ips_icmp6_mib;
+
+	struct igmpstat		ips_igmpstat;
+
+	kstat_t		*ips_ip_mibkp;	/* kstat exporting ip_mib data */
+	kstat_t		*ips_icmp_mibkp; /* kstat exporting icmp_mib data */
+	kstat_t		*ips_ip_kstat;
+	ip_stat_t	ips_ip_statistics;
+	kstat_t		*ips_ip6_kstat;
+	ip6_stat_t	ips_ip6_statistics;
+
+/* ip.c */
+	krwlock_t	ips_ip_g_nd_lock;
+	kmutex_t	ips_igmp_timer_lock;
+	kmutex_t	ips_mld_timer_lock;
+	kmutex_t	ips_ip_mi_lock;
+	kmutex_t	ips_ip_addr_avail_lock;
+	krwlock_t	ips_ill_g_lock;
+	krwlock_t	ips_ipsec_capab_ills_lock;
+				/* protects the list of IPsec capable ills */
+	void	*ips_ipsec_capab_ills_ah;
+	void	*ips_ipsec_capab_ills_esp;
+
+	krwlock_t	ips_ill_g_usesrc_lock;
+
+	void	*ips_illgrp_head_v4;	/* Head of IPv4 ill groups */
+	void	*ips_illgrp_head_v6;	/* Head of IPv6 ill groups */
+
+/* ipclassifier.c - keep in ip_stack_t */
+	/* ipclassifier hash tables */
+	void	*ips_rts_clients;
+	void	*ips_ipcl_conn_fanout;
+	void	*ips_ipcl_bind_fanout;
+	void	*ips_ipcl_proto_fanout;
+	void	*ips_ipcl_proto_fanout_v6;
+	void	*ips_ipcl_udp_fanout;
+	void	*ips_ipcl_raw_fanout;
+	uint_t		ips_ipcl_conn_fanout_size;
+	uint_t		ips_ipcl_bind_fanout_size;
+	uint_t		ips_ipcl_udp_fanout_size;
+	uint_t		ips_ipcl_raw_fanout_size;
+	void	*ips_ipcl_globalhash_fanout;
+	int		ips_conn_g_index;
+};
+typedef struct ip_stack ip_stack_t;
+
+/* Finding an ip_stack_t */
+#define	CONNQ_TO_IPST(_q)	(Q_TO_CONN(_q)->conn_netstack->netstack_ip)
+#define	ILLQ_TO_IPST(_q)	(((ill_t *)(_q)->q_ptr)->ill_ipst)
+
+#else /* _KERNEL */
+typedef int ip_stack_t;
+#endif /* _KERNEL */
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _INET_IP_STACK_H */
diff -druN src/k_sunos510.c src/k_sunos510.c
--- src/k_sunos510.c	2005-10-18 11:22:04.000000000 +0200
+++ src/k_sunos510.c	2007-11-21 12:47:00.717975000 +0100
@@ -64,6 +64,9 @@
 #include <netinet/ip6.h>
 #include <net/if.h>
 
+#include "netstack.h"
+#include "ip_stack.h"
+
 uint_t   ipcl_conn_fanout_size;
 
 #if   !defined(IN6_V4_MAPPED_TO_INADDR)
@@ -154,7 +157,10 @@
 ka_open(void **misc)
 {
     struct kainfo *kp;
-
+    netstack_t netstack_head;
+    struct ip_stack ip_stack;
+    struct connf_s  *ipcl_conn_fanout;
+    netstack_t *netstack_head_ptr;
 
     kp = s_malloc(sizeof(*kp));
     
@@ -168,10 +174,8 @@
 	return -1;
     }
     
-    
-    kp->nl[0].n_name = "ipcl_conn_fanout";
-    kp->nl[1].n_name = "ipcl_conn_fanout_size";
-    kp->nl[2].n_name = NULL;
+    kp->nl[0].n_name = "netstack_head";
+    kp->nl[1].n_name = NULL;
     
     /*
     ** Extract offsets to the needed variables in the kernel
@@ -184,6 +188,39 @@
 	return -1;
     }
 
+    if (!getbuf(kp->kd, kp->nl[0].n_value, (char *) &netstack_head_ptr,
+	     sizeof(netstack_head_ptr), "netstack_head_ptr")) {
+       kvm_close(kp->kd);
+       s_free(kp);
+       syslog(LOG_ERR, "getbuf: can't get netstack_head_ptr");
+       return -1;
+    }
+
+    /* load netstack_head */
+    if (!getbuf(kp->kd, netstack_head_ptr, (char *) &netstack_head,
+	     sizeof(netstack_head), "netstack_head")) {
+       kvm_close(kp->kd);
+       s_free(kp);
+       syslog(LOG_ERR, "getbuf: can't get netstack_head ");
+       return -1;
+    }
+
+    /* get ip_stack */
+    if (!getbuf(kp->kd, netstack_head.netstack_ip, (char *) &ip_stack,
+	     sizeof(ip_stack), "ip_stack")) {
+       kvm_close(kp->kd);
+       s_free(kp);
+       syslog(LOG_ERR, "getbuf: can't get ip_stack");
+       return -1;
+    }
+    
+    kp->nl[0].n_name = "ipcl_conn_fanout";
+    kp->nl[0].n_value = (long) ip_stack.ips_ipcl_conn_fanout;
+    kp->nl[1].n_name = "ipcl_conn_fanout_size";
+    kp->nl[1].n_value = (long) ip_stack.ips_ipcl_conn_fanout_size;
+    kp->nl[2].n_name = NULL;
+
+#if 0
     /*
      * Read the two kernel values we need but won't change
      */
@@ -196,6 +233,9 @@
 	    syslog(LOG_ERR, "getbuf: can't get needed symbols");
 	    return -1;
     }
+#endif
+    kp->hash_size = ip_stack.ips_ipcl_conn_fanout_size;
+    kp->hash_table = ip_stack.ips_ipcl_conn_fanout;
 
     *misc = (void *) kp;
     return 0;
diff -druN src/netstack.h src/netstack.h
--- src/netstack.h	1970-01-01 01:00:00.000000000 +0100
+++ src/netstack.h	2007-11-21 09:59:05.237496000 +0100
@@ -0,0 +1,242 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _SYS_NETSTACK_H
+#define	_SYS_NETSTACK_H
+
+#pragma ident	"@(#)netstack.h	1.3	07/05/17 SMI"
+
+#include <sys/kstat.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * This allows various pieces in and around IP to have a separate instance
+ * for each instance of IP. This is used to support zones that have an
+ * exclusive stack.
+ * Pieces of software far removed from IP (e.g., kernel software
+ * sitting on top of TCP or UDP) probably should not use the netstack
+ * support; if such software wants to support separate zones it
+ * can do that using the zones framework (zone_key_create() etc)
+ * whether there is a shared IP stack or and exclusive IP stack underneath.
+ */
+
+/*
+ * Each netstack has an identifier. We reuse the zoneid allocation for
+ * this but have a separate typedef. Thus the shared stack (used by
+ * the global zone and other shared stack zones) have a zero ID, and
+ * the exclusive stacks have a netstackid that is the same as their zoneid.
+ */
+typedef id_t	netstackid_t;
+
+#define	GLOBAL_NETSTACKID	0
+
+/*
+ * One for each module which uses netstack support.
+ * Used in netstack_register().
+ *
+ * The order of these is important for some modules both for
+ * the creation (which done in ascending order) and destruction (which is
+ * done ine in decending order).
+ */
+#define	NS_ALL		-1	/* Match all */
+#define	NS_HOOK		0
+#define	NS_NETI		1
+#define	NS_ARP		2
+#define	NS_IP		3
+#define	NS_ICMP		4
+#define	NS_UDP		5
+#define	NS_TCP		6
+#define	NS_SCTP		7
+#define	NS_RTS		8
+#define	NS_IPSEC	9
+#define	NS_KEYSOCK	10
+#define	NS_SPDSOCK	11
+#define	NS_IPSECAH	12
+#define	NS_IPSECESP	13
+#define	NS_TUN		14
+#define	NS_IPF		15
+#define	NS_STR		16	/* autopush list etc */
+#define	NS_MAX		(NS_STR+1)
+
+/*
+ * One for every netstack in the system.
+ * We use a union so that the compilar and lint can provide type checking -
+ * in principle we could have
+ * #define	netstack_arp		netstack_modules[NS_ARP]
+ * etc, but that would imply void * types hence no type checking by the
+ * compiler.
+ *
+ * All the fields in netstack_t except netstack_next are protected by
+ * netstack_lock. netstack_next is protected by netstack_g_lock.
+ */
+struct netstack {
+	union {
+		void	*nu_modules[NS_MAX];
+		struct {
+			struct hook_stack	*nu_hook;
+			struct neti_stack	*nu_neti;
+			struct arp_stack	*nu_arp;
+			struct ip_stack		*nu_ip;
+			struct icmp_stack	*nu_icmp;
+			struct udp_stack	*nu_udp;
+			struct tcp_stack	*nu_tcp;
+			struct sctp_stack	*nu_sctp;
+			struct rts_stack	*nu_rts;
+			struct ipsec_stack	*nu_ipsec;
+			struct keysock_stack	*nu_keysock;
+			struct spd_stack	*nu_spdsock;
+			struct ipsecah_stack	*nu_ipsecah;
+			struct ipsecesp_stack	*nu_ipsecesp;
+			struct tun_stack	*nu_tun;
+			struct ipf_stack	*nu_ipf;
+			struct str_stack	*nu_str;
+		} nu_s;
+	} netstack_u;
+#define	netstack_modules	netstack_u.nu_modules
+#define	netstack_hook		netstack_u.nu_s.nu_hook
+#define	netstack_neti		netstack_u.nu_s.nu_neti
+#define	netstack_arp		netstack_u.nu_s.nu_arp
+#define	netstack_ip		netstack_u.nu_s.nu_ip
+#define	netstack_icmp		netstack_u.nu_s.nu_icmp
+#define	netstack_udp		netstack_u.nu_s.nu_udp
+#define	netstack_tcp		netstack_u.nu_s.nu_tcp
+#define	netstack_sctp		netstack_u.nu_s.nu_sctp
+#define	netstack_rts		netstack_u.nu_s.nu_rts
+#define	netstack_ipsec		netstack_u.nu_s.nu_ipsec
+#define	netstack_keysock	netstack_u.nu_s.nu_keysock
+#define	netstack_spdsock	netstack_u.nu_s.nu_spdsock
+#define	netstack_ipsecah	netstack_u.nu_s.nu_ipsecah
+#define	netstack_ipsecesp	netstack_u.nu_s.nu_ipsecesp
+#define	netstack_tun		netstack_u.nu_s.nu_tun
+#define	netstack_ipf		netstack_u.nu_s.nu_ipf
+#define	netstack_str		netstack_u.nu_s.nu_str
+
+	uint16_t	netstack_m_state[NS_MAX]; /* module state */
+
+	kmutex_t	netstack_lock;
+	struct netstack *netstack_next;
+	netstackid_t	netstack_stackid;
+	int		netstack_numzones;	/* Number of zones using this */
+	int		netstack_refcnt;	/* Number of hold-rele */
+	int		netstack_flags;	/* See below */
+};
+typedef struct netstack netstack_t;
+
+/* netstack_flags values */
+#define	NSF_UNINIT	0x01		/* Not initialized */
+#define	NSF_CLOSING	0x02		/* Going away */
+
+/*
+ * State for each module for each stack - netstack_m_state[moduleid]
+ * Keeps track of pending actions to avoid holding looks when
+ * calling into the create/shutdown/destroy functions in the module.
+ */
+#define	NSS_CREATE_NEEDED	0x0001
+#define	NSS_CREATE_INPROGRESS	0x0002
+#define	NSS_CREATE_COMPLETED	0x0004
+#define	NSS_SHUTDOWN_NEEDED	0x0010
+#define	NSS_SHUTDOWN_INPROGRESS	0x0020
+#define	NSS_SHUTDOWN_COMPLETED	0x0040
+#define	NSS_DESTROY_NEEDED	0x0100
+#define	NSS_DESTROY_INPROGRESS	0x0200
+#define	NSS_DESTROY_COMPLETED	0x0400
+
+#define	NSS_CREATE_ALL	\
+	(NSS_CREATE_NEEDED|NSS_CREATE_INPROGRESS|NSS_CREATE_COMPLETED)
+#define	NSS_SHUTDOWN_ALL	\
+	(NSS_SHUTDOWN_NEEDED|NSS_SHUTDOWN_INPROGRESS|NSS_SHUTDOWN_COMPLETED)
+#define	NSS_DESTROY_ALL	\
+	(NSS_DESTROY_NEEDED|NSS_DESTROY_INPROGRESS|NSS_DESTROY_COMPLETED)
+
+/*
+ * One for each of the NS_* values.
+ */
+struct netstack_registry {
+	int		nr_flags;	/* 0 if nothing registered */
+	void		*(*nr_create)(netstackid_t, netstack_t *);
+	void		(*nr_shutdown)(netstackid_t, void *);
+	void		(*nr_destroy)(netstackid_t, void *);
+};
+
+/* nr_flags values */
+#define	NRF_REGISTERED	0x01
+
+/*
+ * To support kstat_create_netstack() using kstat_add_zone we need
+ * to track both
+ *  - all zoneids that use the global/shared stack
+ *  - all kstats that have been added for the shared stack
+ */
+
+extern void netstack_init(void);
+extern void netstack_hold(netstack_t *);
+extern void netstack_rele(netstack_t *);
+extern netstack_t *netstack_find_by_cred(const cred_t *);
+extern netstack_t *netstack_find_by_stackid(netstackid_t);
+extern netstack_t *netstack_find_by_zoneid(zoneid_t);
+
+extern zoneid_t netstackid_to_zoneid(netstackid_t);
+extern netstackid_t zoneid_to_netstackid(zoneid_t);
+
+extern netstack_t *netstack_get_current(void);
+
+/*
+ * Register interest in changes to the set of netstacks.
+ * The createfn and destroyfn are required, but the shutdownfn can be
+ * NULL.
+ * Note that due to the current zsd implementation, when the create
+ * function is called the zone isn't fully present, thus functions
+ * like zone_find_by_* will fail, hence the create function can not
+ * use many zones kernel functions including zcmn_err().
+ */
+extern void	netstack_register(int,
+    void *(*)(netstackid_t, netstack_t *),
+    void (*)(netstackid_t, void *),
+    void (*)(netstackid_t, void *));
+extern void	netstack_unregister(int);
+extern kstat_t	*kstat_create_netstack(char *, int, char *, char *, uchar_t,
+    uint_t, uchar_t, netstackid_t);
+extern void	kstat_delete_netstack(kstat_t *, netstackid_t);
+
+/*
+ * Simple support for walking all the netstacks.
+ * The caller of netstack_next() needs to call netstack_rele() when
+ * done with a netstack.
+ */
+typedef	int	netstack_handle_t;
+
+extern void	netstack_next_init(netstack_handle_t *);
+extern void	netstack_next_fini(netstack_handle_t *);
+extern netstack_t	*netstack_next(netstack_handle_t *);
+
+#ifdef	__cplusplus
+}
+#endif
+
+
+#endif	/* _SYS_NETSTACK_H */
